linux - mmap/dev/fb0 失败,返回 "Invalid argument"

标签 linux linux-device-driver embedded-linux framebuffer

我有一个嵌入式系统,想直接使用/dev/fb0。作为第一个测试,我使用了一些基于找到的示例代码的代码 everywhere in the net and SO .打开成功,还有fstat之类的。但是 mmap 因 EINVAL 而失败。

来源:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

int main() {
    int fbfd = 0;

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    char *fbp = 0;
    int x = 0, y = 0;
    long int location = 0;

    // Open the file for reading and writing
    fbfd = open("/dev/fb0", O_RDWR);
    if (fbfd == -1) {
        perror("Error: cannot open framebuffer device");
        exit(1);
    }
    printf("The framebuffer device was opened successfully.\n");

    struct stat stat;
    fstat(fbfd, &stat);
    printf("/dev/mem -> size: %u blksize: %u blkcnt: %u\n", 
            stat.st_size, stat.st_blksize, stat.st_blocks);

    // Get fixed screen information
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
        perror("Error reading fixed information");
        exit(2);
    }

    // Get variable screen information
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
        perror("Error reading variable information");
        exit(3);
    }

    printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

    // Figure out the size of the screen in bytes
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    const int PADDING = 4096;
    int mmapsize = (screensize + PADDING - 1) & ~(PADDING-1);

    // Map the device to memory
    fbp = (char *)mmap(0, mmapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ((int)fbp == -1) {
        perror("Error: failed to map framebuffer device to memory");
        exit(4);
    }
    printf("The framebuffer device was mapped to memory successfully.\n");

    munmap(fbp, screensize);
    close(fbfd);

    return 0;
}

输出:

The framebuffer device was opened successfully.
/dev/mem -> size: 0 blksize: 4096 blkcnt: 0
640x480, 4bpp
Error: failed to map framebuffer device to memory: Invalid argument

跟踪:

...
open("/dev/fb0", O_RDWR)                = 3
write(1, "The framebuffer device was opene"..., 48The framebuffer device was opened successfully.
) = 48
fstat64(3, {st_mode=S_IFCHR|0640, st_rdev=makedev(29, 0), ...}) = 0
write(1, "/dev/mem -> size: 0 blksize: 409"..., 44/dev/mem -> size: 0 blksize: 4096 blkcnt: 0
) = 44
ioctl(3, FBIOGET_FSCREENINFO or FBIOPUT_CONTRAST, 0xbfca6564) = 0
ioctl(3, FBIOGET_VSCREENINFO, 0xbfca6600) = 0
write(1, "640x480, 4bpp\n", 14640x480, 4bpp
)         = 14
old_mmap(NULL, 155648, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = -1 EINVAL (Invalid argument)
write(2, "Error: failed to map framebuffer"..., 49Error: failed to map framebuffer device to memory) = 49
write(2, ": ", 2: )                       = 2
write(2, "Invalid argument", 16Invalid argument)        = 16
write(2, "\n", 1
)                       = 1

带有控制台和晚礼服的启动屏幕是可见的。 cat/dev/urandom >/dev/fb0 使屏幕充满噪音。系统上的页面大小为 4096 (`getconf PAGESIZE)。所以,155648 (0x26000) 是一个倍数。偏移量和指针都为零。映射和文件模式都是 RW ..我错过了什么?

这是针对使用 uClibc 和 busybox 运行单个应用程序构建的嵌入式设备,我必须从一个古老的内核中移植它。有画线等代码,不需要多处理/窗口..请不要提示 directfb ;)。

最佳答案

提供framebuffer 的内核驱动程序不支持framebuffer 设备的传统直接mmap();您需要使用较新的 DRMKMS 界面。

关于linux - mmap/dev/fb0 失败,返回 "Invalid argument",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22915778/

相关文章:

python - 在 vim 中安装 YouCompleteMe 时遇到 python 问题

linux - 从名称中包含版本的文件夹下载、提取和复制文件

linux - 流量转发

c# 将消息发送到 linux 上的本地 syslog 服务

linux - IORESOURCE_IRQ(地址)在soc芯片中如何工作?

Linux:在 board_init 函数中访问 i2c 设备

linux-kernel - 关于 dma_alloc_coherent 的一些问题

linux - 中断处理和用户空间通知

c - pthread_mutex_timedlock 没有超时

c - 重写旧版 cpufreq_driver 的 cpufreq_freq_table 初始化