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