Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * console TV application.  Uses a framebuffer device.
  3  *
  4  *   (c) 1998-2001 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  5  *
  6  */
  7 
  8 #include "config.h"
  9 
 10 #include <stdio.h>
 11 #include <stdlib.h>
 12 #include <string.h>
 13 #include <unistd.h>
 14 #include <time.h>
 15 #include <fcntl.h>
 16 #include <termios.h>
 17 #include <signal.h>
 18 #include <ctype.h>
 19 #include <errno.h>
 20 #include <sys/time.h>
 21 #include <sys/ioctl.h>
 22 #include <sys/types.h>
 23 #include <sys/mman.h>
 24 #include <curses.h>
 25 #include <math.h>
 26 #include <pthread.h>
 27 
 28 #include <linux/kd.h>
 29 #include <linux/fb.h>
 30 
 31 #include "grab-ng.h"
 32 #include "writefile.h"
 33 #include "sound.h"
 34 #include "channel.h"
 35 #include "frequencies.h"
 36 #include "commands.h"
 37 #include "capture.h"
 38 #include "lirc.h"
 39 #include "joystick.h"
 40 #include "midictrl.h"
 41 #include "event.h"
 42 
 43 #include "fbtools.h"
 44 #include "fs.h"
 45 #include "matrox.h"
 46 
 47 #define MAX(x,y)        ((x)>(y)?(x):(y))
 48 #define MIN(x,y)        ((x)<(y)?(x):(y))
 49 
 50 /* ---------------------------------------------------------------------- */
 51 /* framebuffer                                                            */
 52 
 53 static char  *fbdev    = NULL;
 54 static char  *fontfile = NULL;
 55 static char  *mode     = NULL;
 56 static char  *joydev   = NULL;
 57 static struct fs_font *f;
 58 #ifndef X_DISPLAY_MISSING
 59 static char *x11_font = "10x20";
 60 #endif
 61 
 62 static unsigned short red[256],  green[256],  blue[256];
 63 static struct fb_cmap cmap  = { 0, 256, red,  green,  blue };
 64 
 65 static int switch_last,fb;
 66 static int keep_dma_on = 0;
 67 
 68 static int sig,quiet,matrox;
 69 static int ww,hh;
 70 static float fbgamma = 1.0;
 71 
 72 static struct ng_video_buf   *buf;
 73 static struct ng_video_fmt   fmt,gfmt;
 74 static struct ng_video_conv  *conv;
 75 static struct ng_convert_handle *ch;
 76 static int dx,dy;
 77 
 78 int have_config;
 79 int x11_native_format,have_dga=1,debug;
 80 
 81 /*--- channels ------------------------------------------------------------*/
 82 
 83 struct event_entry kbd_events[] = {
 84     {
 85         .event  = "kbd-key-+",
 86         .action = "volume inc",
 87     },{
 88         .event  = "kbd-key--",
 89         .action = "volume dec",
 90     },{
 91         .event  = "kbd-key-enter",
 92         .action = "volume mute",
 93     },{
 94         .event  = "kbd-key-space",
 95         .action = "setstation next",
 96     },{
 97         .event  = "kbd-key-backspace",
 98         .action = "setstation back",
 99     },{
100         .event  = "kbd-key-pgup",
101         .action = "setstation next",
102     },{
103         .event  = "kbd-key-pgdown",
104         .action = "setstation prev",
105     },{
106         .event  = "kbd-key-right",
107         .action = "setchannel fine_up",
108     },{
109         .event  = "kbd-key-left",
110         .action = "setchannel fine_down",
111     },{
112         .event  = "kbd-key-up",
113         .action = "setchannel next",
114     },{
115         .event  = "kbd-key-down",
116         .action = "setchannel prev",
117     },{
118         .event  = "kbd-key-g",
119         .action = "snap ppm",
120     },{
121         .event  = "kbd-key-j",
122         .action = "snap jpeg",
123     },{
124         .event  = "kbd-key-v",
125         .action = "capture toggle",
126     },{
127         .event  = "kbd-key-f",
128         .action = "fullscreen toggle",
129     },{
130         .event  = "kbd-key-0",
131         .action = "keypad 0",
132     },{
133         .event  = "kbd-key-1",
134         .action = "keypad 1",
135     },{
136         .event  = "kbd-key-2",
137         .action = "keypad 2",
138     },{
139         .event  = "kbd-key-3",
140         .action = "keypad 3",
141     },{
142         .event  = "kbd-key-4",
143         .action = "keypad 4",
144     },{
145         .event  = "kbd-key-5",
146         .action = "keypad 5",
147     },{
148         .event  = "kbd-key-6",
149         .action = "keypad 6",
150     },{
151         .event  = "kbd-key-7",
152         .action = "keypad 7",
153     },{
154         .event  = "kbd-key-8",
155         .action = "keypad 8",
156     },{
157         .event  = "kbd-key-9",
158         .action = "keypad 9",
159     },{
160 
161         /* end of list */
162     }
163 };
164 struct KEYTAB {
165     int  key;
166     char *name;
167 };
168 
169 static struct KEYTAB keytab[] = {
170     { 9,             "tab"       },
171     { 10,            "enter"     },
172     { 13,            "enter"     },
173     { KEY_ENTER,     "enter"     },
174 
175     { ' ',           "space"     },
176     { KEY_BACKSPACE, "backspace" },
177 
178     { KEY_RIGHT,     "right"     },
179     { KEY_LEFT,      "left"      },
180     { KEY_UP,        "up"        },
181     { KEY_DOWN,      "down"      },
182     { KEY_PPAGE,     "pgup"      },
183     { KEY_NPAGE,     "pgdown"    },
184     { KEY_HOME,      "home"      },
185     { KEY_END,       "end"       },
186 };
187 
188 #define NKEYTAB (sizeof(keytab)/sizeof(struct KEYTAB))
189 
190 static char              *snapbase;
191 static char              default_title[128] = "???";
192 static char              message[128] = "";
193 
194 /* ---------------------------------------------------------------------- */
195 /* framebuffer stuff                                                      */
196 
197 static void
198 linear_palette(int bit)
199 {
200     int             i, size = 256 >> (8 - bit);
201 
202     for (i = 0; i < size; i++)
203         red[i] = green[i] = blue[i] = (unsigned short)(65535.0
204                 * pow(i/(size - 1.0), fbgamma));
205 }
206 
207 static void
208 dither_palette(int r, int g, int b)
209 {
210     int             rs, gs, bs, i;
211 
212     rs = 256 / (r - 1);
213     gs = 256 / (g - 1);
214     bs = 256 / (b - 1);
215     for (i = 0; i < r*g*b; i++) {
216         green[i+16] = (gs * ((i / (r * b)) % g)) * 255;
217         red[i+16]   = (rs * ((i / b) % r)) * 255;
218         blue[i+16]  = (bs * ((i) % b)) * 255;
219     }
220 }
221 
222 static void
223 fb_initcolors(int fd, int gray)
224 {
225     /* get colormap */
226     if (fb_var.bits_per_pixel == 8 ||
227         fb_fix.visual == FB_VISUAL_DIRECTCOLOR) {
228         if (-1 == ioctl(fd,FBIOGETCMAP,&cmap))
229             perror("ioctl FBIOGETCMAP");
230     }
231     
232     switch (fb_var.bits_per_pixel) {
233     case 8:
234         if (gray) {
235             linear_palette(8);
236             x11_native_format = VIDEO_GRAY;
237         } else {
238             dither_palette(5,9,5);
239             x11_native_format = VIDEO_RGB08;
240         }
241         break;
242     case 15:
243     case 16:
244         if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR)
245             linear_palette(5);
246 #if BYTE_ORDER == BIG_ENDIAN
247         x11_native_format = (fb_var.green.length == 6) ?
248             VIDEO_RGB16_BE : VIDEO_RGB15_BE;
249 #else
250         x11_native_format = (fb_var.green.length == 6) ?
251             VIDEO_RGB16_LE : VIDEO_RGB15_LE;
252 #endif
253         break;
254     case 24:
255         if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR)
256             linear_palette(8);
257 #if BYTE_ORDER == BIG_ENDIAN
258         x11_native_format = VIDEO_RGB24;
259 #else
260         x11_native_format = VIDEO_BGR24;
261 #endif
262         break;
263     case 32:
264         if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR)
265             linear_palette(8);
266 #if BYTE_ORDER == BIG_ENDIAN
267         x11_native_format = VIDEO_RGB32;
268 #else
269         x11_native_format = VIDEO_BGR32;
270 #endif
271         break;
272     default:
273         fprintf(stderr, "Oops: %i bit/pixel ???\n",
274                 fb_var.bits_per_pixel);
275         exit(1);
276     }
277 
278     /* set colormap */
279     if (fb_var.bits_per_pixel == 8 ||
280         fb_fix.visual == FB_VISUAL_DIRECTCOLOR) {
281         if (-1 == ioctl(fd,FBIOPUTCMAP,&cmap))
282             perror("ioctl FBIOPUTCMAP");
283     }
284 }
285 
286 static void
287 tty_init(void)
288 {
289     /* we use curses just for kbd input */
290     initscr();
291     cbreak();
292     noecho();
293     keypad(stdscr,1);
294 }
295 
296 static void
297 tty_cleanup(void)
298 {
299     clear();
300     refresh();
301     endwin();
302 }
303 
304 
305 /* ---------------------------------------------------------------------- */
306 
307 static void
308 text_init(char *font)
309 {
310     char   *fonts[2] = { font, NULL };
311 
312     if (NULL == f)
313         f = fs_consolefont(font ? fonts : NULL);
314 #ifndef X_DISPLAY_MISSING
315     if (NULL == f && 0 == fs_connect(NULL))
316         f = fs_open(font ? font : x11_font);
317 #endif
318     if (NULL == f) {
319         fprintf(stderr,"no font available\n");
320         exit(1);
321     }
322 }
323 
324 static void
325 text_out(int x, int y, char *str)
326 {
327     y *= f->height;
328     y -= f->fontHeader.max_bounds.descent;
329     fs_puts(f,x,y,str);
330 }
331 
332 static int
333 text_width(char *str)
334 {
335     return fs_textwidth(f,str);
336 }
337 
338 /* ---------------------------------------------------------------------- */
339 
340 #ifdef HAVE_ALSA
341 static struct midi_handle fb_midi;
342 #endif
343 
344 /* ---------------------------------------------------------------------- */
345 
346 static void
347 ctrlc(int signal)
348 {
349     sig=1;
350 }
351 
352 #if 0
353 void
354 change_audio(int mode)
355 {
356     if (grabber->grab_audio)
357         grabber->grab_audio(-1,-1,&mode);
358 }
359 #endif
360 
361 static void do_capture(int from, int to, int tmp_switch)
362 {
363     /* off */
364     switch (from) {
365     case CAPTURE_GRABDISPLAY:
366         if (f_drv & CAN_CAPTURE)
367             drv->stopvideo(h_drv);
368         break;
369     case CAPTURE_OVERLAY:
370         if (f_drv & CAN_CAPTURE)
371             drv->overlay(h_drv,NULL,0,0,NULL,0,0);
372         if (matrox && !tmp_switch)
373             gfx_scaler_off();
374         break;
375     }
376 
377     /* on */
378     memset(&buf,0,sizeof(buf));
379     switch (to) {
380     case CAPTURE_GRABDISPLAY:
381         if (ww && hh) {
382             dx  = fb_var.xres-fmt.width;
383             dy  = 0;
384             fmt.fmtid  = x11_native_format;
385             fmt.width  = ww;
386             fmt.height = hh;
387             fmt.bytesperline = fb_fix.line_length;
388         } else {
389             if (quiet) {
390                 dx  = 0;
391                 dy  = 0;
392             } else {
393                 dx  = f->height*3/2;
394                 dy  = f->height;
395             }
396             fmt.fmtid  = x11_native_format;
397             fmt.width  = fb_var.xres-dx;
398             fmt.height = fb_var.yres-dy;
399             fmt.bytesperline = fb_fix.line_length;
400         }
401         if (0 != ng_grabber_setformat(&fmt,1)) {
402             gfmt = fmt;
403             if (NULL == (conv = ng_grabber_findconv(&gfmt,0))) {
404                 fprintf(stderr,"can't fint useful capture format\n");
405                 exit(1);
406             }
407             ch = ng_convert_alloc(conv,&gfmt,&fmt);
408             ng_convert_init(ch);
409         }
410         dx += (fb_var.xres-24-fmt.width)/2;
411         dy += (fb_var.yres-16-fmt.height)/2;
412         
413         if (f_drv & CAN_CAPTURE)
414             drv->startvideo(h_drv,-1,2);
415         break;
416     case CAPTURE_OVERLAY:
417         fmt.fmtid  = x11_native_format;
418         if (ww && hh) {
419             fmt.width  = ww;
420             fmt.height = hh;
421             dx = fb_var.xres-fmt.width;
422             dy = 0;
423         } else if (quiet) {
424             fmt.width  = fb_var.xres;
425             fmt.height = fb_var.yres;
426             dx = 0;
427             dy = 0;
428         } else {
429             fmt.width  = fb_var.xres-24;
430             fmt.height = fb_var.yres-16;
431             dx = f->height*3/2;
432             dy = f->height;
433         }
434         if (matrox) {
435             struct ng_video_fmt off;
436             int starty;
437 #if 1
438             /* FIXME: need some kind of size negotiation */
439             /* hardcoded: PAL, half height (want no interleace) */
440             off.width  = 768;
441             off.height = 288;
442             starty = fb_var.yres;
443 #else
444             /* settings for debugging */
445             off.width  = 320;
446             off.height = 240;
447             starty = fb_var.yres-off.height;
448 #endif
449             off.bytesperline = fb_fix.line_length;
450             if (off.width*2 > off.bytesperline)
451                 off.width = off.bytesperline/2;
452             off.fmtid = VIDEO_YUYV;
453             drv->overlay(h_drv,&off,0,starty,NULL,0,0);
454             gfx_scaler_on(starty*off.bytesperline,off.bytesperline,
455                           off.width,off.height,
456                           dx,dx+fmt.width,
457                           dy,dy+fmt.height);
458         } else {
459             drv->overlay(h_drv,&fmt,dx,dy,NULL,0,1);
460         }
461         break;
462     }
463 }
464 
465 static void
466 do_exit(void)
467 {
468     sig = 1;
469 }
470 
471 static void
472 new_title(char *txt)
473 {
474     strcpy(default_title,txt);
475 }
476 
477 static void
478 new_message(char *txt)
479 {
480     strcpy(message,txt);
481 }
482 
483 static void
484 channel_menu(void)
485 {
486     char key[32],ctrl[16],event[64],action[128];
487     int  i;
488 
489     for (i = 0; i < count; i++) {
490         if (channels[i]->key) {
491             if (2 != sscanf(channels[i]->key,"%15[A-Za-z0-9_]+%31[A-Za-z0-9_]",
492                             ctrl,key))
493                 strcpy(key,channels[i]->key);
494             sprintf(event,"kbd-key-%s",key);
495             sprintf(action,"setstation \"%s\"",channels[i]->name);
496             event_register(event,action);
497         }
498     }
499 }
500 
501 static void
502 do_fullscreen(void)
503 {
504     do_va_cmd(2,"capture","off");
505     quiet = !quiet;
506     fb_memset(fb_mem+fb_mem_offset,0,fb_fix.smem_len);
507     do_va_cmd(2,"capture","on");
508 }
509 
510 /*--- main ---------------------------------------------------------------*/
511 
512 static void
513 grabber_init(void)
514 {
515     struct ng_video_fmt screen;
516 
517     memset(&screen,0,sizeof(screen));
518     screen.fmtid        = x11_native_format,
519     screen.width        = fb_var.xres_virtual;
520     screen.height       = fb_var.yres_virtual;
521     screen.bytesperline = fb_fix.line_length;
522     drv = ng_vid_open(ng_dev.video,NULL,&screen,0,&h_drv);
523     if (NULL == drv) {
524         fprintf(stderr,"no grabber device available\n");
525         exit(1);
526     }
527     f_drv = drv->capabilities(h_drv);
528     add_attrs(drv->list_attrs(h_drv));
529 }
530 
531 static void
532 console_switch(void)
533 {
534     switch (fb_switch_state) {
535     case FB_REL_REQ:
536         if (!keep_dma_on)
537             do_va_cmd(2,"capture","off");
538         switch_last = fb_switch_state;
539         fb_switch_release();
540         break;
541     case FB_ACQ_REQ:
542         switch_last = fb_switch_state;
543         fb_switch_acquire();
544         fb_memset(fb_mem+fb_mem_offset,0,fb_fix.smem_len);
545         ioctl(fb,FBIOPAN_DISPLAY,&fb_var);
546         do_va_cmd(2,"capture","on");
547         break;
548     case FB_ACTIVE:
549     case FB_INACTIVE:
550     default:
551         switch_last = fb_switch_state;
552         break;
553     }
554 }
555 
556 #if 0
557 /* just a hook for some test code */
558 static void
559 scaler_test(int off)
560 {
561     if (!matrox) {
562         matrox=1;
563         if (-1 == gfx_init(fb))
564             matrox = 0;
565     }
566 
567     if (matrox) {
568         gfx_scaler_on(0,fb_fix.line_length,320,240,
569                       fb_var.xres-320,fb_var.xres,0,240);
570         sleep(2);
571     }
572 }
573 #endif
574 
575 int
576 main(int argc, char *argv[])
577 {
578     int             i,key,c,gray=0,rc,vt=0,fps=0,t1,t2,lirc,js,err,mute=1,fdmax;
579     unsigned int    ui;
580     unsigned long   freq;
581     struct timeval  tv;
582     time_t          t;
583     char            text[80],event[64],*env,*dst;
584     fd_set          set;
585     struct sigaction act,old;
586 
587 
588     if (0 == geteuid() && 0 != getuid()) {
589         fprintf(stderr,"fbtv /must not/ be installed suid root\n");
590         exit(1);
591     }
592 
593     if (NULL != (env = getenv("FBFONT")))
594         fontfile = env;
595     ng_init();
596     for (;;) {
597         double val;
598         c = getopt(argc, argv, "Mgvqxkd:o:s:c:f:m:z:t:j:");
599         if (c == -1)
600             break;
601         switch (c) {
602         case 'z':
603             if(sscanf(optarg, "%lf", &val) == 1) {
604                 if(val < 0.1 || val > 10)
605                     fprintf(stderr, "gamma value is out of range.  must be "
606                             "0.1 < value < 10.0\n");
607                 else
608                     fbgamma = 1.0 / val;
609             }
610             break;
611         case 'f':
612             fontfile = optarg;
613             break;
614         case 'm':
615             mode = optarg;
616             break;
617         case 'g':
618             gray = 1;
619             break;
620         case 'M':
621             matrox = 1;
622             break;
623         case 'k':
624             keep_dma_on = 1;
625             break;
626         case 'v':
627             debug++;
628             ng_debug++;
629             break;
630         case 'q':
631             quiet = 1;
632             break;
633         case 'd':
634             fbdev = optarg;
635             break;
636         case 'o':
637             snapbase = strdup(optarg);
638             break;
639         case 's':
640             sscanf(optarg,"%dx%d",&ww,&hh);
641             break;
642         case 'c':
643             ng_dev.video = optarg;
644             /* v4l-conf needs this too */
645             strcat(ng_v4l_conf," -c ");
646             strcat(ng_v4l_conf,ng_dev.video);
647             break;
648         case 't':
649             if (optarg)
650                 vt = strtoul(optarg, 0, 0);
651             else
652                 vt = 0;
653             break;
654         case 'j':
655             joydev = optarg;
656             break;
657         default:
658             exit(1);
659         }
660     }
661 
662     do_overlay = 1;
663     text_init(fontfile);
664     fb = fb_init(fbdev,mode,vt);
665     fb_catch_exit_signals();
666     fb_initcolors(fb,gray);
667     fb_switch_init();
668     switch_last = fb_switch_state;
669     fs_init_fb(15);
670 
671     if (matrox)
672         if (-1 == gfx_init(fb))
673             matrox = 0;
674     if (matrox)
675         strcat(ng_v4l_conf," -y ");
676     
677     grabber_init();
678     freq_init();
679     read_config(NULL,NULL,NULL);
680     if (0 != strlen(mixerdev)) {
681         struct ng_attribute *attr;
682         if (NULL != (attr = ng_mix_init(mixerdev,mixerctl)))
683             add_attrs(attr);
684     }
685 
686     /* set hooks (command.c) */
687     update_title      = new_title;
688     display_message   = new_message;
689     set_capture_hook  = do_capture;
690     exit_hook         = do_exit;
691     fullscreen_hook   = do_fullscreen;
692 
693     tty_init();
694     memset(&act,0,sizeof(act));
695     act.sa_handler = ctrlc;
696     sigemptyset(&act.sa_mask);
697     sigaction(SIGINT,&act,&old);
698 
699     /* init hardware */
700     attr_init();
701     audio_on();
702     audio_init();
703 
704     /* build channel list */
705     parse_config();
706     channel_menu();
707 
708     init_overlay();
709     if (optind+1 == argc) {
710         do_va_cmd(2,"setstation",argv[optind]);
711     } else {
712         if ((f_drv & CAN_TUNE) && 0 != (freq = drv->getfreq(h_drv))) {
713             for (i = 0; i < chancount; i++)
714                 if (chanlist[i].freq == freq*1000/16) {
715                     do_va_cmd(2,"setchannel",chanlist[i].name);
716                     break;
717                 }
718         }
719         if (-1 == cur_channel) {
720             if (count > 0)
721                 do_va_cmd(2,"setstation","");
722             else
723                 set_defaults();
724         }
725     }
726 
727     /* keyboard, lirc + midi + joystick input support */
728     event_register_list(kbd_events);
729     lirc = lirc_tv_init();
730     js = joystick_tv_init(joydev);
731 #ifdef HAVE_ALSA
732     fb_midi.fd = -1;
733     if (midi) {
734         if (-1 != midi_open(&fb_midi, "fbtv"))
735             midi_connect(&fb_midi,midi);
736     }
737 #endif
738 
739     fb_memset(fb_mem+fb_mem_offset,0,fb_fix.smem_len);
740     for (;!sig;) {
741         if ((fb_switch_state == FB_ACTIVE || keep_dma_on) && !quiet) {
742             /* clear first lines */
743             fb_memset(fb_mem+fb_mem_offset,0,f->height*fb_fix.line_length);
744             if (message[0] != '\0') {
745                 strcpy(text,message);
746             } else {
747                 sprintf(text,"Framebuffer TV - %s",default_title);
748             }
749             /* debugging + preformance monitoring */
750             switch (cur_capture) {
751             case CAPTURE_GRABDISPLAY:
752                 sprintf(text+strlen(text), " - grab %d.%d fps",fps/5,(fps*2)%10);
753                 break;
754             }
755             text_out(0,0,text);
756 
757             if (dy > 0) {
758                 /* display time */
759                 time(&t);
760                 strftime(text,16,"%H:%M",localtime(&t));
761                 text_out(fb_var.xres - text_width(text) - f->width, 0, text);
762             }
763         }
764         if (switch_last != fb_switch_state)
765             console_switch();
766 
767         t1 = time(NULL);
768         fps = 0;
769         message[0] = '\0';
770         for (;!sig;) {
771             FD_ZERO(&set);
772             FD_SET(0,&set);
773             fdmax = 1;
774             if (lirc != -1) {
775                 FD_SET(lirc,&set);
776                 fdmax = MAX(fdmax,lirc+1);
777             }
778             if (js != -1) {
779                 FD_SET(js,&set);
780                 fdmax = MAX(fdmax,js+1);
781             }
782 #ifdef HAVE_ALSA
783             if (fb_midi.fd != -1) {
784                 FD_SET(fb_midi.fd,&set);
785                 fdmax = MAX(fdmax,fb_midi.fd+1);
786             }
787 #endif
788             if (cur_capture == CAPTURE_GRABDISPLAY &&
789                 (fb_switch_state == FB_ACTIVE || keep_dma_on)) {
790                 fps++;
791                 /* grab + convert frame */
792                 if (NULL == (buf = ng_grabber_grab_image(0))) {
793                     fprintf(stderr,"capturing image failed\n");
794                     exit(1);
795                 }
796                 if (ch)
797                     buf = ng_convert_frame(ch,NULL,buf);
798                 /* blit frame */
799                 dst = fb_mem +
800                     dy * fb_fix.line_length +
801                     dx * ((fb_var.bits_per_pixel+7)/8);
802                 for (ui = 0; ui < buf->fmt.height; ui++) {
803                     memcpy(dst, buf->data + ui*buf->fmt.bytesperline,
804                            buf->fmt.bytesperline);
805                     dst += fb_fix.line_length;
806                 }
807                 ng_release_video_buf(buf);
808                 tv.tv_sec  = 0;
809                 tv.tv_usec = 0;
810                 rc = select(fdmax,&set,NULL,NULL,&tv);
811             } else {
812                 tv.tv_sec  = 6;
813                 tv.tv_usec = 0;
814                 rc = select(fdmax,&set,NULL,NULL,&tv);
815             }
816             err = errno;
817             if (switch_last != fb_switch_state)
818                 console_switch();
819             if (-1 == rc  &&  EINTR == err) {
820                 FD_ZERO(&set);
821                 continue;
822             }
823             if (rc > 0)
824                 break;
825             t2 = time(NULL);
826             if (t2 - t1 >= 5) {
827                 keypad_timeout();
828                 break;
829             }
830         }
831 
832         if (FD_ISSET(0,&set)) {
833             /* keyboard input */
834             switch (key = getch()) {
835             case 27: /* ESC */
836             case 'q':
837             case 'Q':
838                 sig=1;
839                 break;
840             case 'x':
841             case 'X':
842                 sig=1;
843                 mute=0;
844                 break;
845             case -1:
846                 break;
847 
848 #if 0 /* debug */
849             case 'y':
850                 /* scaler_test(1); */
851                 do_va_cmd(2,"capture","off");
852                 do_va_cmd(2,"capture","grab");
853                 break;
854 #endif
855 
856             default:
857                 event[0] = 0;
858                 if (key > ' ' && key < 127) {
859                     /* as is */
860                     sprintf(event,"kbd-key-%c",key);
861                 } else if (key >= KEY_F(0) && key <= KEY_F(12)) {
862                     /* function keys */
863                     sprintf(event,"kbd-key-f%d",key - KEY_F(0));
864                 } else {
865                     /* other special keys */
866                     for (ui = 0; ui < NKEYTAB; ui++) {
867                         if (keytab[ui].key == key)
868                             break;
869                     }
870                     if (ui != NKEYTAB)
871                         sprintf(event,"kbd-key-%s",keytab[ui].name);
872                 }
873                 if (0 != event[0]) {
874                     event_dispatch(event);
875                 } else {
876                     sprintf(message,"unknown key: %d 0x%x ",key,key);
877                 }
878 
879             }
880         }  /* if (FD_ISSET(0,&set)) */
881 
882         if (lirc != -1 && FD_ISSET(lirc,&set)) {
883             /* lirc input */
884             if (-1 == lirc_tv_havedata()) {
885                 fprintf(stderr,"lirc: connection lost\n");
886                 close(lirc);
887                 lirc = -1;
888             }
889         }
890 
891         if (js != -1 && FD_ISSET(js,&set)) {
892             /* joystick input */
893             joystick_tv_havedata(js);
894         }
895 
896 #ifdef HAVE_ALSA
897         if (fb_midi.fd != -1 && FD_ISSET(fb_midi.fd,&set)) {
898             /* midi input */
899             midi_read(&fb_midi);
900             midi_translate(&fb_midi);
901         }
902 #endif
903     }
904     do_va_cmd(2,"capture","off");
905     if (mute)
906         audio_off();
907     drv->close(h_drv);
908     if (fb_switch_state == FB_ACTIVE)
909         fb_memset(fb_mem+fb_mem_offset,0,fb_fix.smem_len);
910     tty_cleanup();
911     fb_cleanup();
912     exit(0);
913 }
914 
  This page was automatically generated by the LXR engine.