Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Framebuffer VSync problem

By: a guest on Dec 16th, 2012  |  syntax: C  |  size: 5.51 KB  |  views: 101  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #include <string.h>
  6. #include <pthread.h>
  7. #include <unistd.h>
  8. #include <termios.h>
  9. #include <linux/fb.h>
  10. #include <sys/mman.h>
  11. #include <linux/input.h>
  12. #include <linux/keyboard.h>
  13. #include <linux/kd.h>
  14.  
  15. int arg = 0;
  16. int mfd = 0;
  17. int kfd = 0;
  18. size_t rb = 0;
  19. size_t rk = 0;
  20. struct input_event ev[64];
  21. struct input_event ev2[64];
  22. unsigned char data;
  23. int mouse_read = 0;
  24. unsigned char read_buffer[sizeof(struct input_event)*3];
  25.  
  26. int is_keyboard(int fd)
  27. {
  28.   int data;
  29.   if(ioctl(fd, KDGKBTYPE, &data) != 0)
  30.     return 0;
  31.  
  32.   return 1;
  33. }
  34.  
  35. void* handle_input_mouse(void *ptr)
  36. {
  37.   for(;;)
  38.     rb = read(mfd, ev, sizeof(ev));
  39.  
  40.   return NULL;
  41. }
  42.  
  43. void* handle_input_keyboard(void *ptr)
  44. {
  45.   while(1)
  46.     {
  47.       rk = read(kfd, &data, sizeof(data));
  48.     }
  49.   return NULL;
  50. }
  51.  
  52. int main()
  53. {
  54.   int fbfd = 0;
  55.   int ttyfd = 0;
  56.   int old_mode = -1;
  57.  
  58.   char *files_to_try[] = {"/dev/tty", "/dev/console", NULL};
  59.  
  60.   struct fb_var_screeninfo vinfo;
  61.   struct fb_fix_screeninfo finfo;
  62.  
  63.   struct termios config;
  64.   struct termios oldconfig;
  65.  
  66.   int squarex = 0, squarey = 0;
  67.  
  68.   long unsigned int screensize = 0;
  69.   unsigned char *fbp = NULL;
  70.   unsigned char *fbpbackup = NULL;
  71.   unsigned char *fbpdb = NULL;
  72.   int x = 0, y = 0;
  73.  
  74.   long int location = 0;
  75.   pthread_t input_mouse, input_keyboard;
  76.  
  77.   if((fbfd = open("/dev/fb0", O_RDWR)) == -1)
  78.     {
  79.       puts("Error: cannot open framebuffer device.");
  80.       exit(1);
  81.     }
  82.   puts("The framebuffer device was opened successfully.");
  83.  
  84.   if(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
  85.     {
  86.       puts("Error reading fixed information.");
  87.       exit(2);
  88.     }
  89.  
  90.   if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
  91.     {
  92.       puts("Error reading variable information.");
  93.       exit(3);
  94.     }
  95.  
  96.   if((mfd = open("/dev/input/event3", O_RDONLY, 0)) < 0)
  97.     {
  98.       puts("Erorr opening mouse.");
  99.       goto error;
  100.     }
  101.  
  102.   int i;
  103.   for(i = 0; files_to_try[i] != NULL; ++i)
  104.     {
  105.       kfd = open(files_to_try[i], O_RDONLY);
  106.       if(kfd < 0) continue;
  107.  
  108.       if(is_keyboard(kfd)) break;
  109.  
  110.       close(kfd);
  111.     }
  112.  
  113.   if(files_to_try[i] == NULL) return 1;
  114.  
  115.   if(ioctl(kfd, KDGKBMODE, &old_mode) != 0)
  116.     {
  117.       printf("Unable to query keyboard mode.\n");
  118.       goto error;
  119.     }
  120.  
  121.   if(ioctl(kfd, KDSKBMODE, K_MEDIUMRAW) != 0)
  122.     {
  123.       printf("Unable to set mediumraw mode.\n");
  124.       goto error;
  125.     }
  126.  
  127.  
  128.   char *ret = ttyname(STDIN_FILENO);
  129.   ttyfd = open(ret, O_RDWR | O_NOCTTY | O_NDELAY);
  130.  
  131.   if(ttyfd < 0)
  132.     {
  133.       puts("Failed to open tty");
  134.       exit(6);
  135.     }
  136.  
  137.   tcgetattr(ttyfd, &oldconfig);
  138.  
  139.   config = oldconfig;
  140.   config.c_iflag = 0;
  141.   config.c_lflag &= ~(ECHO | ICANON | ISIG);
  142.  
  143.   tcsetattr(ttyfd, TCSAFLUSH, &config);
  144.  
  145.   screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
  146.  
  147.   squarex = vinfo.xres/2 - 50;
  148.   squarey = vinfo.yres/2 - 50;
  149.  
  150.   fbp = (char*)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
  151.  
  152.   fbpbackup = (char*)malloc(screensize);
  153.   fbpdb = (char*)malloc(screensize);
  154.   memcpy(fbpbackup, fbp, screensize);
  155.  
  156.   if(fbp == MAP_FAILED)
  157.     {
  158.      
  159.       exit(4);
  160.     }
  161.  
  162.   printf("\e[?25l");
  163.   fflush(stdout);
  164.   int quit = 0;
  165.   int draw = 0;
  166.  
  167.  
  168.    
  169.   memset(fbpdb, 0x0, screensize);
  170.   for(x = squarex; x < squarex + 100; x++)
  171.     for(y = squarey; y < squarey + 100; y++)
  172.       {
  173.                 location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y + vinfo.yoffset) * finfo.line_length;
  174.                 *(fbpdb + location + 0) = 0x0;
  175.                 *(fbpdb + location + 1) = 0x0;
  176.                 *(fbpdb + location + 2) = 0xff;
  177.           }
  178.  
  179.   memcpy(fbp, fbpdb, screensize);
  180.  
  181.   pthread_create(&input_mouse, NULL, handle_input_mouse, NULL);
  182.   pthread_create(&input_keyboard, NULL, handle_input_keyboard, NULL);    
  183.   ioctl(fbfd, _IOW('F', 309, int), 1);
  184.  
  185.  
  186.   while(!quit)
  187.     {    
  188.       int result;
  189.  
  190.       draw = 0;
  191.       if(rb)
  192.                 {      
  193.                   for(i = 0; i < rb/sizeof(struct input_event); ++i)
  194.                         {
  195.                           struct input_event *currev = &ev[i];
  196.                           if(EV_REL == currev -> type)
  197.                                 {
  198.                                   if(currev -> code == REL_X)
  199.                                         squarex += currev -> value;
  200.                                   if(currev -> code == REL_Y)
  201.                                         squarey += currev -> value;
  202.  
  203.                                   if(squarey < 0) squarey = 0;
  204.                                   if(squarey + 100 > vinfo.yres) squarey = vinfo.yres - 100;
  205.  
  206.                                   if(squarex < 0) squarex = 0;
  207.                                   if(squarex + 100 > vinfo.xres) squarex = vinfo.xres - 100;
  208.  
  209.                                   draw = 1;
  210.                                 }
  211.                         }
  212.                 }
  213.  
  214.       rb = 0;
  215.  
  216.       if(rk)
  217.                 {
  218.                   if((data & 0x7F) == 1)
  219.                         {
  220.                           quit = 1;
  221.                           draw = 0;
  222.                           memset(fbp, 0x0, screensize);
  223.                         }
  224.                 }
  225.  
  226.       rk = 0;
  227.  
  228.           if(draw)
  229.                 {
  230.                   memset(fbpdb, 0x0, screensize);
  231.                   for(x = squarex; x < squarex + 100; x++)
  232.                         for(y = squarey; y < squarey + 100; y++)
  233.                           {
  234.                                 location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y + vinfo.yoffset) * finfo.line_length;
  235.                                 *(fbpdb + location + 0) = 0x0;
  236.                                 *(fbpdb + location + 1) = 0x0;
  237.                                 *(fbpdb + location + 2) = 0xff;
  238.                           }
  239.                   draw = 0;
  240.  
  241.  
  242.                   ioctl(fbfd, FBIO_WAITFORVSYNC, &arg);
  243.                   memcpy(fbp, fbpdb, screensize);
  244.                 }
  245.     }
  246.  
  247.   printf("\e[?25h");
  248.   fflush(stdout);
  249.  
  250.   memcpy(fbp, fbpbackup, screensize);
  251.   free(fbpbackup);
  252.   free(fbpdb);
  253.  
  254.   munmap(fbp, screensize);
  255.   close(fbfd);
  256.  
  257.   ioctl(kfd, KDSKBMODE, old_mode);
  258.   tcsetattr(ttyfd, TCSAFLUSH, &oldconfig);
  259.  
  260.   return 0;
  261.  
  262.  
  263.  error:
  264.  
  265.   if(old_mode != -1)
  266.     {
  267.       ioctl(kfd, KDSKBMODE, old_mode);
  268.       tcsetattr(ttyfd, TCSAFLUSH, &oldconfig);
  269.     }
  270.  
  271.   return 1;
  272.  
  273. }