1 /*-
2 * (MPSAFE)
3 *
4 * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
29 * $FreeBSD$
30 */
31
32 #include "opt_kbd.h"
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/conf.h>
37 #include <sys/consio.h>
38 #include <sys/fcntl.h>
39 #include <sys/kbio.h>
40 #include <sys/kernel.h>
41 #include <sys/limits.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/mutex.h>
46 #include <sys/poll.h>
47 #include <sys/proc.h>
48 #include <sys/queue.h>
49 #include <sys/event.h>
50 #include <sys/systm.h>
51 #include <sys/taskqueue.h>
52 #include <sys/uio.h>
53 #include <dev/misc/kbd/kbdreg.h>
54 #include <dev/misc/kbd/kbdtables.h>
55
56 #define KEYBOARD_NAME "kbdmux"
57
58 MALLOC_DECLARE(M_KBDMUX);
59 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
60
61 /*****************************************************************************
62 *****************************************************************************
63 ** Keyboard state
64 *****************************************************************************
65 *****************************************************************************/
66
67 #define KBDMUX_Q_SIZE 512 /* input queue size */
68
69 #define KBDMUX_LOCK_DECL_GLOBAL \
70 struct lock ks_lock
71
72 #define KBDMUX_SLEEP(s, f, d, t) \
73 lksleep(&(s)->f, &(s)->ks_lock, PCATCH, (d), (t))
74
75 #define KBDMUX_CALLOUT_INIT(s) \
76 callout_init_mp(&(s)->ks_timo)
77
78 #define KBDMUX_QUEUE_INTR(s) \
79 taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
80
81 /*
82 * kbdmux keyboard
83 */
84 struct kbdmux_kbd
85 {
86 keyboard_t *kbd; /* keyboard */
87 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
88 };
89
90 typedef struct kbdmux_kbd kbdmux_kbd_t;
91
92 /*
93 * kbdmux state
94 */
95 struct kbdmux_state
96 {
97 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
98 unsigned int ks_inq_start;
99 unsigned int ks_inq_length;
100 struct task ks_task; /* interrupt task */
101 struct callout ks_timo; /* timeout handler */
102 #define TICKS (hz) /* rate */
103
104 int ks_flags; /* flags */
105 #define COMPOSE (1 << 0) /* compose char flag */
106 #define POLLING (1 << 1) /* polling */
107 #define TASK (1 << 2) /* interrupt task queued */
108
109 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
110 int ks_state; /* state */
111 int ks_accents; /* accent key index (> 0) */
112 u_int ks_composed_char; /* composed char code */
113 u_char ks_prefix; /* AT scan code prefix */
114
115 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
116
117 KBDMUX_LOCK_DECL_GLOBAL;
118 };
119
120 typedef struct kbdmux_state kbdmux_state_t;
121
122 /*****************************************************************************
123 *****************************************************************************
124 ** Helper functions
125 *****************************************************************************
126 *****************************************************************************/
127
128 static task_fn_t kbdmux_kbd_intr;
129 static timeout_t kbdmux_kbd_intr_timo;
130 static kbd_callback_func_t kbdmux_kbd_event;
131
132 static void
133 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
134 {
135 unsigned int p;
136
137 if (state->ks_inq_length == KBDMUX_Q_SIZE)
138 return;
139
140 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
141 state->ks_inq[p] = c;
142 state->ks_inq_length++;
143 }
144
145 static int
146 kbdmux_kbd_getc(kbdmux_state_t *state)
147 {
148 unsigned char c;
149
150 if (state->ks_inq_length == 0)
151 return (-1);
152
153 c = state->ks_inq[state->ks_inq_start];
154 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
155 state->ks_inq_length--;
156
157 return (c);
158 }
159
160 /*
161 * Interrupt handler task
162 */
163 void
164 kbdmux_kbd_intr(void *xkbd, int pending)
165 {
166 keyboard_t *kbd = (keyboard_t *) xkbd;
167 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
168 KBD_LOCK_DECLARE;
169
170 KBD_LOCK(kbd); /* recursive so ok */
171 kbd_intr(kbd, NULL);
172 state->ks_flags &= ~TASK;
173 wakeup(&state->ks_task);
174 KBD_UNLOCK(kbd);
175 }
176
177 /*
178 * Schedule interrupt handler on timeout. Called with locked state.
179 */
180 void
181 kbdmux_kbd_intr_timo(void *xkbd)
182 {
183 keyboard_t *kbd = (keyboard_t *) xkbd;
184 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
185 KBD_LOCK_DECLARE;
186
187 KBD_LOCK(kbd);
188
189 if (callout_pending(&state->ks_timo)) {
190 KBD_UNLOCK(kbd);
191 return; /* callout was reset */
192 }
193
194 if (!callout_active(&state->ks_timo)) {
195 KBD_UNLOCK(kbd);
196 return; /* callout was stopped */
197 }
198
199 callout_deactivate(&state->ks_timo);
200
201 /* queue interrupt task if needed */
202 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
203 KBDMUX_QUEUE_INTR(state) == 0)
204 state->ks_flags |= TASK;
205
206 /* re-schedule timeout */
207 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, kbd);
208 KBD_UNLOCK(kbd);
209 }
210
211 /*
212 * Process event from one of our keyboards
213 */
214 static int
215 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
216 {
217 kbdmux_state_t *state = (kbdmux_state_t *) arg;
218
219 switch (event) {
220 case KBDIO_KEYINPUT: {
221 int c;
222
223 /*
224 * Read all chars from the keyboard
225 *
226 * Turns out that atkbd(4) check_char() method may return
227 * "true" while read_char() method returns NOKEY. If this
228 * happens we could stuck in the loop below. Avoid this
229 * by breaking out of the loop if read_char() method returns
230 * NOKEY.
231 */
232
233 while (kbd_check_char(kbd)) {
234 c = kbd_read_char(kbd, 0);
235 if (c == NOKEY)
236 break;
237 if (c == ERRKEY)
238 continue; /* XXX ring bell */
239 if (!KBD_IS_BUSY(kbd))
240 continue; /* not open - discard the input */
241
242 kbdmux_kbd_putc(state, c);
243 }
244
245 /* queue interrupt task if needed */
246 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
247 KBDMUX_QUEUE_INTR(state) == 0)
248 state->ks_flags |= TASK;
249
250 } break;
251
252 case KBDIO_UNLOADING: {
253 kbdmux_kbd_t *k;
254
255 SLIST_FOREACH(k, &state->ks_kbds, next)
256 if (k->kbd == kbd)
257 break;
258
259 if (k != NULL) {
260 kbd_release(k->kbd, &k->kbd);
261 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
262
263 k->kbd = NULL;
264
265 kfree(k, M_KBDMUX);
266 }
267
268 } break;
269
270 default:
271 return (EINVAL);
272 /* NOT REACHED */
273 }
274 return (0);
275 }
276
277 /****************************************************************************
278 ****************************************************************************
279 ** Keyboard driver
280 ****************************************************************************
281 ****************************************************************************/
282
283 static int kbdmux_configure(int flags);
284 static kbd_probe_t kbdmux_probe;
285 static kbd_init_t kbdmux_init;
286 static kbd_term_t kbdmux_term;
287 static kbd_intr_t kbdmux_intr;
288 static kbd_test_if_t kbdmux_test_if;
289 static kbd_enable_t kbdmux_enable;
290 static kbd_disable_t kbdmux_disable;
291 static kbd_read_t kbdmux_read;
292 static kbd_check_t kbdmux_check;
293 static kbd_read_char_t kbdmux_read_char;
294 static kbd_check_char_t kbdmux_check_char;
295 static kbd_ioctl_t kbdmux_ioctl;
296 static kbd_lock_t kbdmux_lock;
297 static kbd_clear_state_t kbdmux_clear_state;
298 static kbd_get_state_t kbdmux_get_state;
299 static kbd_set_state_t kbdmux_set_state;
300 static kbd_poll_mode_t kbdmux_poll;
301
302 static keyboard_switch_t kbdmuxsw = {
303 .probe = kbdmux_probe,
304 .init = kbdmux_init,
305 .term = kbdmux_term,
306 .intr = kbdmux_intr,
307 .test_if = kbdmux_test_if,
308 .enable = kbdmux_enable,
309 .disable = kbdmux_disable,
310 .read = kbdmux_read,
311 .check = kbdmux_check,
312 .read_char = kbdmux_read_char,
313 .check_char = kbdmux_check_char,
314 .ioctl = kbdmux_ioctl,
315 .lock = kbdmux_lock,
316 .clear_state = kbdmux_clear_state,
317 .get_state = kbdmux_get_state,
318 .set_state = kbdmux_set_state,
319 .get_fkeystr = genkbd_get_fkeystr,
320 .poll = kbdmux_poll,
321 .diag = genkbd_diag,
322 };
323
324 /*
325 * Return the number of found keyboards
326 */
327 static int
328 kbdmux_configure(int flags)
329 {
330 return (1);
331 }
332
333 /*
334 * Detect a keyboard
335 */
336 static int
337 kbdmux_probe(int unit, void *arg, int flags)
338 {
339 if (resource_disabled(KEYBOARD_NAME, unit))
340 return (ENXIO);
341
342 return (0);
343 }
344
345 /*
346 * Reset and initialize the keyboard (stolen from atkbd.c)
347 *
348 * Called without kbd lock held.
349 */
350 static int
351 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
352 {
353 kbdmux_state_t *state = NULL;
354 keymap_t *keymap = NULL;
355 accentmap_t *accmap = NULL;
356 fkeytab_t *fkeymap = NULL;
357 keyboard_t *kbd = NULL;
358 int error, needfree, fkeymap_size, delay[2];
359
360 if (*kbdp == NULL) {
361 *kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
362 state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
363 keymap = kmalloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
364 accmap = kmalloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
365 fkeymap = kmalloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
366 fkeymap_size = NELEM(fkey_tab);
367 needfree = 1;
368
369 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
370 (accmap == NULL) || (fkeymap == NULL)) {
371 error = ENOMEM;
372 goto bad;
373 }
374
375 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
376 KBDMUX_CALLOUT_INIT(state);
377 SLIST_INIT(&state->ks_kbds);
378 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
379 return (0);
380 } else {
381 kbd = *kbdp;
382 state = (kbdmux_state_t *) kbd->kb_data;
383 keymap = kbd->kb_keymap;
384 accmap = kbd->kb_accentmap;
385 fkeymap = kbd->kb_fkeytab;
386 fkeymap_size = kbd->kb_fkeytab_size;
387 needfree = 0;
388 }
389
390 if (!KBD_IS_PROBED(kbd)) {
391 /* XXX assume 101/102 keys keyboard */
392 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags,
393 KB_PRI_MUX, 0, 0);
394 bcopy(&key_map, keymap, sizeof(key_map));
395 bcopy(&accent_map, accmap, sizeof(accent_map));
396 bcopy(fkey_tab, fkeymap,
397 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
398 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
399 kbd->kb_data = (void *)state;
400
401 KBD_FOUND_DEVICE(kbd);
402 KBD_PROBE_DONE(kbd);
403
404 kbdmux_clear_state(kbd);
405 state->ks_mode = K_XLATE;
406 }
407
408 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
409 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
410
411 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
412
413 delay[0] = kbd->kb_delay1;
414 delay[1] = kbd->kb_delay2;
415 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
416
417 KBD_INIT_DONE(kbd);
418 }
419
420 if (!KBD_IS_CONFIGURED(kbd)) {
421 if (kbd_register(kbd) < 0) {
422 error = ENXIO;
423 goto bad;
424 }
425
426 KBD_CONFIG_DONE(kbd);
427
428 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, kbd);
429 }
430
431 return (0);
432 bad:
433 if (needfree) {
434 if (state != NULL)
435 kfree(state, M_KBDMUX);
436 if (keymap != NULL)
437 kfree(keymap, M_KBDMUX);
438 if (accmap != NULL)
439 kfree(accmap, M_KBDMUX);
440 if (fkeymap != NULL)
441 kfree(fkeymap, M_KBDMUX);
442 if (kbd != NULL) {
443 kfree(kbd, M_KBDMUX);
444 *kbdp = NULL; /* insure ref doesn't leak to caller */
445 }
446 }
447
448 return (error);
449 }
450
451 /*
452 * Finish using this keyboard
453 *
454 * NOTE: deregistration automatically unlocks lock.
455 */
456 static int
457 kbdmux_term(keyboard_t *kbd)
458 {
459 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
460 kbdmux_kbd_t *k;
461
462 /* kill callout */
463 callout_stop(&state->ks_timo);
464
465 /* wait for interrupt task */
466 while (state->ks_flags & TASK)
467 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
468
469 /* release all keyboards from the mux */
470 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
471 kbd_release(k->kbd, &k->kbd);
472 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
473
474 k->kbd = NULL;
475
476 kfree(k, M_KBDMUX);
477 }
478
479 kbd_unregister(kbd);
480
481 bzero(state, sizeof(*state));
482 kfree(state, M_KBDMUX);
483
484 kfree(kbd->kb_keymap, M_KBDMUX);
485 kfree(kbd->kb_accentmap, M_KBDMUX);
486 kfree(kbd->kb_fkeytab, M_KBDMUX);
487 kfree(kbd, M_KBDMUX);
488
489 return (0);
490 }
491
492 /*
493 * Keyboard interrupt routine
494 */
495 static int
496 kbdmux_intr(keyboard_t *kbd, void *arg)
497 {
498 int c;
499
500 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
501 /* let the callback function to process the input */
502 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
503 kbd->kb_callback.kc_arg);
504 } else {
505 /* read and discard the input; no one is waiting for input */
506 do {
507 c = kbdmux_read_char(kbd, FALSE);
508 } while (c != NOKEY);
509 }
510
511 return (0);
512 }
513
514 /*
515 * Test the interface to the device
516 */
517 static int
518 kbdmux_test_if(keyboard_t *kbd)
519 {
520 return (0);
521 }
522
523 /*
524 * Enable the access to the device; until this function is called,
525 * the client cannot read from the keyboard.
526 */
527 static int
528 kbdmux_enable(keyboard_t *kbd)
529 {
530 KBD_ACTIVATE(kbd);
531 return (0);
532 }
533
534 /*
535 * Disallow the access to the device
536 */
537 static int
538 kbdmux_disable(keyboard_t *kbd)
539 {
540 KBD_DEACTIVATE(kbd);
541 return (0);
542 }
543
544 /*
545 * Read one byte from the keyboard if it's allowed
546 */
547 static int
548 kbdmux_read(keyboard_t *kbd, int wait)
549 {
550 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
551 int c, ret;
552
553 do {
554 c = kbdmux_kbd_getc(state);
555 } while (c == -1 && wait);
556
557 if (c != -1)
558 kbd->kb_count++;
559
560 ret = (KBD_IS_ACTIVE(kbd)? c : -1);
561
562 return ret;
563 }
564
565 /*
566 * Check if data is waiting
567 */
568 static int
569 kbdmux_check(keyboard_t *kbd)
570 {
571 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
572 int ready;
573
574 if (!KBD_IS_ACTIVE(kbd))
575 return (FALSE);
576
577 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
578
579 return (ready);
580 }
581
582 /*
583 * Read char from the keyboard (stolen from atkbd.c)
584 *
585 * Note: We do not attempt to detect the case where no keyboards are
586 * present in the wait case. If the kernel is sitting at the
587 * debugger prompt we want someone to be able to plug in a keyboard
588 * and have it work, and not just panic or fall through or do
589 * something equally nasty.
590 */
591 static u_int
592 kbdmux_read_char(keyboard_t *kbd, int wait)
593 {
594 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
595 u_int action;
596 int scancode, keycode;
597
598 next_code:
599
600 /* do we have a composed char to return? */
601 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
602 action = state->ks_composed_char;
603 state->ks_composed_char = 0;
604 if (action > UCHAR_MAX) {
605 return (ERRKEY);
606 }
607 return (action);
608 }
609
610 /*
611 * See if there is something in the keyboard queue
612 */
613 scancode = kbdmux_kbd_getc(state);
614
615 if (scancode == -1) {
616 if (state->ks_flags & POLLING) {
617 kbdmux_kbd_t *k;
618
619 SLIST_FOREACH(k, &state->ks_kbds, next) {
620 while (kbd_check_char(k->kbd)) {
621 scancode = kbd_read_char(k->kbd, 0);
622 if (scancode == ERRKEY)
623 continue;
624 if (scancode == NOKEY)
625 break;
626 if (!KBD_IS_BUSY(k->kbd))
627 continue;
628 kbdmux_kbd_putc(state, scancode);
629 }
630 }
631
632 if (state->ks_inq_length > 0)
633 goto next_code;
634 if (wait)
635 goto next_code;
636 } else {
637 if (wait) {
638 KBDMUX_SLEEP(state, ks_task, "kbdwai", hz/10);
639 goto next_code;
640 }
641 }
642 return (NOKEY);
643 }
644
645 kbd->kb_count++;
646
647 /* return the byte as is for the K_RAW mode */
648 if (state->ks_mode == K_RAW)
649 return (scancode);
650
651 /* translate the scan code into a keycode */
652 keycode = scancode & 0x7F;
653 switch (state->ks_prefix) {
654 case 0x00: /* normal scancode */
655 switch(scancode) {
656 case 0xB8: /* left alt (compose key) released */
657 if (state->ks_flags & COMPOSE) {
658 state->ks_flags &= ~COMPOSE;
659 if (state->ks_composed_char > UCHAR_MAX)
660 state->ks_composed_char = 0;
661 }
662 break;
663 case 0x38: /* left alt (compose key) pressed */
664 if (!(state->ks_flags & COMPOSE)) {
665 state->ks_flags |= COMPOSE;
666 state->ks_composed_char = 0;
667 }
668 break;
669 case 0xE0:
670 case 0xE1:
671 state->ks_prefix = scancode;
672 goto next_code;
673 }
674 break;
675 case 0xE0: /* 0xE0 prefix */
676 state->ks_prefix = 0;
677 switch (keycode) {
678 case 0x1C: /* right enter key */
679 keycode = 0x59;
680 break;
681 case 0x1D: /* right ctrl key */
682 keycode = 0x5A;
683 break;
684 case 0x35: /* keypad divide key */
685 keycode = 0x5B;
686 break;
687 case 0x37: /* print scrn key */
688 keycode = 0x5C;
689 break;
690 case 0x38: /* right alt key (alt gr) */
691 keycode = 0x5D;
692 break;
693 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
694 keycode = 0x68;
695 break;
696 case 0x47: /* grey home key */
697 keycode = 0x5E;
698 break;
699 case 0x48: /* grey up arrow key */
700 keycode = 0x5F;
701 break;
702 case 0x49: /* grey page up key */
703 keycode = 0x60;
704 break;
705 case 0x4B: /* grey left arrow key */
706 keycode = 0x61;
707 break;
708 case 0x4D: /* grey right arrow key */
709 keycode = 0x62;
710 break;
711 case 0x4F: /* grey end key */
712 keycode = 0x63;
713 break;
714 case 0x50: /* grey down arrow key */
715 keycode = 0x64;
716 break;
717 case 0x51: /* grey page down key */
718 keycode = 0x65;
719 break;
720 case 0x52: /* grey insert key */
721 keycode = 0x66;
722 break;
723 case 0x53: /* grey delete key */
724 keycode = 0x67;
725 break;
726 /* the following 3 are only used on the MS "Natural" keyboard */
727 case 0x5b: /* left Window key */
728 keycode = 0x69;
729 break;
730 case 0x5c: /* right Window key */
731 keycode = 0x6a;
732 break;
733 case 0x5d: /* menu key */
734 keycode = 0x6b;
735 break;
736 case 0x5e: /* power key */
737 keycode = 0x6d;
738 break;
739 case 0x5f: /* sleep key */
740 keycode = 0x6e;
741 break;
742 case 0x63: /* wake key */
743 keycode = 0x6f;
744 break;
745 case 0x64: /* [JP106USB] backslash, underscore */
746 keycode = 0x73;
747 break;
748 default: /* ignore everything else */
749 goto next_code;
750 }
751 break;
752 case 0xE1: /* 0xE1 prefix */
753 /*
754 * The pause/break key on the 101 keyboard produces:
755 * E1-1D-45 E1-9D-C5
756 * Ctrl-pause/break produces:
757 * E0-46 E0-C6 (See above.)
758 */
759 state->ks_prefix = 0;
760 if (keycode == 0x1D)
761 state->ks_prefix = 0x1D;
762 goto next_code;
763 /* NOT REACHED */
764 case 0x1D: /* pause / break */
765 state->ks_prefix = 0;
766 if (keycode != 0x45)
767 goto next_code;
768 keycode = 0x68;
769 break;
770 }
771
772 /* XXX assume 101/102 keys AT keyboard */
773 switch (keycode) {
774 case 0x5c: /* print screen */
775 if (state->ks_flags & ALTS)
776 keycode = 0x54; /* sysrq */
777 break;
778 case 0x68: /* pause/break */
779 if (state->ks_flags & CTLS)
780 keycode = 0x6c; /* break */
781 break;
782 }
783
784 /* return the key code in the K_CODE mode */
785 if (state->ks_mode == K_CODE)
786 return (keycode | (scancode & 0x80));
787
788 /* compose a character code */
789 if (state->ks_flags & COMPOSE) {
790 switch (keycode | (scancode & 0x80)) {
791 /* key pressed, process it */
792 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
793 state->ks_composed_char *= 10;
794 state->ks_composed_char += keycode - 0x40;
795 if (state->ks_composed_char > UCHAR_MAX)
796 return (ERRKEY);
797 goto next_code;
798 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
799 state->ks_composed_char *= 10;
800 state->ks_composed_char += keycode - 0x47;
801 if (state->ks_composed_char > UCHAR_MAX)
802 return (ERRKEY);
803 goto next_code;
804 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
805 state->ks_composed_char *= 10;
806 state->ks_composed_char += keycode - 0x4E;
807 if (state->ks_composed_char > UCHAR_MAX)
808 return (ERRKEY);
809 goto next_code;
810 case 0x52: /* keypad 0 */
811 state->ks_composed_char *= 10;
812 if (state->ks_composed_char > UCHAR_MAX)
813 return (ERRKEY);
814 goto next_code;
815
816 /* key released, no interest here */
817 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
818 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
819 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
820 case 0xD2: /* keypad 0 */
821 goto next_code;
822
823 case 0x38: /* left alt key */
824 break;
825
826 default:
827 if (state->ks_composed_char > 0) {
828 state->ks_flags &= ~COMPOSE;
829 state->ks_composed_char = 0;
830 return (ERRKEY);
831 }
832 break;
833 }
834 }
835
836 /* keycode to key action */
837 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
838 &state->ks_state, &state->ks_accents);
839 if (action == NOKEY)
840 goto next_code;
841
842 return (action);
843 }
844
845 /*
846 * Check if char is waiting
847 */
848 static int
849 kbdmux_check_char(keyboard_t *kbd)
850 {
851 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
852 int ready;
853
854 if (!KBD_IS_ACTIVE(kbd))
855 return (FALSE);
856
857 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
858 ready = TRUE;
859 else
860 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
861
862 return (ready);
863 }
864
865 /*
866 * Keyboard ioctl's
867 */
868 static int
869 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
870 {
871 static int delays[] = {
872 250, 500, 750, 1000
873 };
874
875 static int rates[] = {
876 34, 38, 42, 46, 50, 55, 59, 63,
877 68, 76, 84, 92, 100, 110, 118, 126,
878 136, 152, 168, 184, 200, 220, 236, 252,
879 272, 304, 336, 368, 400, 440, 472, 504
880 };
881
882 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
883 kbdmux_kbd_t *k;
884 keyboard_info_t *ki;
885 int error = 0, mode;
886
887 if (state == NULL)
888 return (ENXIO);
889
890 switch (cmd) {
891 case KBADDKBD: /* add keyboard to the mux */
892 ki = (keyboard_info_t *) arg;
893
894 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
895 strcmp(ki->kb_name, "*") == 0) {
896 return (EINVAL); /* bad input */
897 }
898
899 SLIST_FOREACH(k, &state->ks_kbds, next)
900 if (k->kbd->kb_unit == ki->kb_unit &&
901 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
902 break;
903
904 if (k != NULL)
905 return (0); /* keyboard already in the mux */
906
907 k = kmalloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
908 if (k == NULL)
909 return (ENOMEM); /* out of memory */
910
911 k->kbd = kbd_get_keyboard(
912 kbd_allocate(
913 ki->kb_name,
914 ki->kb_unit,
915 (void *) &k->kbd,
916 kbdmux_kbd_event, (void *) state));
917 if (k->kbd == NULL) {
918 kfree(k, M_KBDMUX);
919 return (EINVAL); /* bad keyboard */
920 }
921
922 kbd_enable(k->kbd);
923 kbd_clear_state(k->kbd);
924
925 /* set K_RAW mode on slave keyboard */
926 mode = K_RAW;
927 error = kbd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
928 if (error == 0) {
929 /* set lock keys state on slave keyboard */
930 mode = state->ks_state & LOCK_MASK;
931 error = kbd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
932 }
933
934 if (error != 0) {
935 kbd_release(k->kbd, &k->kbd);
936 k->kbd = NULL;
937 kfree(k, M_KBDMUX);
938 return (error); /* could not set mode */
939 }
940
941 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
942 break;
943
944 case KBRELKBD: /* release keyboard from the mux */
945 ki = (keyboard_info_t *) arg;
946
947 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
948 strcmp(ki->kb_name, "*") == 0) {
949 return (EINVAL); /* bad input */
950 }
951
952 SLIST_FOREACH(k, &state->ks_kbds, next)
953 if (k->kbd->kb_unit == ki->kb_unit &&
954 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
955 break;
956
957 if (k != NULL) {
958 error = kbd_release(k->kbd, &k->kbd);
959 if (error == 0) {
960 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
961
962 k->kbd = NULL;
963
964 kfree(k, M_KBDMUX);
965 }
966 } else
967 error = ENXIO; /* keyboard is not in the mux */
968
969 break;
970
971 case KDGKBMODE: /* get kyboard mode */
972 *(int *)arg = state->ks_mode;
973 break;
974
975 case KDSKBMODE: /* set keyboard mode */
976 switch (*(int *)arg) {
977 case K_XLATE:
978 if (state->ks_mode != K_XLATE) {
979 /* make lock key state and LED state match */
980 state->ks_state &= ~LOCK_MASK;
981 state->ks_state |= KBD_LED_VAL(kbd);
982 }
983 /* FALLTHROUGH */
984
985 case K_RAW:
986 case K_CODE:
987 if (state->ks_mode != *(int *)arg) {
988 kbdmux_clear_state(kbd);
989 state->ks_mode = *(int *)arg;
990 }
991 break;
992
993 default:
994 error = EINVAL;
995 break;
996 }
997 break;
998
999 case KDGETLED: /* get keyboard LED */
1000 *(int *)arg = KBD_LED_VAL(kbd);
1001 break;
1002
1003 case KDSETLED: /* set keyboard LED */
1004 /* NOTE: lock key state in ks_state won't be changed */
1005 if (*(int *)arg & ~LOCK_MASK)
1006 return (EINVAL);
1007
1008 KBD_LED_VAL(kbd) = *(int *)arg;
1009
1010 /* KDSETLED on all slave keyboards */
1011 SLIST_FOREACH(k, &state->ks_kbds, next)
1012 kbd_ioctl(k->kbd, KDSETLED, arg);
1013 break;
1014
1015 case KDGKBSTATE: /* get lock key state */
1016 *(int *)arg = state->ks_state & LOCK_MASK;
1017 break;
1018
1019 case KDSKBSTATE: /* set lock key state */
1020 if (*(int *)arg & ~LOCK_MASK)
1021 return (EINVAL);
1022
1023 state->ks_state &= ~LOCK_MASK;
1024 state->ks_state |= *(int *)arg;
1025
1026 /* KDSKBSTATE on all slave keyboards */
1027 SLIST_FOREACH(k, &state->ks_kbds, next)
1028 kbd_ioctl(k->kbd, KDSKBSTATE, arg);
1029
1030 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1031 /* NOT REACHED */
1032
1033 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1034 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1035 if (cmd == KDSETREPEAT) {
1036 int i;
1037
1038 /* lookup delay */
1039 for (i = NELEM(delays) - 1; i > 0; i --)
1040 if (((int *)arg)[0] >= delays[i])
1041 break;
1042 mode = i << 5;
1043
1044 /* lookup rate */
1045 for (i = NELEM(rates) - 1; i > 0; i --)
1046 if (((int *)arg)[1] >= rates[i])
1047 break;
1048 mode |= i;
1049 } else
1050 mode = *(int *)arg;
1051
1052 if (mode & ~0x7f)
1053 return (EINVAL);
1054
1055 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1056 kbd->kb_delay2 = rates[mode & 0x1f];
1057
1058 /* perform command on all slave keyboards */
1059 SLIST_FOREACH(k, &state->ks_kbds, next)
1060 kbd_ioctl(k->kbd, cmd, arg);
1061 break;
1062
1063 case PIO_KEYMAP: /* set keyboard translation table */
1064 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1065 case PIO_DEADKEYMAP: /* set accent key translation table */
1066 state->ks_accents = 0;
1067
1068 /* perform command on all slave keyboards */
1069 SLIST_FOREACH(k, &state->ks_kbds, next)
1070 kbd_ioctl(k->kbd, cmd, arg);
1071 /* FALLTHROUGH */
1072
1073 default:
1074 error = genkbd_commonioctl(kbd, cmd, arg);
1075 break;
1076 }
1077 return (error);
1078 }
1079
1080 /*
1081 * Lock the access to the keyboard
1082 */
1083 static int
1084 kbdmux_lock(keyboard_t *kbd, int lock)
1085 {
1086 return (1); /* XXX */
1087 }
1088
1089 /*
1090 * Clear the internal state of the keyboard
1091 *
1092 * NOTE: May be called unlocked from init
1093 */
1094 static void
1095 kbdmux_clear_state(keyboard_t *kbd)
1096 {
1097 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1098
1099 state->ks_flags &= ~(COMPOSE|POLLING);
1100 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1101 state->ks_accents = 0;
1102 state->ks_composed_char = 0;
1103 /* state->ks_prefix = 0; XXX */
1104 state->ks_inq_length = 0;
1105 }
1106
1107 /*
1108 * Save the internal state
1109 */
1110 static int
1111 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1112 {
1113 if (len == 0)
1114 return (sizeof(kbdmux_state_t));
1115 if (len < sizeof(kbdmux_state_t))
1116 return (-1);
1117
1118 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1119
1120 return (0);
1121 }
1122
1123 /*
1124 * Set the internal state
1125 */
1126 static int
1127 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1128 {
1129 if (len < sizeof(kbdmux_state_t))
1130 return (ENOMEM);
1131
1132 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1133
1134 return (0);
1135 }
1136
1137 /*
1138 * Set polling
1139 *
1140 * Caller interlocks all keyboard calls. We must not lock here.
1141 */
1142 static int
1143 kbdmux_poll(keyboard_t *kbd, int on)
1144 {
1145 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1146 kbdmux_kbd_t *k;
1147
1148 if (on)
1149 state->ks_flags |= POLLING;
1150 else
1151 state->ks_flags &= ~POLLING;
1152
1153 /* set poll on slave keyboards */
1154 SLIST_FOREACH(k, &state->ks_kbds, next)
1155 kbd_poll(k->kbd, on);
1156
1157 return (0);
1158 }
1159
1160 /*****************************************************************************
1161 *****************************************************************************
1162 ** Module
1163 *****************************************************************************
1164 *****************************************************************************/
1165
1166 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1167
1168 static int
1169 kbdmux_modevent(module_t mod, int type, void *data)
1170 {
1171 keyboard_switch_t *sw;
1172 keyboard_t *kbd;
1173 int error;
1174
1175 switch (type) {
1176 case MOD_LOAD:
1177 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1178 break;
1179
1180 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1181 kbd_delete_driver(&kbdmux_kbd_driver);
1182 error = ENXIO;
1183 break;
1184 }
1185
1186 kbd = NULL;
1187
1188 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1189 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1190 kbd_delete_driver(&kbdmux_kbd_driver);
1191 break;
1192 }
1193
1194 #ifdef KBD_INSTALL_CDEV
1195 if ((error = kbd_attach(kbd)) != 0) {
1196 (*sw->term)(kbd);
1197 kbd_delete_driver(&kbdmux_kbd_driver);
1198 break;
1199 }
1200 #endif
1201
1202 if ((error = (*sw->enable)(kbd)) != 0) {
1203 (*sw->disable)(kbd);
1204 #ifdef KBD_INSTALL_CDEV
1205 kbd_detach(kbd);
1206 #endif
1207 (*sw->term)(kbd);
1208 kbd_delete_driver(&kbdmux_kbd_driver);
1209 break;
1210 }
1211 break;
1212
1213 case MOD_UNLOAD:
1214 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1215 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1216
1217 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1218 if (kbd != NULL) {
1219 (*sw->disable)(kbd);
1220 #ifdef KBD_INSTALL_CDEV
1221 kbd_detach(kbd);
1222 #endif
1223 (*sw->term)(kbd);
1224 kbd_delete_driver(&kbdmux_kbd_driver);
1225 }
1226 error = 0;
1227 break;
1228
1229 default:
1230 error = EOPNOTSUPP;
1231 break;
1232 }
1233 return (error);
1234 }
1235
1236 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
Cache object: e7610c09978e79470d4e90127800f0c4
|