adb_kbd.c revision 356007
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: stable/11/sys/dev/adb/adb_kbd.c 356007 2019-12-22 16:04:12Z kevans $
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 + nitems(scan)))
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        .probe =	akbd_probe,
198        .init =		akbd_init,
199        .term =		akbd_term,
200        .intr =		akbd_interrupt,
201        .test_if =	akbd_test_if,
202        .enable =	akbd_enable,
203        .disable =	akbd_disable,
204        .read =		akbd_read,
205        .check =	akbd_check,
206        .read_char =	akbd_read_char,
207        .check_char =	akbd_check_char,
208        .ioctl =	akbd_ioctl,
209        .lock =		akbd_lock,
210        .clear_state =	akbd_clear_state,
211        .get_state =	akbd_get_state,
212        .set_state =	akbd_set_state,
213        .get_fkeystr =	genkbd_get_fkeystr,
214        .poll =		akbd_poll,
215        .diag =		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, NULL, MTX_DEF);
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) {
428			devctl_notify("PMU", "Button", "pressed", NULL);
429			mtx_unlock(&sc->sc_mutex);
430			return (0);
431		} else if (data[0] == 0xff) {
432			mtx_unlock(&sc->sc_mutex);
433			return (0);	/* Ignore power button release. */
434		}
435		if ((data[0] & 0x7f) == 57 && sc->buffers < 7) {
436			/* Fake the down/up cycle for caps lock */
437			sc->buffer[sc->buffers++] = data[0] & 0x7f;
438			sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7);
439		} else {
440			sc->buffer[sc->buffers++] = data[0];
441		}
442		if (sc->buffer[sc->buffers-1] < 0xff)
443			sc->last_press = sc->buffer[sc->buffers-1];
444
445		if ((data[1] & 0x7f) == 57 && sc->buffers < 7) {
446			/* Fake the down/up cycle for caps lock */
447			sc->buffer[sc->buffers++] = data[1] & 0x7f;
448			sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7);
449		} else {
450			sc->buffer[sc->buffers++] = data[1];
451		}
452
453		if (sc->buffer[sc->buffers-1] < 0xff)
454			sc->last_press = sc->buffer[sc->buffers-1];
455
456		/* Stop any existing key repeating */
457		callout_stop(&sc->sc_repeater);
458
459		/* Schedule a repeat callback on keydown */
460		if (!(sc->last_press & (1 << 7))) {
461			callout_reset(&sc->sc_repeater,
462			    ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc);
463		}
464	mtx_unlock(&sc->sc_mutex);
465
466	cv_broadcast(&sc->sc_cv);
467
468	if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
469		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
470			 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
471	}
472
473	return (0);
474}
475
476static void
477akbd_repeat(void *xsc) {
478	struct adb_kbd_softc *sc = xsc;
479	int notify_kbd = 0;
480
481	/* Fake an up/down key repeat so long as we have the
482	   free buffers */
483	mtx_lock(&sc->sc_mutex);
484		if (sc->buffers < 7) {
485			sc->buffer[sc->buffers++] = sc->last_press | (1 << 7);
486			sc->buffer[sc->buffers++] = sc->last_press;
487
488			notify_kbd = 1;
489		}
490	mtx_unlock(&sc->sc_mutex);
491
492	if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd)
493	    && KBD_IS_BUSY(&sc->sc_kbd)) {
494		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
495		    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
496	}
497
498	/* Reschedule the callout */
499	callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2),
500	    akbd_repeat, sc);
501}
502
503static int
504akbd_configure(int flags)
505{
506	return 0;
507}
508
509static int
510akbd_probe(int unit, void *arg, int flags)
511{
512	return 0;
513}
514
515static int
516akbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
517{
518	return 0;
519}
520
521static int
522akbd_term(keyboard_t *kbd)
523{
524	return 0;
525}
526
527static int
528akbd_interrupt(keyboard_t *kbd, void *arg)
529{
530	return 0;
531}
532
533static int
534akbd_test_if(keyboard_t *kbd)
535{
536	return 0;
537}
538
539static int
540akbd_enable(keyboard_t *kbd)
541{
542	KBD_ACTIVATE(kbd);
543	return (0);
544}
545
546static int
547akbd_disable(keyboard_t *kbd)
548{
549	struct adb_kbd_softc *sc;
550	sc = (struct adb_kbd_softc *)(kbd);
551
552	callout_stop(&sc->sc_repeater);
553	KBD_DEACTIVATE(kbd);
554	return (0);
555}
556
557static int
558akbd_read(keyboard_t *kbd, int wait)
559{
560	return (0);
561}
562
563static int
564akbd_check(keyboard_t *kbd)
565{
566	struct adb_kbd_softc *sc;
567
568	if (!KBD_IS_ACTIVE(kbd))
569		return (FALSE);
570
571	sc = (struct adb_kbd_softc *)(kbd);
572
573	mtx_lock(&sc->sc_mutex);
574#ifdef AKBD_EMULATE_ATKBD
575		if (sc->at_buffered_char[0]) {
576			mtx_unlock(&sc->sc_mutex);
577			return (TRUE);
578		}
579#endif
580
581		if (sc->buffers > 0) {
582			mtx_unlock(&sc->sc_mutex);
583			return (TRUE);
584		}
585	mtx_unlock(&sc->sc_mutex);
586
587	return (FALSE);
588}
589
590static u_int
591akbd_read_char(keyboard_t *kbd, int wait)
592{
593	struct adb_kbd_softc *sc;
594	uint16_t key;
595	uint8_t adb_code;
596	int i;
597
598	sc = (struct adb_kbd_softc *)(kbd);
599
600	mtx_lock(&sc->sc_mutex);
601
602#if defined(AKBD_EMULATE_ATKBD)
603	if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) {
604		key = sc->at_buffered_char[0];
605		if (key & SCAN_PREFIX) {
606			sc->at_buffered_char[0] = key & ~SCAN_PREFIX;
607			key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
608		} else {
609			sc->at_buffered_char[0] = sc->at_buffered_char[1];
610			sc->at_buffered_char[1] = 0;
611		}
612
613		mtx_unlock(&sc->sc_mutex);
614
615		return (key);
616	}
617#endif
618
619	if (!sc->buffers && wait)
620		cv_wait(&sc->sc_cv,&sc->sc_mutex);
621
622	if (!sc->buffers) {
623		mtx_unlock(&sc->sc_mutex);
624		return (NOKEY);
625	}
626
627	adb_code = sc->buffer[0];
628
629	for (i = 1; i < sc->buffers; i++)
630		sc->buffer[i-1] = sc->buffer[i];
631
632	sc->buffers--;
633
634	#ifdef AKBD_EMULATE_ATKBD
635		key = adb_to_at_scancode_map[adb_code & 0x7f];
636		if (sc->sc_mode == K_CODE) {
637			/* Add the key-release bit */
638			key |= adb_code & 0x80;
639		} else if (sc->sc_mode == K_RAW) {
640			/*
641			 * In the raw case, we have to emulate the gross
642			 * variable-length AT keyboard thing. Since this code
643			 * is copied from sunkbd, which is the same code
644			 * as ukbd, it might be nice to have this centralized.
645			 */
646
647			key = keycode2scancode(key,
648			    0, adb_code & 0x80);
649
650			if (key & SCAN_PREFIX) {
651				if (key & SCAN_PREFIX_CTL) {
652					sc->at_buffered_char[0] =
653					    0x1d | (key & SCAN_RELEASE);
654					sc->at_buffered_char[1] =
655					    key & ~SCAN_PREFIX;
656				} else if (key & SCAN_PREFIX_SHIFT) {
657					sc->at_buffered_char[0] =
658					    0x2a | (key & SCAN_RELEASE);
659					sc->at_buffered_char[1] =
660					    key & ~SCAN_PREFIX_SHIFT;
661				} else {
662					sc->at_buffered_char[0] =
663					    key & ~SCAN_PREFIX;
664					sc->at_buffered_char[1] = 0;
665				}
666
667				key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
668			}
669		}
670	#else
671		key = adb_code;
672	#endif
673
674	mtx_unlock(&sc->sc_mutex);
675
676	return (key);
677}
678
679static int
680akbd_check_char(keyboard_t *kbd)
681{
682	if (!KBD_IS_ACTIVE(kbd))
683		return (FALSE);
684
685	return (akbd_check(kbd));
686}
687
688static int
689set_typematic(keyboard_t *kbd, int code)
690{
691	/* These numbers are in microseconds, so convert to ticks */
692
693	static int delays[] = { 250, 500, 750, 1000 };
694	static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
695				68,  76,  84,  92, 100, 110, 118, 126,
696				136, 152, 168, 184, 200, 220, 236, 252,
697				272, 304, 336, 368, 400, 440, 472, 504 };
698
699	if (code & ~0x7f)
700		return EINVAL;
701	kbd->kb_delay1 = delays[(code >> 5) & 3];
702	kbd->kb_delay2 = rates[code & 0x1f];
703	return 0;
704}
705
706static int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
707{
708	struct adb_kbd_softc *sc;
709	uint16_t r2;
710	int error;
711
712	sc = (struct adb_kbd_softc *)(kbd);
713	error = 0;
714
715	switch (cmd) {
716	case KDGKBMODE:
717		*(int *)data = sc->sc_mode;
718		break;
719	case KDSKBMODE:
720		switch (*(int *)data) {
721		case K_XLATE:
722			if (sc->sc_mode != K_XLATE) {
723				/* make lock key state and LED state match */
724				sc->sc_state &= ~LOCK_MASK;
725				sc->sc_state |= KBD_LED_VAL(kbd);
726			}
727			/* FALLTHROUGH */
728		case K_RAW:
729		case K_CODE:
730			if (sc->sc_mode != *(int *)data)
731				sc->sc_mode = *(int *)data;
732			break;
733		default:
734			error = EINVAL;
735			break;
736		}
737
738		break;
739
740	case KDGETLED:
741		*(int *)data = KBD_LED_VAL(kbd);
742		break;
743
744	case KDSKBSTATE:
745		if (*(int *)data & ~LOCK_MASK) {
746			error = EINVAL;
747			break;
748		}
749		sc->sc_state &= ~LOCK_MASK;
750		sc->sc_state |= *(int *)data;
751
752		/* FALLTHROUGH */
753
754	case KDSETLED:
755		KBD_LED_VAL(kbd) = *(int *)data;
756
757		if (!sc->have_led_control)
758			break;
759
760		r2 = (~0 & 0x04) | 3;
761
762		if (*(int *)data & NLKED)
763			r2 &= ~1;
764		if (*(int *)data & CLKED)
765			r2 &= ~2;
766		if (*(int *)data & SLKED)
767			r2 &= ~4;
768
769		adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2,
770			sizeof(uint16_t),(u_char *)&r2);
771
772		break;
773
774	case KDGKBSTATE:
775		*(int *)data = sc->sc_state & LOCK_MASK;
776		break;
777
778	case KDSETREPEAT:
779		if (!KBD_HAS_DEVICE(kbd))
780			return 0;
781		if (((int *)data)[1] < 0)
782			return EINVAL;
783		if (((int *)data)[0] < 0)
784			return EINVAL;
785		else if (((int *)data)[0] == 0)  /* fastest possible value */
786			kbd->kb_delay1 = 200;
787		else
788			kbd->kb_delay1 = ((int *)data)[0];
789		kbd->kb_delay2 = ((int *)data)[1];
790
791		break;
792
793	case KDSETRAD:
794		error = set_typematic(kbd, *(int *)data);
795		break;
796
797	case PIO_KEYMAP:
798	case OPIO_KEYMAP:
799	case PIO_KEYMAPENT:
800	case PIO_DEADKEYMAP:
801	default:
802		return (genkbd_commonioctl(kbd, cmd, data));
803	}
804
805	return (error);
806}
807
808static int akbd_lock(keyboard_t *kbd, int lock)
809{
810	return (0);
811}
812
813static void akbd_clear_state(keyboard_t *kbd)
814{
815	struct adb_kbd_softc *sc;
816
817	sc = (struct adb_kbd_softc *)(kbd);
818
819	mtx_lock(&sc->sc_mutex);
820
821	sc->buffers = 0;
822	callout_stop(&sc->sc_repeater);
823
824#if defined(AKBD_EMULATE_ATKBD)
825	sc->at_buffered_char[0] = 0;
826	sc->at_buffered_char[1] = 0;
827#endif
828	mtx_unlock(&sc->sc_mutex);
829}
830
831static int akbd_get_state(keyboard_t *kbd, void *buf, size_t len)
832{
833	return (0);
834}
835
836static int akbd_set_state(keyboard_t *kbd, void *buf, size_t len)
837{
838	return (0);
839}
840
841static int akbd_poll(keyboard_t *kbd, int on)
842{
843	return (0);
844}
845
846static int
847akbd_modevent(module_t mod, int type, void *data)
848{
849	switch (type) {
850	case MOD_LOAD:
851		kbd_add_driver(&akbd_kbd_driver);
852		break;
853
854	case MOD_UNLOAD:
855		kbd_delete_driver(&akbd_kbd_driver);
856		break;
857
858	default:
859		return (EOPNOTSUPP);
860	}
861
862	return (0);
863}
864
865static int
866adb_fn_keys(SYSCTL_HANDLER_ARGS)
867{
868	struct adb_kbd_softc *sc = arg1;
869	int error;
870	uint16_t is_fn_enabled;
871	unsigned int is_fn_enabled_sysctl;
872
873	adb_read_register(sc->sc_dev, 1, &is_fn_enabled);
874	is_fn_enabled &= 1;
875	is_fn_enabled_sysctl = is_fn_enabled;
876	error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req);
877
878	if (error || !req->newptr)
879		return (error);
880
881	is_fn_enabled = is_fn_enabled_sysctl;
882	if (is_fn_enabled != 1 && is_fn_enabled != 0)
883		return (EINVAL);
884
885	adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled);
886	return (0);
887}
888
889DEV_MODULE(akbd, akbd_modevent, NULL);
890
891