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 cosmoff . É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 Anthony Jaguenaud . Évalué à 2. Dernière modification le 06 juillet 2021 à 10:41.
En fait, tu cumules ;-)
/dev/fb0 est un device bloc.
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.