Forum Linux.général /dev/fb0 apparement j'ai pas tout compris

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
4
5
juil.
2021

Bonjour à tous,

j'aimerai en écrivant directement dans /dev/fb0 éteindre mon écran, en realité mettre toutes les leds de mon écran à 0. J'ai donc fait ce code :

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <sched.h>
    #include <linux/fb.h>
    #include <sys/ioctl.h>

    int main(int argc, char const *argv[])
    {
        //set scheduler to max priority
        struct sched_param sch_param;
        sch_param.sched_priority = 99;

        if( sched_setscheduler(getpid(), SCHED_FIFO, &sch_param) < 0)
        {
            printf("error sched_setscheduler : %s\n", strerror(errno));
            return 1;
        }


        //get fd
        int fb_fd = open("/dev/fb0", O_RDWR);
        if ( fb_fd < 0)
        {
            printf("error open fb : %s\n", strerror(errno));
            return 1;
        }

        // Get fixed screen information
        struct fb_var_screeninfo vinfo;
        struct fb_fix_screeninfo finfo;
        if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) 
        {
            printf("error ioctl FBIOGET_FSCREENINFO : %s\n", strerror(errno));
            return 1;
        }

        // Get variable screen information
        if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) 
        {
            printf("error ioctl FBIOGET_VSCREENINFO : %s\n", strerror(errno));
            return 1;
        }

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

        // Figure out the size of the screen in bytes
        size_t screenSize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
        printf("screenSize = %li\n", screenSize);

        unsigned char* fb = mmap(NULL, screenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
        if ( fb == NULL)
        {
            printf("error mmap from fb : %s\n", strerror(errno));
            return 1;
        }
        printf("address from fb : %p\n", fb);

        int stop = 10000; // value initialize in random in order to stop the loop
        size_t count = screenSize/4;
        while (1)
        {
            int * tmp = (int*)fb;
            for (size_t i = 0; i < count; i++)
            {
                *tmp++ = 0;           
            }

            stop--;
            if(stop == 0)
                break;

        }

        return 0;
    }

Mon premier probleme c'est que l'écran ne s'éteind jamais, il n'y a meme pas un soupcon d'une baisse de luminosité, pourtant ce que je met ne m'a pas l'air si déconnant. j'ai meme mis à un moment de désespoir intense, la priorité de mon processus au max au cas ou, mais non rien.

Je suis étonné néanmoins par l'adresse que me retourne mmap, il ne me retourne jamais la meme adresse, j'en déduis donc qu'il s'agit d'une adresse virtuelle. Mais je pensais que /dev/fb0 retournait justement une adresse physique.

merci d'avance pour vos remarques et votre aide

  • # it works !!

    Posté par  . Évalué à 1.

    ok ca marche, j'ai basculé sur une console (ctrl+alt+F2), puis j'ai modifié le :
    *tmp++ = 0;
    en
    *tmp++ = 0x00FF0000 (transparency + RGB)

    et l'écran a basculé en rouge (mettre une sleep(1) juste avant la boucle car le terminal a tendance a ecrire des choses sur l'écran, notamment du noir)

    pour la seconde question, je comprend pas trop le fonctionnement de taper directement sur l'adresse physique mais via une adresse virtuelle

    • [^] # Re: it works !!

      Posté par  . Évalué à 2. Dernière modification le 06 juillet 2021 à 10:41.

      pour la seconde question, je comprend pas trop le fonctionnement de taper directement sur l'adresse physique mais via une adresse virtuelle

      En fait, tu cumules ;-)

      /dev/fb0 est un device bloc.

      • On peut l’ouvrir,
      • Il a une taille
      • faire des fseek dedans

      Le driver associé, contient des hook (crochet) pour intercepter les appels à open, read, write, _seek, etc.

      Lorsque tu fais un mmap, tu as aussi un hook dédié qui met en place la zone mémoire (c’est une déduction, si quelqu’un de plus expert que moi peut confirmer… infirmer aussi, même si ce ne serait pas sympas). Mais, potentiellement, le driver va t’autoriser à accéder à une zone restreinte, pas à l’ensemble du device. Donc, il va utiliser le driver mémoire pour programmer la MMU pour rediriger la page mémoire vers la vrai mémoire. Le fait que tu vois une adresse différente à chaque fois n’est pas un problème, c’est le contrôleur mémoire du CPU qui gère cette redirection.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.