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