adb_kbd.c revision 226449
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 226449 2011-10-16 21:01:42Z 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#include <sys/sysctl.h>
39
40#include <machine/bus.h>
41
42#include "opt_kbd.h"
43#include <dev/kbd/kbdreg.h>
44#include <dev/kbd/kbdtables.h>
45#include <dev/ofw/openfirm.h>
46#include <dev/ofw/ofw_bus.h>
47
48#include <vm/vm.h>
49#include <vm/pmap.h>
50
51#include "adb.h"
52
53#define KBD_DRIVER_NAME "akbd"
54
55#define AKBD_EMULATE_ATKBD 1
56
57static int adb_kbd_probe(device_t dev);
58static int adb_kbd_attach(device_t dev);
59static int adb_kbd_detach(device_t dev);
60static void akbd_repeat(void *xsc);
61static int adb_fn_keys(SYSCTL_HANDLER_ARGS);
62
63static u_int adb_kbd_receive_packet(device_t dev, u_char status,
64	u_char command, u_char reg, int len, u_char *data);
65
66struct adb_kbd_softc {
67	keyboard_t sc_kbd;
68
69	device_t sc_dev;
70	struct mtx sc_mutex;
71	struct cv  sc_cv;
72
73	int sc_mode;
74	int sc_state;
75
76	int have_led_control;
77
78	uint8_t buffer[8];
79#ifdef AKBD_EMULATE_ATKBD
80	uint8_t at_buffered_char[2];
81#endif
82	volatile int buffers;
83
84	struct callout sc_repeater;
85	int sc_repeatstart;
86	int sc_repeatcontinue;
87	uint8_t last_press;
88};
89
90static device_method_t adb_kbd_methods[] = {
91	/* Device interface */
92	DEVMETHOD(device_probe,         adb_kbd_probe),
93        DEVMETHOD(device_attach,        adb_kbd_attach),
94        DEVMETHOD(device_detach,        adb_kbd_detach),
95        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
96        DEVMETHOD(device_suspend,       bus_generic_suspend),
97        DEVMETHOD(device_resume,        bus_generic_resume),
98
99	/* ADB interface */
100	DEVMETHOD(adb_receive_packet,	adb_kbd_receive_packet),
101
102	{ 0, 0 }
103};
104
105static driver_t adb_kbd_driver = {
106	"akbd",
107	adb_kbd_methods,
108	sizeof(struct adb_kbd_softc),
109};
110
111static devclass_t adb_kbd_devclass;
112
113DRIVER_MODULE(akbd, adb, adb_kbd_driver, adb_kbd_devclass, 0, 0);
114
115#ifdef AKBD_EMULATE_ATKBD
116
117#define	SCAN_PRESS		0x000
118#define	SCAN_RELEASE		0x080
119#define	SCAN_PREFIX_E0		0x100
120#define	SCAN_PREFIX_E1		0x200
121#define	SCAN_PREFIX_CTL		0x400
122#define	SCAN_PREFIX_SHIFT	0x800
123#define	SCAN_PREFIX		(SCAN_PREFIX_E0 | SCAN_PREFIX_E1 |	\
124				SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT)
125
126static const uint8_t adb_to_at_scancode_map[128] = { 30, 31, 32, 33, 35, 34,
127	44, 45, 46, 47, 0, 48, 16, 17, 18, 19, 21, 20, 2, 3, 4, 5, 7, 6, 13,
128	10, 8, 12, 9, 11, 27, 24, 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43,
129	51, 53, 49, 50, 52, 15, 57, 41, 14, 0, 1, 29, 0, 42, 58, 56, 97, 98,
130	100, 95, 0, 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 91, 89, 0, 74, 13, 0,
131	0, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73, 0, 0, 0, 63, 64, 65, 61,
132	66, 67, 0, 87, 0, 105, 0, 70, 0, 68, 0, 88, 0, 107, 102, 94, 96, 103,
133	62, 99, 60, 101, 59, 54, 93, 90, 0, 0 };
134
135static int
136keycode2scancode(int keycode, int shift, int up)
137{
138	static const int scan[] = {
139		/* KP enter, right ctrl, KP divide */
140		0x1c , 0x1d , 0x35 ,
141		/* print screen */
142		0x37 | SCAN_PREFIX_SHIFT,
143		/* right alt, home, up, page up, left, right, end */
144		0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f,
145		/* down, page down, insert, delete */
146		0x50, 0x51, 0x52, 0x53,
147		/* pause/break (see also below) */
148		0x46,
149		/*
150		 * MS: left window, right window, menu
151		 * also Sun: left meta, right meta, compose
152		 */
153		0x5b, 0x5c, 0x5d,
154		/* Sun type 6 USB */
155		/* help, stop, again, props, undo, front, copy */
156		0x68, 0x5e, 0x5f, 0x60,	0x61, 0x62, 0x63,
157		/* open, paste, find, cut, audiomute, audiolower, audioraise */
158		0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e,
159		/* power */
160		0x20
161	};
162	int scancode;
163
164	scancode = keycode;
165	if ((keycode >= 89) && (keycode < 89 + sizeof(scan) / sizeof(scan[0])))
166	scancode = scan[keycode - 89] | SCAN_PREFIX_E0;
167	/* pause/break */
168	if ((keycode == 104) && !(shift & CTLS))
169		scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL;
170	if (shift & SHIFTS)
171		scancode &= ~SCAN_PREFIX_SHIFT;
172	return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS));
173}
174#endif
175
176/* keyboard driver declaration */
177static int              akbd_configure(int flags);
178static kbd_probe_t      akbd_probe;
179static kbd_init_t       akbd_init;
180static kbd_term_t       akbd_term;
181static kbd_intr_t       akbd_interrupt;
182static kbd_test_if_t    akbd_test_if;
183static kbd_enable_t     akbd_enable;
184static kbd_disable_t    akbd_disable;
185static kbd_read_t       akbd_read;
186static kbd_check_t      akbd_check;
187static kbd_read_char_t  akbd_read_char;
188static kbd_check_char_t akbd_check_char;
189static kbd_ioctl_t      akbd_ioctl;
190static kbd_lock_t       akbd_lock;
191static kbd_clear_state_t akbd_clear_state;
192static kbd_get_state_t  akbd_get_state;
193static kbd_set_state_t  akbd_set_state;
194static kbd_poll_mode_t  akbd_poll;
195
196keyboard_switch_t akbdsw = {
197        akbd_probe,
198        akbd_init,
199        akbd_term,
200        akbd_interrupt,
201        akbd_test_if,
202        akbd_enable,
203        akbd_disable,
204        akbd_read,
205        akbd_check,
206        akbd_read_char,
207        akbd_check_char,
208        akbd_ioctl,
209        akbd_lock,
210        akbd_clear_state,
211        akbd_get_state,
212        akbd_set_state,
213        genkbd_get_fkeystr,
214        akbd_poll,
215        genkbd_diag,
216};
217
218KEYBOARD_DRIVER(akbd, akbdsw, akbd_configure);
219
220static int
221adb_kbd_probe(device_t dev)
222{
223	uint8_t type;
224
225	type = adb_get_device_type(dev);
226
227	if (type != ADB_DEVICE_KEYBOARD)
228		return (ENXIO);
229
230	switch(adb_get_device_handler(dev)) {
231	case 1:
232		device_set_desc(dev,"Apple Standard Keyboard");
233		break;
234	case 2:
235		device_set_desc(dev,"Apple Extended Keyboard");
236		break;
237	case 4:
238		device_set_desc(dev,"Apple ISO Keyboard");
239		break;
240	case 5:
241		device_set_desc(dev,"Apple Extended ISO Keyboard");
242		break;
243	case 8:
244		device_set_desc(dev,"Apple Keyboard II");
245		break;
246	case 9:
247		device_set_desc(dev,"Apple ISO Keyboard II");
248		break;
249	case 12:
250		device_set_desc(dev,"PowerBook Keyboard");
251		break;
252	case 13:
253		device_set_desc(dev,"PowerBook ISO Keyboard");
254		break;
255	case 24:
256		device_set_desc(dev,"PowerBook Extended Keyboard");
257		break;
258	case 27:
259		device_set_desc(dev,"Apple Design Keyboard");
260		break;
261	case 195:
262		device_set_desc(dev,"PowerBook G3 Keyboard");
263		break;
264	case 196:
265		device_set_desc(dev,"iBook Keyboard");
266		break;
267	default:
268		device_set_desc(dev,"ADB Keyboard");
269		break;
270	}
271
272	return (0);
273}
274
275static int
276ms_to_ticks(int ms)
277{
278	if (hz > 1000)
279		return ms*(hz/1000);
280
281	return ms/(1000/hz);
282}
283
284static int
285adb_kbd_attach(device_t dev)
286{
287	struct adb_kbd_softc *sc;
288	keyboard_switch_t *sw;
289	uint32_t fkeys;
290	phandle_t handle;
291
292	sw = kbd_get_switch(KBD_DRIVER_NAME);
293	if (sw == NULL) {
294		return ENXIO;
295	}
296
297	sc = device_get_softc(dev);
298	sc->sc_dev = dev;
299	sc->sc_mode = K_RAW;
300	sc->sc_state = 0;
301	sc->have_led_control = 0;
302	sc->buffers = 0;
303
304	/* Try stepping forward to the extended keyboard protocol */
305	adb_set_device_handler(dev,3);
306
307	mtx_init(&sc->sc_mutex,KBD_DRIVER_NAME,MTX_DEF,0);
308	cv_init(&sc->sc_cv,KBD_DRIVER_NAME);
309	callout_init(&sc->sc_repeater, 0);
310
311#ifdef AKBD_EMULATE_ATKBD
312	kbd_init_struct(&sc->sc_kbd, KBD_DRIVER_NAME, KB_101, 0, 0, 0, 0);
313	kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab,
314            sizeof(fkey_tab) / sizeof(fkey_tab[0]));
315#else
316	#error ADB raw mode not implemented
317#endif
318
319	KBD_FOUND_DEVICE(&sc->sc_kbd);
320	KBD_PROBE_DONE(&sc->sc_kbd);
321	KBD_INIT_DONE(&sc->sc_kbd);
322	KBD_CONFIG_DONE(&sc->sc_kbd);
323
324	(*sw->enable)(&sc->sc_kbd);
325
326	kbd_register(&sc->sc_kbd);
327
328#ifdef KBD_INSTALL_CDEV
329	if (kbd_attach(&sc->sc_kbd)) {
330		adb_kbd_detach(dev);
331		return ENXIO;
332	}
333#endif
334
335	/* Check if we can read out the LED state from
336	   this keyboard by reading the key state register */
337	if (adb_read_register(dev, 2, NULL) == 2)
338		sc->have_led_control = 1;
339
340	adb_set_autopoll(dev,1);
341
342	handle = OF_finddevice("mac-io/via-pmu/adb/keyboard");
343	if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys",
344	    &fkeys, sizeof(fkeys)) != -1) {
345		static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5",
346		    "F6", "F7", "F8", "F9", "F10", "F11", "F12"};
347		struct sysctl_ctx_list *ctx;
348		struct sysctl_oid *tree;
349		int i;
350
351		if (bootverbose)
352			device_printf(dev, "Keyboard has embedded Fn keys\n");
353
354		for (i = 0; i < 12; i++) {
355			uint32_t keyval;
356			char buf[3];
357			if (OF_getprop(handle, key_names[i], &keyval,
358			    sizeof(keyval)) < 0)
359				continue;
360			buf[0] = 1;
361			buf[1] = i+1;
362			buf[2] = keyval;
363			adb_write_register(dev, 0, 3, buf);
364		}
365		adb_write_register(dev, 1, 2, &(uint16_t){0});
366
367		ctx = device_get_sysctl_ctx(dev);
368		tree = device_get_sysctl_tree(dev);
369
370		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
371		    "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc,
372		    0, adb_fn_keys, "I",
373		    "Set the Fn keys to be their F-key type as default");
374	}
375
376	return (0);
377}
378
379static int
380adb_kbd_detach(device_t dev)
381{
382	struct adb_kbd_softc *sc;
383	keyboard_t *kbd;
384
385	sc = device_get_softc(dev);
386
387	adb_set_autopoll(dev,0);
388	callout_stop(&sc->sc_repeater);
389
390	mtx_lock(&sc->sc_mutex);
391
392	kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME,
393	          device_get_unit(dev)));
394
395	kbdd_disable(kbd);
396
397#ifdef KBD_INSTALL_CDEV
398	kbd_detach(kbd);
399#endif
400
401	kbdd_term(kbd);
402
403	mtx_unlock(&sc->sc_mutex);
404
405	mtx_destroy(&sc->sc_mutex);
406	cv_destroy(&sc->sc_cv);
407
408	return (0);
409}
410
411static u_int
412adb_kbd_receive_packet(device_t dev, u_char status,
413    u_char command, u_char reg, int len, u_char *data)
414{
415	struct adb_kbd_softc *sc;
416
417	sc = device_get_softc(dev);
418
419	if (command != ADB_COMMAND_TALK)
420		return 0;
421
422	if (reg != 0 || len != 2)
423		return (0);
424
425	mtx_lock(&sc->sc_mutex);
426		/* 0x7f is always the power button */
427		if (data[0] == 0x7f && devctl_process_running()) {
428			devctl_notify("PMU", "Button", "pressed", NULL);
429			return (0);
430		} else if (data[0] == 0xff) {
431			return (0);	/* Ignore power button release. */
432		}
433		if ((data[0] & 0x7f) == 57 && sc->buffers < 7) {
434			/* Fake the down/up cycle for caps lock */
435			sc->buffer[sc->buffers++] = data[0] & 0x7f;
436			sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7);
437		} else {
438			sc->buffer[sc->buffers++] = data[0];
439		}
440		if (sc->buffer[sc->buffers-1] < 0xff)
441			sc->last_press = sc->buffer[sc->buffers-1];
442
443		if ((data[1] & 0x7f) == 57 && sc->buffers < 7) {
444			/* Fake the down/up cycle for caps lock */
445			sc->buffer[sc->buffers++] = data[1] & 0x7f;
446			sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7);
447		} else {
448			sc->buffer[sc->buffers++] = data[1];
449		}
450
451		if (sc->buffer[sc->buffers-1] < 0xff)
452			sc->last_press = sc->buffer[sc->buffers-1];
453
454		/* Stop any existing key repeating */
455		callout_stop(&sc->sc_repeater);
456
457		/* Schedule a repeat callback on keydown */
458		if (!(sc->last_press & (1 << 7))) {
459			callout_reset(&sc->sc_repeater,
460			    ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc);
461		}
462	mtx_unlock(&sc->sc_mutex);
463
464	cv_broadcast(&sc->sc_cv);
465
466	if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
467		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
468			 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
469	}
470
471	return (0);
472}
473
474static void
475akbd_repeat(void *xsc) {
476	struct adb_kbd_softc *sc = xsc;
477	int notify_kbd = 0;
478
479	/* Fake an up/down key repeat so long as we have the
480	   free buffers */
481	mtx_lock(&sc->sc_mutex);
482		if (sc->buffers < 7) {
483			sc->buffer[sc->buffers++] = sc->last_press | (1 << 7);
484			sc->buffer[sc->buffers++] = sc->last_press;
485
486			notify_kbd = 1;
487		}
488	mtx_unlock(&sc->sc_mutex);
489
490	if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd)
491	    && KBD_IS_BUSY(&sc->sc_kbd)) {
492		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
493		    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
494	}
495
496	/* Reschedule the callout */
497	callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2),
498	    akbd_repeat, sc);
499}
500
501static int
502akbd_configure(int flags)
503{
504	return 0;
505}
506
507static int
508akbd_probe(int unit, void *arg, int flags)
509{
510	return 0;
511}
512
513static int
514akbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
515{
516	return 0;
517}
518
519static int
520akbd_term(keyboard_t *kbd)
521{
522	return 0;
523}
524
525static int
526akbd_interrupt(keyboard_t *kbd, void *arg)
527{
528	return 0;
529}
530
531static int
532akbd_test_if(keyboard_t *kbd)
533{
534	return 0;
535}
536
537static int
538akbd_enable(keyboard_t *kbd)
539{
540	KBD_ACTIVATE(kbd);
541	return (0);
542}
543
544static int
545akbd_disable(keyboard_t *kbd)
546{
547	struct adb_kbd_softc *sc;
548	sc = (struct adb_kbd_softc *)(kbd);
549
550	callout_stop(&sc->sc_repeater);
551	KBD_DEACTIVATE(kbd);
552	return (0);
553}
554
555static int
556akbd_read(keyboard_t *kbd, int wait)
557{
558	return (0);
559}
560
561static int
562akbd_check(keyboard_t *kbd)
563{
564	struct adb_kbd_softc *sc;
565
566	if (!KBD_IS_ACTIVE(kbd))
567		return (FALSE);
568
569	sc = (struct adb_kbd_softc *)(kbd);
570
571	mtx_lock(&sc->sc_mutex);
572#ifdef AKBD_EMULATE_ATKBD
573		if (sc->at_buffered_char[0]) {
574			mtx_unlock(&sc->sc_mutex);
575			return (TRUE);
576		}
577#endif
578
579		if (sc->buffers > 0) {
580			mtx_unlock(&sc->sc_mutex);
581			return (TRUE);
582		}
583	mtx_unlock(&sc->sc_mutex);
584
585	return (FALSE);
586}
587
588static u_int
589akbd_read_char(keyboard_t *kbd, int wait)
590{
591	struct adb_kbd_softc *sc;
592	uint16_t key;
593	uint8_t adb_code;
594	int i;
595
596	sc = (struct adb_kbd_softc *)(kbd);
597
598	mtx_lock(&sc->sc_mutex);
599
600#if defined(AKBD_EMULATE_ATKBD)
601	if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) {
602		key = sc->at_buffered_char[0];
603		if (key & SCAN_PREFIX) {
604			sc->at_buffered_char[0] = key & ~SCAN_PREFIX;
605			key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
606		} else {
607			sc->at_buffered_char[0] = sc->at_buffered_char[1];
608			sc->at_buffered_char[1] = 0;
609		}
610
611		mtx_unlock(&sc->sc_mutex);
612
613		return (key);
614	}
615#endif
616
617	if (!sc->buffers && wait)
618		cv_wait(&sc->sc_cv,&sc->sc_mutex);
619
620	if (!sc->buffers) {
621		mtx_unlock(&sc->sc_mutex);
622		return (0);
623	}
624
625	adb_code = sc->buffer[0];
626
627	for (i = 1; i < sc->buffers; i++)
628		sc->buffer[i-1] = sc->buffer[i];
629
630	sc->buffers--;
631
632	#ifdef AKBD_EMULATE_ATKBD
633		key = adb_to_at_scancode_map[adb_code & 0x7f];
634		if (sc->sc_mode == K_CODE) {
635			/* Add the key-release bit */
636			key |= adb_code & 0x80;
637		} else if (sc->sc_mode == K_RAW) {
638			/*
639			 * In the raw case, we have to emulate the gross
640			 * variable-length AT keyboard thing. Since this code
641			 * is copied from sunkbd, which is the same code
642			 * as ukbd, it might be nice to have this centralized.
643			 */
644
645			key = keycode2scancode(key,
646			    0, adb_code & 0x80);
647
648			if (key & SCAN_PREFIX) {
649				if (key & SCAN_PREFIX_CTL) {
650					sc->at_buffered_char[0] =
651					    0x1d | (key & SCAN_RELEASE);
652					sc->at_buffered_char[1] =
653					    key & ~SCAN_PREFIX;
654				} else if (key & SCAN_PREFIX_SHIFT) {
655					sc->at_buffered_char[0] =
656					    0x2a | (key & SCAN_RELEASE);
657					sc->at_buffered_char[1] =
658					    key & ~SCAN_PREFIX_SHIFT;
659				} else {
660					sc->at_buffered_char[0] =
661					    key & ~SCAN_PREFIX;
662					sc->at_buffered_char[1] = 0;
663				}
664
665				key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
666			}
667		}
668	#else
669		key = adb_code;
670	#endif
671
672	mtx_unlock(&sc->sc_mutex);
673
674	return (key);
675}
676
677static int
678akbd_check_char(keyboard_t *kbd)
679{
680	if (!KBD_IS_ACTIVE(kbd))
681		return (FALSE);
682
683	return (akbd_check(kbd));
684}
685
686static int
687set_typematic(keyboard_t *kbd, int code)
688{
689	/* These numbers are in microseconds, so convert to ticks */
690
691	static int delays[] = { 250, 500, 750, 1000 };
692	static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
693				68,  76,  84,  92, 100, 110, 118, 126,
694				136, 152, 168, 184, 200, 220, 236, 252,
695				272, 304, 336, 368, 400, 440, 472, 504 };
696
697	if (code & ~0x7f)
698		return EINVAL;
699	kbd->kb_delay1 = delays[(code >> 5) & 3];
700	kbd->kb_delay2 = rates[code & 0x1f];
701	return 0;
702}
703
704static int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
705{
706	struct adb_kbd_softc *sc;
707	uint16_t r2;
708	int error;
709
710	sc = (struct adb_kbd_softc *)(kbd);
711	error = 0;
712
713	switch (cmd) {
714	case KDGKBMODE:
715		*(int *)data = sc->sc_mode;
716		break;
717	case KDSKBMODE:
718		switch (*(int *)data) {
719		case K_XLATE:
720			if (sc->sc_mode != K_XLATE) {
721				/* make lock key state and LED state match */
722				sc->sc_state &= ~LOCK_MASK;
723				sc->sc_state |= KBD_LED_VAL(kbd);
724			}
725			/* FALLTHROUGH */
726		case K_RAW:
727		case K_CODE:
728			if (sc->sc_mode != *(int *)data)
729				sc->sc_mode = *(int *)data;
730			break;
731		default:
732			error = EINVAL;
733			break;
734		}
735
736		break;
737
738	case KDGETLED:
739		*(int *)data = KBD_LED_VAL(kbd);
740		break;
741
742	case KDSKBSTATE:
743		if (*(int *)data & ~LOCK_MASK) {
744			error = EINVAL;
745			break;
746		}
747		sc->sc_state &= ~LOCK_MASK;
748		sc->sc_state |= *(int *)data;
749
750		/* FALLTHROUGH */
751
752	case KDSETLED:
753		KBD_LED_VAL(kbd) = *(int *)data;
754
755		if (!sc->have_led_control)
756			break;
757
758		r2 = (~0 & 0x04) | 3;
759
760		if (*(int *)data & NLKED)
761			r2 &= ~1;
762		if (*(int *)data & CLKED)
763			r2 &= ~2;
764		if (*(int *)data & SLKED)
765			r2 &= ~4;
766
767		adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2,
768			sizeof(uint16_t),(u_char *)&r2);
769
770		break;
771
772	case KDGKBSTATE:
773		*(int *)data = sc->sc_state & LOCK_MASK;
774		break;
775
776	case KDSETREPEAT:
777		if (!KBD_HAS_DEVICE(kbd))
778			return 0;
779		if (((int *)data)[1] < 0)
780			return EINVAL;
781		if (((int *)data)[0] < 0)
782			return EINVAL;
783		else if (((int *)data)[0] == 0)  /* fastest possible value */
784			kbd->kb_delay1 = 200;
785		else
786			kbd->kb_delay1 = ((int *)data)[0];
787		kbd->kb_delay2 = ((int *)data)[1];
788
789		break;
790
791	case KDSETRAD:
792		error = set_typematic(kbd, *(int *)data);
793		break;
794
795	case PIO_KEYMAP:
796	case OPIO_KEYMAP:
797	case PIO_KEYMAPENT:
798	case PIO_DEADKEYMAP:
799	default:
800		return (genkbd_commonioctl(kbd, cmd, data));
801	}
802
803	return (error);
804}
805
806static int akbd_lock(keyboard_t *kbd, int lock)
807{
808	return (0);
809}
810
811static void akbd_clear_state(keyboard_t *kbd)
812{
813	struct adb_kbd_softc *sc;
814
815	sc = (struct adb_kbd_softc *)(kbd);
816
817	mtx_lock(&sc->sc_mutex);
818
819	sc->buffers = 0;
820	callout_stop(&sc->sc_repeater);
821
822#if defined(AKBD_EMULATE_ATKBD)
823	sc->at_buffered_char[0] = 0;
824	sc->at_buffered_char[1] = 0;
825#endif
826	mtx_unlock(&sc->sc_mutex);
827}
828
829static int akbd_get_state(keyboard_t *kbd, void *buf, size_t len)
830{
831	return (0);
832}
833
834static int akbd_set_state(keyboard_t *kbd, void *buf, size_t len)
835{
836	return (0);
837}
838
839static int akbd_poll(keyboard_t *kbd, int on)
840{
841	return (0);
842}
843
844static int
845akbd_modevent(module_t mod, int type, void *data)
846{
847	switch (type) {
848	case MOD_LOAD:
849		kbd_add_driver(&akbd_kbd_driver);
850		break;
851
852	case MOD_UNLOAD:
853		kbd_delete_driver(&akbd_kbd_driver);
854		break;
855
856	default:
857		return (EOPNOTSUPP);
858	}
859
860	return (0);
861}
862
863static int
864adb_fn_keys(SYSCTL_HANDLER_ARGS)
865{
866	struct adb_kbd_softc *sc = arg1;
867	int error;
868	uint16_t is_fn_enabled;
869	unsigned int is_fn_enabled_sysctl;
870
871	adb_read_register(sc->sc_dev, 1, &is_fn_enabled);
872	is_fn_enabled &= 1;
873	is_fn_enabled_sysctl = is_fn_enabled;
874	error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req);
875
876	if (error || !req->newptr)
877		return (error);
878
879	is_fn_enabled = is_fn_enabled_sysctl;
880	if (is_fn_enabled != 1 && is_fn_enabled != 0)
881		return (EINVAL);
882
883	adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled);
884	return (0);
885}
886
887DEV_MODULE(akbd, akbd_modevent, NULL);
888
889