Deleted Added
sdiff udiff text old ( 185724 ) new ( 186906 )
full compact
1/*-
2 * Copyright (C) 2008 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * $FreeBSD: head/sys/dev/adb/adb_kbd.c 185724 2008-12-06 23:26:02Z nwhitehorn $
26 */
27
28#include <sys/cdefs.h>
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/module.h>
32#include <sys/bus.h>
33#include <sys/conf.h>
34#include <sys/kbio.h>
35#include <sys/condvar.h>
36#include <sys/callout.h>
37#include <sys/kernel.h>
38
39#include <machine/bus.h>
40
41#include "opt_kbd.h"
42#include <dev/kbd/kbdreg.h>
43#include <dev/kbd/kbdtables.h>
44
45#include <vm/vm.h>
46#include <vm/pmap.h>
47
48#include "adb.h"
49
50#define KBD_DRIVER_NAME "akbd"
51
52#define AKBD_EMULATE_ATKBD 1
53
54static int adb_kbd_probe(device_t dev);
55static int adb_kbd_attach(device_t dev);
56static int adb_kbd_detach(device_t dev);
57static void akbd_repeat(void *xsc);
58
59static u_int adb_kbd_receive_packet(device_t dev, u_char status,
60 u_char command, u_char reg, int len, u_char *data);
61
62struct adb_kbd_softc {
63 keyboard_t sc_kbd;
64
65 device_t sc_dev;
66 struct mtx sc_mutex;
67 struct cv sc_cv;
68
69 int sc_mode;
70 int sc_state;
71
72 int have_led_control;
73
74 uint8_t buffer[8];
75 volatile int buffers;
76
77 struct callout sc_repeater;
78 int sc_repeatstart;
79 int sc_repeatcontinue;
80 uint8_t last_press;
81};
82
83static device_method_t adb_kbd_methods[] = {
84 /* Device interface */
85 DEVMETHOD(device_probe, adb_kbd_probe),
86 DEVMETHOD(device_attach, adb_kbd_attach),
87 DEVMETHOD(device_detach, adb_kbd_detach),
88 DEVMETHOD(device_shutdown, bus_generic_shutdown),
89 DEVMETHOD(device_suspend, bus_generic_suspend),
90 DEVMETHOD(device_resume, bus_generic_resume),
91
92 /* ADB interface */
93 DEVMETHOD(adb_receive_packet, adb_kbd_receive_packet),
94
95 { 0, 0 }
96};
97
98static driver_t adb_kbd_driver = {
99 "akbd",
100 adb_kbd_methods,
101 sizeof(struct adb_kbd_softc),
102};
103
104static devclass_t adb_kbd_devclass;
105
106DRIVER_MODULE(akbd, adb, adb_kbd_driver, adb_kbd_devclass, 0, 0);
107
108static const uint8_t adb_to_at_scancode_map[128] = { 30, 31, 32, 33, 35, 34,
109 44, 45, 46, 47, 0, 48, 16, 17, 18, 19, 21, 20, 2, 3, 4, 5, 7, 6, 13,
110 10, 8, 12, 9, 11, 27, 24, 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43,
111 51, 53, 49, 50, 52, 15, 57, 41, 14, 0, 1, 29, 0, 42, 58, 56, 97, 98,
112 100, 95, 0, 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 91, 89, 0, 74, 13, 0,
113 0, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73, 0, 0, 0, 63, 64, 65, 61,
114 66, 67, 0, 87, 0, 105, 0, 70, 0, 68, 0, 88, 0, 107, 102, 94, 96, 103,
115 62, 99, 60, 101, 59, 54, 93, 90, 0, 0 };
116
117/* keyboard driver declaration */
118static int akbd_configure(int flags);
119static kbd_probe_t akbd_probe;
120static kbd_init_t akbd_init;
121static kbd_term_t akbd_term;
122static kbd_intr_t akbd_interrupt;
123static kbd_test_if_t akbd_test_if;
124static kbd_enable_t akbd_enable;
125static kbd_disable_t akbd_disable;
126static kbd_read_t akbd_read;
127static kbd_check_t akbd_check;
128static kbd_read_char_t akbd_read_char;
129static kbd_check_char_t akbd_check_char;
130static kbd_ioctl_t akbd_ioctl;
131static kbd_lock_t akbd_lock;
132static kbd_clear_state_t akbd_clear_state;
133static kbd_get_state_t akbd_get_state;
134static kbd_set_state_t akbd_set_state;
135static kbd_poll_mode_t akbd_poll;
136
137keyboard_switch_t akbdsw = {
138 akbd_probe,
139 akbd_init,
140 akbd_term,
141 akbd_interrupt,
142 akbd_test_if,
143 akbd_enable,
144 akbd_disable,
145 akbd_read,
146 akbd_check,
147 akbd_read_char,
148 akbd_check_char,
149 akbd_ioctl,
150 akbd_lock,
151 akbd_clear_state,
152 akbd_get_state,
153 akbd_set_state,
154 genkbd_get_fkeystr,
155 akbd_poll,
156 genkbd_diag,
157};
158
159KEYBOARD_DRIVER(akbd, akbdsw, akbd_configure);
160
161static int
162adb_kbd_probe(device_t dev)
163{
164 uint8_t type;
165
166 type = adb_get_device_type(dev);
167
168 if (type != ADB_DEVICE_KEYBOARD)
169 return (ENXIO);
170
171 switch(adb_get_device_handler(dev)) {
172 case 1:
173 device_set_desc(dev,"Apple Standard Keyboard");
174 break;
175 case 2:
176 device_set_desc(dev,"Apple Extended Keyboard");
177 break;
178 case 4:
179 device_set_desc(dev,"Apple ISO Keyboard");
180 break;
181 case 5:
182 device_set_desc(dev,"Apple Extended ISO Keyboard");
183 break;
184 case 8:
185 device_set_desc(dev,"Apple Keyboard II");
186 break;
187 case 9:
188 device_set_desc(dev,"Apple ISO Keyboard II");
189 break;
190 case 12:
191 device_set_desc(dev,"PowerBook Keyboard");
192 break;
193 case 13:
194 device_set_desc(dev,"PowerBook ISO Keyboard");
195 break;
196 case 24:
197 device_set_desc(dev,"PowerBook Extended Keyboard");
198 break;
199 case 27:
200 device_set_desc(dev,"Apple Design Keyboard");
201 break;
202 case 195:
203 device_set_desc(dev,"PowerBook G3 Keyboard");
204 break;
205 case 196:
206 device_set_desc(dev,"iBook Keyboard");
207 break;
208 default:
209 device_set_desc(dev,"ADB Keyboard");
210 break;
211 }
212
213 return (0);
214}
215
216static int
217ms_to_ticks(int ms)
218{
219 if (hz > 1000)
220 return ms*(hz/1000);
221
222 return ms/(1000/hz);
223}
224
225static int
226adb_kbd_attach(device_t dev)
227{
228 struct adb_kbd_softc *sc;
229 keyboard_switch_t *sw;
230
231 sw = kbd_get_switch(KBD_DRIVER_NAME);
232 if (sw == NULL) {
233 return ENXIO;
234 }
235
236 sc = device_get_softc(dev);
237 sc->sc_dev = dev;
238 sc->sc_mode = K_RAW;
239 sc->sc_state = 0;
240 sc->have_led_control = 0;
241 sc->buffers = 0;
242
243 /* Try stepping forward to the extended keyboard protocol */
244 adb_set_device_handler(dev,3);
245
246 mtx_init(&sc->sc_mutex,KBD_DRIVER_NAME,MTX_DEF,0);
247 cv_init(&sc->sc_cv,KBD_DRIVER_NAME);
248 callout_init(&sc->sc_repeater, 0);
249
250#ifdef AKBD_EMULATE_ATKBD
251 kbd_init_struct(&sc->sc_kbd, KBD_DRIVER_NAME, KB_101, 0, 0, 0, 0);
252 kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab,
253 sizeof(fkey_tab) / sizeof(fkey_tab[0]));
254#else
255 #error ADB raw mode not implemented
256#endif
257
258 KBD_FOUND_DEVICE(&sc->sc_kbd);
259 KBD_PROBE_DONE(&sc->sc_kbd);
260 KBD_INIT_DONE(&sc->sc_kbd);
261 KBD_CONFIG_DONE(&sc->sc_kbd);
262
263 (*sw->enable)(&sc->sc_kbd);
264
265 kbd_register(&sc->sc_kbd);
266
267#ifdef KBD_INSTALL_CDEV
268 if (kbd_attach(&sc->sc_kbd)) {
269 adb_kbd_detach(dev);
270 return ENXIO;
271 }
272#endif
273
274 /* Check if we can read out the LED state from
275 this keyboard by reading the key state register */
276 if (adb_read_register(dev, 2, NULL) == 2)
277 sc->have_led_control = 1;
278
279 adb_set_autopoll(dev,1);
280
281 return (0);
282}
283
284static int
285adb_kbd_detach(device_t dev)
286{
287 struct adb_kbd_softc *sc;
288 keyboard_t *kbd;
289
290 sc = device_get_softc(dev);
291
292 adb_set_autopoll(dev,0);
293 callout_stop(&sc->sc_repeater);
294
295 mtx_lock(&sc->sc_mutex);
296
297 kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME,
298 device_get_unit(dev)));
299
300 kbdd_disable(kbd);
301
302#ifdef KBD_INSTALL_CDEV
303 kbd_detach(kbd);
304#endif
305
306 kbdd_term(kbd);
307
308 mtx_unlock(&sc->sc_mutex);
309
310 mtx_destroy(&sc->sc_mutex);
311 cv_destroy(&sc->sc_cv);
312
313 return (0);
314}
315
316static u_int
317adb_kbd_receive_packet(device_t dev, u_char status,
318 u_char command, u_char reg, int len, u_char *data)
319{
320 struct adb_kbd_softc *sc;
321
322 sc = device_get_softc(dev);
323
324 if (command != ADB_COMMAND_TALK)
325 return 0;
326
327 if (reg != 0 || len != 2)
328 return (0);
329
330 mtx_lock(&sc->sc_mutex);
331 if ((data[0] & 0x7f) == 57 && sc->buffers < 7) {
332 /* Fake the down/up cycle for caps lock */
333 sc->buffer[sc->buffers++] = data[0] & 0x7f;
334 sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7);
335 } else {
336 sc->buffer[sc->buffers++] = data[0];
337 }
338
339 if (sc->buffer[sc->buffers-1] < 0xff)
340 sc->last_press = sc->buffer[sc->buffers-1];
341
342 if ((data[1] & 0x7f) == 57 && sc->buffers < 7) {
343 /* Fake the down/up cycle for caps lock */
344 sc->buffer[sc->buffers++] = data[1] & 0x7f;
345 sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7);
346 } else {
347 sc->buffer[sc->buffers++] = data[1];
348 }
349
350 if (sc->buffer[sc->buffers-1] < 0xff)
351 sc->last_press = sc->buffer[sc->buffers-1];
352
353 /* Stop any existing key repeating */
354 callout_stop(&sc->sc_repeater);
355
356 /* Schedule a repeat callback on keydown */
357 if (!(sc->last_press & (1 << 7))) {
358 callout_reset(&sc->sc_repeater,
359 ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc);
360 }
361 mtx_unlock(&sc->sc_mutex);
362
363 cv_broadcast(&sc->sc_cv);
364
365 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
366 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
367 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
368 }
369
370 return (0);
371}
372
373static void
374akbd_repeat(void *xsc) {
375 struct adb_kbd_softc *sc = xsc;
376 int notify_kbd = 0;
377
378 /* Fake an up/down key repeat so long as we have the
379 free buffers */
380 mtx_lock(&sc->sc_mutex);
381 if (sc->buffers < 7) {
382 sc->buffer[sc->buffers++] = sc->last_press | (1 << 7);
383 sc->buffer[sc->buffers++] = sc->last_press;
384
385 notify_kbd = 1;
386 }
387 mtx_unlock(&sc->sc_mutex);
388
389 if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd)
390 && KBD_IS_BUSY(&sc->sc_kbd)) {
391 sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
392 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
393 }
394
395 /* Reschedule the callout */
396 callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2),
397 akbd_repeat, sc);
398}
399
400static int
401akbd_configure(int flags)
402{
403 return 0;
404}
405
406static int
407akbd_probe(int unit, void *arg, int flags)
408{
409 return 0;
410}
411
412static int
413akbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
414{
415 return 0;
416}
417
418static int
419akbd_term(keyboard_t *kbd)
420{
421 return 0;
422}
423
424static int
425akbd_interrupt(keyboard_t *kbd, void *arg)
426{
427 return 0;
428}
429
430static int
431akbd_test_if(keyboard_t *kbd)
432{
433 return 0;
434}
435
436static int
437akbd_enable(keyboard_t *kbd)
438{
439 KBD_ACTIVATE(kbd);
440 return (0);
441}
442
443static int
444akbd_disable(keyboard_t *kbd)
445{
446 struct adb_kbd_softc *sc;
447 sc = (struct adb_kbd_softc *)(kbd);
448
449 callout_stop(&sc->sc_repeater);
450 KBD_DEACTIVATE(kbd);
451 return (0);
452}
453
454static int
455akbd_read(keyboard_t *kbd, int wait)
456{
457 return (0);
458}
459
460static int
461akbd_check(keyboard_t *kbd)
462{
463 struct adb_kbd_softc *sc;
464
465 if (!KBD_IS_ACTIVE(kbd))
466 return (FALSE);
467
468 sc = (struct adb_kbd_softc *)(kbd);
469
470 mtx_lock(&sc->sc_mutex);
471 if (sc->buffers > 0) {
472 mtx_unlock(&sc->sc_mutex);
473 return (TRUE);
474 }
475 mtx_unlock(&sc->sc_mutex);
476
477 return (FALSE);
478}
479
480static u_int
481akbd_read_char(keyboard_t *kbd, int wait)
482{
483 struct adb_kbd_softc *sc;
484 uint8_t adb_code, final_scancode;
485 int i;
486
487 sc = (struct adb_kbd_softc *)(kbd);
488
489 mtx_lock(&sc->sc_mutex);
490 if (!sc->buffers && wait)
491 cv_wait(&sc->sc_cv,&sc->sc_mutex);
492
493 if (!sc->buffers) {
494 mtx_unlock(&sc->sc_mutex);
495 return (0);
496 }
497
498 adb_code = sc->buffer[0];
499
500 for (i = 1; i < sc->buffers; i++)
501 sc->buffer[i-1] = sc->buffer[i];
502
503 sc->buffers--;
504 mtx_unlock(&sc->sc_mutex);
505
506 #ifdef AKBD_EMULATE_ATKBD
507 final_scancode = adb_to_at_scancode_map[adb_code & 0x7f];
508 final_scancode |= adb_code & 0x80;
509 #else
510 final_scancode = adb_code;
511 #endif
512
513 return (final_scancode);
514}
515
516static int
517akbd_check_char(keyboard_t *kbd)
518{
519 if (!KBD_IS_ACTIVE(kbd))
520 return (FALSE);
521
522 return (akbd_check(kbd));
523}
524
525static int
526set_typematic(keyboard_t *kbd, int code)
527{
528 /* These numbers are in microseconds, so convert to ticks */
529
530 static int delays[] = { 250, 500, 750, 1000 };
531 static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63,
532 68, 76, 84, 92, 100, 110, 118, 126,
533 136, 152, 168, 184, 200, 220, 236, 252,
534 272, 304, 336, 368, 400, 440, 472, 504 };
535
536 if (code & ~0x7f)
537 return EINVAL;
538 kbd->kb_delay1 = delays[(code >> 5) & 3];
539 kbd->kb_delay2 = rates[code & 0x1f];
540 return 0;
541}
542
543static int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
544{
545 struct adb_kbd_softc *sc;
546 uint16_t r2;
547 int error;
548
549 sc = (struct adb_kbd_softc *)(kbd);
550 error = 0;
551
552 switch (cmd) {
553 case KDGKBMODE:
554 *(int *)data = sc->sc_mode;
555 break;
556 case KDSKBMODE:
557 switch (*(int *)data) {
558 case K_XLATE:
559 if (sc->sc_mode != K_XLATE) {
560 /* make lock key state and LED state match */
561 sc->sc_state &= ~LOCK_MASK;
562 sc->sc_state |= KBD_LED_VAL(kbd);
563 }
564 /* FALLTHROUGH */
565 case K_RAW:
566 case K_CODE:
567 if (sc->sc_mode != *(int *)data)
568 sc->sc_mode = *(int *)data;
569 break;
570 default:
571 error = EINVAL;
572 break;
573 }
574
575 break;
576
577 case KDGETLED:
578 *(int *)data = KBD_LED_VAL(kbd);
579 break;
580
581 case KDSKBSTATE:
582 if (*(int *)data & ~LOCK_MASK) {
583 error = EINVAL;
584 break;
585 }
586 sc->sc_state &= ~LOCK_MASK;
587 sc->sc_state |= *(int *)data;
588
589 /* FALLTHROUGH */
590
591 case KDSETLED:
592 KBD_LED_VAL(kbd) = *(int *)data;
593
594 if (!sc->have_led_control)
595 break;
596
597 r2 = (~0 & 0x04) | 3;
598
599 if (*(int *)data & NLKED)
600 r2 &= ~1;
601 if (*(int *)data & CLKED)
602 r2 &= ~2;
603 if (*(int *)data & SLKED)
604 r2 &= ~4;
605
606 adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2,
607 sizeof(uint16_t),(u_char *)&r2);
608
609 break;
610
611 case KDGKBSTATE:
612 *(int *)data = sc->sc_state & LOCK_MASK;
613 break;
614
615 case KDSETREPEAT:
616 if (!KBD_HAS_DEVICE(kbd))
617 return 0;
618 if (((int *)data)[1] < 0)
619 return EINVAL;
620 if (((int *)data)[0] < 0)
621 return EINVAL;
622 else if (((int *)data)[0] == 0) /* fastest possible value */
623 kbd->kb_delay1 = 200;
624 else
625 kbd->kb_delay1 = ((int *)data)[0];
626 kbd->kb_delay2 = ((int *)data)[1];
627
628 break;
629
630 case KDSETRAD:
631 error = set_typematic(kbd, *(int *)data);
632 break;
633
634 case PIO_KEYMAP:
635 case PIO_KEYMAPENT:
636 case PIO_DEADKEYMAP:
637 default:
638 return (genkbd_commonioctl(kbd, cmd, data));
639 }
640
641 return (error);
642}
643
644static int akbd_lock(keyboard_t *kbd, int lock)
645{
646 return (0);
647}
648
649static void akbd_clear_state(keyboard_t *kbd)
650{
651}
652
653static int akbd_get_state(keyboard_t *kbd, void *buf, size_t len)
654{
655 return (0);
656}
657
658static int akbd_set_state(keyboard_t *kbd, void *buf, size_t len)
659{
660 return (0);
661}
662
663static int akbd_poll(keyboard_t *kbd, int on)
664{
665 return (0);
666}
667
668static int
669akbd_modevent(module_t mod, int type, void *data)
670{
671 switch (type) {
672 case MOD_LOAD:
673 kbd_add_driver(&akbd_kbd_driver);
674 break;
675
676 case MOD_UNLOAD:
677 kbd_delete_driver(&akbd_kbd_driver);
678 break;
679
680 default:
681 return (EOPNOTSUPP);
682 }
683
684 return (0);
685}
686
687DEV_MODULE(akbd, akbd_modevent, NULL);
688