1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2 
3 #include <sys/consio.h>
4 #include <sys/time.h>
5 
6 #if __FreeBSD__ >= 5
7 #include <sys/mouse.h>
8 #define MOUSE_DEV "/dev/sysmouse"
9 #define PACKET_SIZE 8
10 #elif defined(PC98)
11 #define MOUSE_DEV "/dev/mse0"
12 #define PACKET_SIZE 5
13 #else
14 #define MOUSE_DEV "/dev/psm0"
15 #define PACKET_SIZE 3
16 #endif
17 
18 /* --- static variables --- */
19 
20 static keymap_t keymap;
21 static accentmap_t *accentmap;
22 
23 /* --- static functions --- */
24 
load_accentmap(void)25 static int load_accentmap(void) {
26   if (accentmap) {
27     return 1;
28   } else if ((accentmap = malloc(sizeof(*accentmap)))) { /* XXX Leadked */
29     ioctl(STDIN_FILENO, GIO_DEADKEYMAP, accentmap);
30 
31     return 1;
32   } else {
33     return 0;
34   }
35 }
36 
open_display(u_int depth)37 static int open_display(u_int depth) {
38   char *dev;
39   int vmode;
40   video_info_t vinfo;
41   video_adapter_info_t vainfo;
42   video_display_start_t vstart;
43   struct termios tm;
44 
45   bl_priv_restore_euid();
46   bl_priv_restore_egid();
47 
48   _display.fb_fd = open((dev = getenv("FRAMEBUFFER")) ? dev : "/dev/ttyv0", O_RDWR);
49 
50   bl_priv_change_euid(bl_getuid());
51   bl_priv_change_egid(bl_getgid());
52 
53   if (_display.fb_fd < 0) {
54     bl_error_printf("Couldn't open %s.\n", dev ? dev : "/dev/ttyv0");
55 
56     return 0;
57   }
58 
59   bl_file_set_cloexec(_display.fb_fd);
60 
61 #ifdef PC98
62   /* XXX 256 colors is not supported for now. */
63 #if 0
64   if (depth == 8) {
65     ioctl(_display.fb_fd, SW_PC98_PEGC640x400, NULL);
66   } else
67 #endif
68   {
69     ioctl(_display.fb_fd, SW_PC98_EGC640x400, NULL);
70   }
71 #endif
72 
73   ioctl(_display.fb_fd, FBIO_GETMODE, &vmode);
74 
75   vinfo.vi_mode = vmode;
76   ioctl(_display.fb_fd, FBIO_MODEINFO, &vinfo);
77   ioctl(_display.fb_fd, FBIO_ADPINFO, &vainfo);
78   ioctl(_display.fb_fd, FBIO_GETDISPSTART, &vstart);
79 
80   if ((_display.fb = _display.fb_base = mmap(NULL, (_display.smem_len = vainfo.va_window_size), PROT_WRITE | PROT_READ,
81                           MAP_SHARED, _display.fb_fd, (off_t)0)) == MAP_FAILED) {
82     bl_error_printf("Retry another mode of resolution and depth.\n");
83 
84     goto error;
85   }
86 
87   _disp.depth = vinfo.vi_depth;
88 
89   if ((_display.bytes_per_pixel = (_disp.depth + 7) / 8) == 3) {
90     _display.bytes_per_pixel = 4;
91   }
92 
93   if (_disp.depth < 15) {
94 #ifdef M_PC98_EGC640x400
95     if (vainfo.va_mode == M_PC98_EGC640x400) {
96       _display.pixels_per_byte = 8;
97       _disp.depth = 4;
98       _display.shift_0 = 7;
99       _display.mask = 1;
100       _display.plane_offset[0] = 0;       /* 0xA8000 */
101       _display.plane_offset[1] = 0x8000;  /* 0xB0000 */
102       _display.plane_offset[2] = 0x10000; /* 0xB8000 */
103       _display.plane_offset[3] = 0x38000; /* 0xE0000 */
104     } else
105 #endif
106     if (_disp.depth < 8) {
107 #ifdef ENABLE_2_4_PPB
108       _display.pixels_per_byte = 8 / _disp.depth;
109 #else
110       /* XXX Forcibly set 1 bpp */
111       _display.pixels_per_byte = 8;
112       _disp.depth = 1;
113 #endif
114 
115       _display.shift_0 = FB_SHIFT_0(_display.pixels_per_byte, _disp.depth);
116       _display.mask = FB_MASK(_display.pixels_per_byte);
117     } else {
118       _display.pixels_per_byte = 1;
119     }
120 
121     if (!cmap_init()) {
122       goto error;
123     }
124   } else {
125     _display.pixels_per_byte = 1;
126   }
127 
128 #ifdef ENABLE_DOUBLE_BUFFER
129   if (_display.pixels_per_byte > 1 && !(_display.back_fb = malloc(_display.smem_len))) {
130     cmap_final();
131 
132     goto error;
133   }
134 #endif
135 
136   _display.line_length = vainfo.va_line_width;
137   _display.xoffset = vstart.x;
138   _display.yoffset = vstart.y;
139 
140   _display.width = _disp.width = vinfo.vi_width;
141   _display.height = _disp.height = vinfo.vi_height;
142 
143   _display.rgbinfo.r_limit = 8 - vinfo.vi_pixel_fsizes[0];
144   _display.rgbinfo.g_limit = 8 - vinfo.vi_pixel_fsizes[1];
145   _display.rgbinfo.b_limit = 8 - vinfo.vi_pixel_fsizes[2];
146   _display.rgbinfo.r_offset = vinfo.vi_pixel_fields[0];
147   _display.rgbinfo.g_offset = vinfo.vi_pixel_fields[1];
148   _display.rgbinfo.b_offset = vinfo.vi_pixel_fields[2];
149 
150   tcgetattr(STDIN_FILENO, &tm);
151   orig_tm = tm;
152   tm.c_iflag = tm.c_oflag = 0;
153   tm.c_cflag &= ~CSIZE;
154   tm.c_cflag |= CS8;
155   tm.c_lflag &= ~(ECHO | ISIG | IEXTEN | ICANON);
156   tm.c_cc[VMIN] = 1;
157   tm.c_cc[VTIME] = 0;
158   tcsetattr(STDIN_FILENO, TCSAFLUSH, &tm);
159 
160   ioctl(STDIN_FILENO, GIO_KEYMAP, &keymap);
161   ioctl(STDIN_FILENO, KDSKBMODE, K_CODE);
162   ioctl(STDIN_FILENO, KDGKBSTATE, &_display.lock_state);
163 
164   _display.fd = STDIN_FILENO;
165 
166   _disp.display = &_display;
167 
168   bl_priv_restore_euid();
169   bl_priv_restore_egid();
170   _mouse.fd = open(MOUSE_DEV, O_RDWR | O_NONBLOCK);
171   bl_priv_change_euid(bl_getuid());
172   bl_priv_change_egid(bl_getgid());
173 
174   if (_mouse.fd != -1) {
175     struct mouse_info info;
176 #ifdef MOUSE_SETLEVEL
177     int level;
178     mousemode_t mode;
179 
180     level = 1;
181     ioctl(_mouse.fd, MOUSE_SETLEVEL, &level);
182     ioctl(_mouse.fd, MOUSE_GETMODE, &mode);
183 
184     if (mode.packetsize != PACKET_SIZE) {
185 #ifdef DEBUG
186       bl_debug_printf(BL_DEBUG_TAG " Failed to open " MOUSE_DEV ".\n");
187 #endif
188       close(_mouse.fd);
189       _mouse.fd = -1;
190     } else
191 #endif
192     {
193       bl_file_set_cloexec(_mouse.fd);
194 
195       _mouse.x = _display.width / 2;
196       _mouse.y = _display.height / 2;
197       _disp_mouse.display = (Display*)&_mouse;
198 
199       tcgetattr(_mouse.fd, &tm);
200       tm.c_iflag = IGNBRK | IGNPAR;
201       tm.c_oflag = 0;
202       tm.c_lflag = 0;
203       tm.c_cc[VTIME] = 0;
204       tm.c_cc[VMIN] = 1;
205       tm.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL;
206       cfsetispeed(&tm, B1200);
207       cfsetospeed(&tm, B1200);
208       tcsetattr(_mouse.fd, TCSAFLUSH, &tm);
209 
210       info.operation = MOUSE_HIDE;
211       ioctl(STDIN_FILENO, CONS_MOUSECTL, &info);
212     }
213   }
214 #ifdef DEBUG
215   else {
216     bl_debug_printf(BL_DEBUG_TAG " Failed to open " MOUSE_DEV ".\n");
217   }
218 #endif
219 
220   return 1;
221 
222 error:
223   if (_display.fb) {
224     munmap(_display.fb, _display.smem_len);
225     _display.fb = _display.fb_base = NULL;
226   }
227 
228   close(_display.fb_fd);
229 
230   return 0;
231 }
232 
receive_mouse_event(void)233 static int receive_mouse_event(void) {
234   u_char buf[PACKET_SIZE * 8];
235   ssize_t len;
236 
237   while ((len = read(_mouse.fd, buf, sizeof(buf))) > 0) {
238     static u_char packet[PACKET_SIZE];
239     static ssize_t packet_len;
240     ssize_t count;
241 
242     for (count = 0; count < len; count++) {
243       int x;
244       int y;
245       int move;
246       struct timeval tv;
247       XButtonEvent xev;
248       ui_window_t *win;
249 
250 #if __FreeBSD__ >= 5
251       int z;
252 
253       if (packet_len == 0) {
254         if ((buf[count] & 0xf8) != 0x80) {
255           /* is not packet header */
256           continue;
257         }
258       }
259 #endif
260 
261       packet[packet_len++] = buf[count];
262 
263       if (packet_len < PACKET_SIZE) {
264         continue;
265       }
266 
267       packet_len = 0;
268 
269       /* set mili seconds */
270       gettimeofday(&tv, NULL);
271       xev.time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
272 
273 #if __FreeBSD__ >= 5
274       x = (char)packet[1] + (char)packet[3];
275       y = (char)packet[2] + (char)packet[4];
276       z = ((char)(packet[5] << 1) + (char)(packet[6] << 1)) >> 1;
277 #else
278       x = (char)packet[1];
279       y = (char)packet[2];
280 #ifndef PC98
281       /* XXX */
282       if (packet[0] & 0x40) {
283         if (packet[0] & 0x10) {
284           x -= 128;
285         } else {
286           x += 128;
287         }
288       }
289 
290       if (packet[0] & 0x80) {
291         if (packet[0] & 0x20) {
292           y -= 128;
293         } else {
294           y += 128;
295         }
296       }
297 #endif
298 #endif
299 
300       move = 0;
301 
302       if (x != 0) {
303         restore_hidden_region();
304 
305         _mouse.x += x;
306 
307         if (_mouse.x < 0) {
308           _mouse.x = 0;
309         } else if (_display.width <= _mouse.x) {
310           _mouse.x = _display.width - 1;
311         }
312 
313         move = 1;
314       }
315 
316       if (y != 0) {
317         restore_hidden_region();
318 
319         _mouse.y -= y;
320 
321         if (_mouse.y < 0) {
322           _mouse.y = 0;
323         } else if (_display.height <= _mouse.y) {
324           _mouse.y = _display.height - 1;
325         }
326 
327         move = 1;
328       }
329 
330       if (move) {
331         update_mouse_cursor_state();
332       }
333 
334 #if __FreeBSD__ >= 5
335       if (~packet[0] & 0x04) {
336         xev.button = Button1;
337         _mouse.button_state = Button1Mask;
338       } else if (~packet[0] & 0x02) {
339         xev.button = Button2;
340         _mouse.button_state = Button2Mask;
341       } else if (~packet[0] & 0x01) {
342         xev.button = Button3;
343         _mouse.button_state = Button3Mask;
344       } else if (z < 0) {
345         xev.button = Button4;
346         _mouse.button_state = Button4Mask;
347       } else if (z > 0) {
348         xev.button = Button5;
349         _mouse.button_state = Button5Mask;
350       }
351 #elif defined(PC98)
352       if ((packet[0] & 0x4) == 0) {
353         xev.button = Button1;
354         _mouse.button_state = Button1Mask;
355       } else if ((packet[0] & 0x2) == 0) {
356         xev.button = Button2;
357         _mouse.button_state = Button2Mask;
358       } else if ((packet[0] & 0x01) == 0) {
359         xev.button = Button3;
360         _mouse.button_state = Button3Mask;
361       }
362 #else
363       if (packet[0] & 0x1) {
364         xev.button = Button1;
365         _mouse.button_state = Button1Mask;
366       } else if (packet[0] & 0x4) {
367         xev.button = Button2;
368         _mouse.button_state = Button2Mask;
369       } else if (packet[0] & 0x02) {
370         xev.button = Button3;
371         _mouse.button_state = Button3Mask;
372       }
373 #endif
374       else {
375         xev.button = 0;
376       }
377 
378       if (move) {
379         xev.type = MotionNotify;
380         xev.state = _mouse.button_state | _display.key_state;
381       } else {
382         if (xev.button) {
383           xev.type = ButtonPress;
384         } else {
385           xev.type = ButtonRelease;
386 
387           if (_mouse.button_state & Button1Mask) {
388             xev.button = Button1;
389           } else if (_mouse.button_state & Button2Mask) {
390             xev.button = Button2;
391           } else if (_mouse.button_state & Button3Mask) {
392             xev.button = Button3;
393           } else if (_mouse.button_state & Button4Mask) {
394             xev.button = Button4;
395           } else if (_mouse.button_state & Button5Mask) {
396             xev.button = Button5;
397           }
398 
399           /* Reset button_state in releasing button */
400           _mouse.button_state = 0;
401         }
402 
403         xev.state = _display.key_state;
404       }
405 
406       if (rotate_display) {
407         if (rotate_display > 0) {
408           xev.x = _mouse.y;
409           xev.y = _display.width - _mouse.x - 1;
410         } else {
411           xev.x = _display.height - _mouse.y - 1;
412           xev.y = _mouse.x;
413         }
414       } else {
415         xev.x = _mouse.x;
416         xev.y = _mouse.y;
417       }
418 
419 #ifdef __DEBUG
420       bl_debug_printf(
421           BL_DEBUG_TAG "Button is %s x %d y %d btn %d time %u\n",
422           xev.type == ButtonPress ? "pressed" : xev.type == MotionNotify ? "motion" : "released",
423           xev.x, xev.y, xev.button, xev.time);
424 #endif
425 
426       if (!check_virtual_kbd(&xev)) {
427         win = get_window(xev.x, xev.y);
428         xev.x -= win->x;
429         xev.y -= win->y;
430 
431         ui_window_receive_event(win, &xev);
432       }
433 
434       if (move) {
435         save_hidden_region();
436         draw_mouse_cursor();
437       }
438     }
439   }
440 
441   return 1;
442 }
443 
444 /* http://kaworu.jpn.org/doc/FreeBSD/jman.ORG/man4/keyboard.4.php */
receive_key_event(void)445 static int receive_key_event(void) {
446   u_char code;
447 
448   while (read(_display.fd, &code, 1) == 1) {
449     static int dead;
450     XKeyEvent xev;
451     int pressed;
452     int idx;
453     int key_state = _display.key_state;
454 
455     if (code & 0x80) {
456       pressed = 0;
457       code &= 0x7f;
458     } else {
459       pressed = 1;
460     }
461 
462     if (code >= keymap.n_keys) {
463       continue;
464     }
465 
466     if (keymap.key[code].flgs & 2) {
467       /* The key should react on num-lock(2). (Keypad keys) */
468 
469       int kcode;
470 
471       if ((kcode = keymap.key[code].map[0]) != 0 && pressed) {
472         /*
473          * KEY_KP0 etc are 0x100 larger than KEY_INSERT etc to
474          * distinguish them.
475          * (see ui.h)
476          */
477         xev.ksym = kcode + 0x200;
478 
479         goto send_event;
480       } else {
481         continue;
482       }
483     }
484 
485     if (_display.key_state) {
486       /* CommandMask is ignored. */
487 
488       idx = (_display.key_state & ShiftMask);
489       if (_display.key_state & ControlMask) {
490         idx |= 2;
491       }
492       if (_display.key_state & Mod2Mask) { /* ALTGR */
493         idx |= 4;
494       }
495     } else {
496       idx = 0;
497     }
498 
499     if (!(keymap.key[code].spcl & (1 << (7 - idx)))) {
500       /* Character keys */
501 
502       if (pressed) {
503         if ((keymap.key[code].flgs & 1) && (_display.lock_state & CLKED)) {
504           /* xor shift bit(1) */
505           idx ^= 1;
506         }
507 
508 #if 1
509         if (code == 41) {
510           xev.ksym = XK_Zenkaku_Hankaku;
511         } else if (code == 121) {
512           xev.ksym = XK_Henkan_Mode;
513         } else if (code == 123) {
514           xev.ksym = XK_Muhenkan;
515         } else if (code == 28) {
516           /*
517            * Always convert code 28 to XK_Return
518            *
519            * key[28].map[0] (Normal)     -> 0xd
520            * key[28].map[1] (Shift)      -> 0xd
521            * key[28].map[2] (Control)    -> 0xa
522            * key[28].map[3] (Shift+Ctrl) -> 0xa
523            */
524           xev.ksym = XK_Return;
525         } else
526 #endif
527         {
528           xev.ksym = keymap.key[code].map[idx];
529           if (xev.ksym >= 0x100) {
530             /* Unicode */
531             xev.ksym += 0x1000; /* See ui_window_get_str() in ui_window.c */
532           } else if ((_display.key_state & Mod2Mask) /* ALTRIGHT */ &&
533                      /*
534                       * e.g.) German keyboard
535                       *       Alt + ( -> [
536                       *       map[0] = (, map[idx] = [
537                       */
538                      keymap.key[code].map[idx] != keymap.key[code].map[0]) {
539             key_state &= ~ModMask;
540           }
541         }
542 
543         if (dead) {
544           if ('a' <= (xev.ksym | 0x20) && (xev.ksym | 0x20) <= 'z') {
545             if (load_accentmap()) {
546               struct acc_t *acc = &accentmap->acc[dead - F_ACC];
547 
548               if (acc->accchar) {
549                 int count;
550 
551                 for (count = 0; count < NUM_ACCENTCHARS; count++) {
552                   if (acc->map[count][0] == 0) {
553                     break;
554                   } else if (acc->map[count][0] == xev.ksym) {
555                     xev.ksym = acc->map[count][1];
556                     break;
557                   }
558                 }
559               }
560             }
561           }
562 
563           dead = 0;
564         }
565 
566         goto send_event;
567       }
568     } else {
569       /* Function keys */
570 
571       int kcode;
572 
573       if ((kcode = keymap.key[code].map[0]) == 0) {
574         /* do nothing */
575       } else if (pressed) {
576         int kcode2 = keymap.key[code].map[idx];
577 
578         if (F_ACC <= kcode2 && kcode2 <= L_ACC) {
579           dead = kcode2;
580         } else {
581           dead = 0;
582 
583           if (kcode == KEY_RIGHTSHIFT || kcode == KEY_LEFTSHIFT) {
584             _display.key_state |= ShiftMask;
585           } else if (kcode == KEY_RIGHTCTRL || kcode == KEY_LEFTCTRL) {
586             _display.key_state |= ControlMask;
587           } else if (kcode == KEY_RIGHTALT) {
588             _display.key_state |= (Mod1Mask|Mod2Mask);
589           } else if (kcode == KEY_LEFTALT) {
590             _display.key_state |= Mod1Mask;
591           } else if (kcode == KEY_NUMLOCK) {
592             _display.lock_state ^= NLKED;
593           } else if (kcode == KEY_CAPSLOCK) {
594             _display.lock_state ^= CLKED;
595           } else {
596             xev.ksym = kcode + 0x100;
597 
598             goto send_event;
599           }
600         }
601       } else {
602         if (kcode == KEY_RIGHTSHIFT || kcode == KEY_LEFTSHIFT) {
603           _display.key_state &= ~ShiftMask;
604         } else if (kcode == KEY_RIGHTCTRL || kcode == KEY_LEFTCTRL) {
605           _display.key_state &= ~ControlMask;
606         } else if (kcode == KEY_RIGHTALT) {
607           _display.key_state &= ~(Mod1Mask|Mod2Mask);
608         } else if (kcode == KEY_LEFTALT) {
609           _display.key_state &= ~Mod1Mask;
610         }
611       }
612     }
613 
614     continue;
615 
616   send_event:
617     xev.type = KeyPress;
618     xev.state = _mouse.button_state | key_state /* Don't use _display.key_state */ ;
619     xev.keycode = code;
620 
621 #ifdef __DEBUG
622     bl_debug_printf(BL_DEBUG_TAG "scancode %d -> ksym 0x%x state 0x%x\n", code, xev.ksym,
623                     xev.state);
624 #endif
625 
626     receive_event_for_multi_roots(&xev);
627   }
628 
629   return 1;
630 }
631