Как получить цвет пикселя из фреймбуфера в Linux (Raspberry Pi)

Я пытаюсь сделать небольшую программу для управления цветом светодиода RGB в соответствии с цветом определенных пикселей на экране. Поскольку это на Raspberry Pi с Raspbmc, я не могу использовать XLib, потому что все рисуется из буфера кадров (не уверен, что это правда, но из того, что я прочитал в FAQ, похоже, это так). Я пытался использовать XLib, но не смог обнаружить дисплей (имеет смысл, почему он сейчас не работает).

Это пример, который я нашел в Интернете. Проблема в том, что компилируется нормально, но при запуске появляется второе сообщение об ошибке: "Ошибка чтения фиксированной информации". Я попытался отобразить содержимое fbfd, но это приводит к ошибке сегментации. Получается, в fbfd ничего не пишется?

Я не могу понять это, потому что все, что я нахожу о буфере кадра, в основном представляет собой один и тот же код, поэтому я не знаю, почему он не работает.

Надеюсь, кто-то может помочь!

#include <unistd.h>
#include <fcntl.h>        /* for fcntl */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>        /* for mmap */
#include <sys/ioctl.h>
#include <linux/fb.h>

#include <stdio.h>
#include <stdlib.h>

int main() {
    long int screensize = 0;    
    int fbfd =0;                    /* frame buffer file descriptor */
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    char* fbp;                    /* pointer to framebuffer */
    int location;                    /* iterate to location */

    int x, y;                    /* x and y location */

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

    /* get the fixed screen information */
    if (ioctl (fbfd, FBIOGET_FSCREENINFO, &finfo)) {
        printf("Error reading fixed information.\n");
        exit(2);
    }

    /* get variable screen information */
    if (ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
        printf("Error reading variable information.\n");
        exit(3);
    }

    /* figure out the size of the screen in bytes */
    //screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

    /* map the device to memory */
    fbp = (char*)mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);

    if ((int)fbp == -1) {
        printf ("Error: failed to map framebuffer device to memory.\n");
        exit(4);
    }
    printf ("Framebuffer device was mapped to memory successfully.\n");

    // Figure out where in memory to put the pixel
    for ( y = 0; y < (vinfo.yres/2); y++ )
        for ( x = 0; x < vinfo.xres; x++ ) { 
            location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
            if ( vinfo.bits_per_pixel == 32 ) { 
                *(fbp + location) = 100; // Some blue 
                *(fbp + location + 1) = 15+(x-100)/2; // A little green 
                *(fbp + location + 2) = 200-(y-100)/5; // A lot of red
                *(fbp + location + 3) = 0; // No transparency 
            } else { //assume 16bpp 
                int b = 10; int g = (x-100)/6; // A little green 
                int r = 31-(y-100)/16; // A lot of red 
                unsigned short int t = r<<11 | g << 5 | b; 
                *((unsigned short int*)(fbp + location)) = t; 
            }
        }
    munmap(fbp, screensize);
    close(fbfd);

    return 0;
}

person Gordon13    schedule 23.10.2013    source источник
comment
попробуйте прочитать это введите здесь описание ссылки   -  person Stan Khalipa    schedule 22.06.2016
comment
Я не удивлен, что это не работает, это выглядит старым. В настоящее время вам нужно запросить фреймбуфер у графического процессора. Вы отправляете конкретное сообщение в конкретный почтовый ящик с указателем на структуру, содержащую информацию о том, что вы хотите, и, если вам повезет, это работает. Тогда он работает как обычный фреймбуфер, возможно не на /dev/fb0, я думаю, вы получили указатель. Но вам нужны барьеры памяти и все такое, потому что процессор взаимодействует с графическим процессором, и вы должны синхронизировать его. Это звучит как что-то от i386. ioctl? Нет. Пока не знаю, поэтому и гуглю, но это неправильно.   -  person Alan Corey    schedule 03.02.2019
comment
На самом деле это сработало. Но под Raspbian на Pi 3B. Я думаю, что в Linux есть драйвер кадрового буфера, который должен получать информацию от графического процессора. Попробуйте fbset, мой правильно считывает размер и глубину экрана. Если у вас есть /etc/fb.modes, он должен показать режимы, которые он может использовать.   -  person Alan Corey    schedule 03.02.2019
comment
Вероятно, у вас где-то есть bcm2708_fb.c или он встроен в ваше ядро. Это авторское право Broadcom, и я думаю, что это заставляет фреймбуфер Pi работать как традиционный фреймбуфер, открывая /dev/fb0 и т. д. Ищите фреймбуфер на raspberrypi.org/forums там много всего, и инженеры тоже участвуют в форуме.   -  person Alan Corey    schedule 03.02.2019