gpiokeys.c revision 356013
1/*-
2 * Copyright (c) 2015-2016 Oleksandr Tymoshenko <gonzo@freebsd.org>
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 AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/sys/dev/gpio/gpiokeys.c 356013 2019-12-22 17:15:48Z kevans $");
29
30#include "opt_platform.h"
31#include "opt_kbd.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/bus.h>
36#include <sys/gpio.h>
37#include <sys/kernel.h>
38#include <sys/lock.h>
39#include <sys/malloc.h>
40#include <sys/module.h>
41#include <sys/mutex.h>
42#include <sys/proc.h>
43#include <sys/kdb.h>
44
45#include <sys/ioccom.h>
46#include <sys/filio.h>
47#include <sys/tty.h>
48#include <sys/kbio.h>
49
50#include <dev/kbd/kbdreg.h>
51#include <dev/kbd/kbdtables.h>
52
53#include <dev/fdt/fdt_common.h>
54#include <dev/ofw/ofw_bus.h>
55#include <dev/ofw/ofw_bus_subr.h>
56
57#include <dev/gpio/gpiobusvar.h>
58#include <dev/gpio/gpiokeys.h>
59
60#define	KBD_DRIVER_NAME	"gpiokeys"
61
62#define	GPIOKEYS_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
63#define	GPIOKEYS_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
64#define	GPIOKEYS_LOCK_INIT(_sc) \
65	mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
66	    "gpiokeys", MTX_DEF)
67#define	GPIOKEYS_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx);
68#define	GPIOKEYS_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
69
70#define	GPIOKEY_LOCK(_key)		mtx_lock(&(_key)->mtx)
71#define	GPIOKEY_UNLOCK(_key)		mtx_unlock(&(_key)->mtx)
72#define	GPIOKEY_LOCK_INIT(_key) \
73	mtx_init(&(_key)->mtx, "gpiokey", "gpiokey", MTX_DEF)
74#define	GPIOKEY_LOCK_DESTROY(_key)	mtx_destroy(&(_key)->mtx);
75
76#define	KEY_PRESS	  0
77#define	KEY_RELEASE	  0x80
78
79#define	SCAN_PRESS	  0
80#define	SCAN_RELEASE	  0x80
81#define	SCAN_CHAR(c)	((c) & 0x7f)
82
83#define	GPIOKEYS_GLOBAL_NMOD                     8	/* units */
84#define	GPIOKEYS_GLOBAL_NKEYCODE                 6	/* units */
85#define	GPIOKEYS_GLOBAL_IN_BUF_SIZE  (2*(GPIOKEYS_GLOBAL_NMOD + (2*GPIOKEYS_GLOBAL_NKEYCODE)))	/* bytes */
86#define	GPIOKEYS_GLOBAL_IN_BUF_FULL  (GPIOKEYS_GLOBAL_IN_BUF_SIZE / 2)	/* bytes */
87#define	GPIOKEYS_GLOBAL_NFKEY        (sizeof(fkey_tab)/sizeof(fkey_tab[0]))	/* units */
88#define	GPIOKEYS_GLOBAL_BUFFER_SIZE	      64	/* bytes */
89
90#define	AUTOREPEAT_DELAY	250
91#define	AUTOREPEAT_REPEAT	34
92
93struct gpiokeys_softc;
94
95struct gpiokey
96{
97	struct gpiokeys_softc	*parent_sc;
98	gpio_pin_t		pin;
99	int			irq_rid;
100	struct resource		*irq_res;
101	void			*intr_hl;
102	struct mtx		mtx;
103	uint32_t		keycode;
104	int			autorepeat;
105	struct callout		debounce_callout;
106	struct callout		repeat_callout;
107	int			repeat_delay;
108	int			repeat;
109	int			debounce_interval;
110};
111
112struct gpiokeys_softc
113{
114	device_t	sc_dev;
115	struct mtx	sc_mtx;
116	struct gpiokey	*sc_keys;
117	int		sc_total_keys;
118
119	keyboard_t	sc_kbd;
120	keymap_t	sc_keymap;
121	accentmap_t	sc_accmap;
122	fkeytab_t	sc_fkeymap[GPIOKEYS_GLOBAL_NFKEY];
123
124	uint32_t	sc_input[GPIOKEYS_GLOBAL_IN_BUF_SIZE];	/* input buffer */
125	uint32_t	sc_time_ms;
126#define	GPIOKEYS_GLOBAL_FLAG_POLLING	0x00000002
127
128	uint32_t	sc_flags;		/* flags */
129
130	int		sc_mode;		/* input mode (K_XLATE,K_RAW,K_CODE) */
131	int		sc_state;		/* shift/lock key state */
132	int		sc_accents;		/* accent key index (> 0) */
133	int		sc_kbd_size;
134
135	uint16_t	sc_inputs;
136	uint16_t	sc_inputhead;
137	uint16_t	sc_inputtail;
138
139	uint8_t		sc_kbd_id;
140};
141
142/* gpio-keys device */
143static int gpiokeys_probe(device_t);
144static int gpiokeys_attach(device_t);
145static int gpiokeys_detach(device_t);
146
147/* kbd methods prototypes */
148static int	gpiokeys_set_typematic(keyboard_t *, int);
149static uint32_t	gpiokeys_read_char(keyboard_t *, int);
150static void	gpiokeys_clear_state(keyboard_t *);
151static int	gpiokeys_ioctl(keyboard_t *, u_long, caddr_t);
152static int	gpiokeys_enable(keyboard_t *);
153static int	gpiokeys_disable(keyboard_t *);
154static void	gpiokeys_event_keyinput(struct gpiokeys_softc *);
155
156static void
157gpiokeys_put_key(struct gpiokeys_softc *sc, uint32_t key)
158{
159
160	GPIOKEYS_ASSERT_LOCKED(sc);
161
162	if (sc->sc_inputs < GPIOKEYS_GLOBAL_IN_BUF_SIZE) {
163		sc->sc_input[sc->sc_inputtail] = key;
164		++(sc->sc_inputs);
165		++(sc->sc_inputtail);
166		if (sc->sc_inputtail >= GPIOKEYS_GLOBAL_IN_BUF_SIZE) {
167			sc->sc_inputtail = 0;
168		}
169	} else {
170		device_printf(sc->sc_dev, "input buffer is full\n");
171	}
172}
173
174static void
175gpiokeys_key_event(struct gpiokeys_softc *sc, uint16_t keycode, int pressed)
176{
177	uint32_t key;
178
179
180	key = keycode & SCAN_KEYCODE_MASK;
181
182	if (!pressed)
183		key |= KEY_RELEASE;
184
185	GPIOKEYS_LOCK(sc);
186	if (keycode & SCAN_PREFIX_E0)
187		gpiokeys_put_key(sc, 0xe0);
188	else if (keycode & SCAN_PREFIX_E1)
189		gpiokeys_put_key(sc, 0xe1);
190
191	gpiokeys_put_key(sc, key);
192	GPIOKEYS_UNLOCK(sc);
193
194	gpiokeys_event_keyinput(sc);
195}
196
197static void
198gpiokey_autorepeat(void *arg)
199{
200	struct gpiokey *key;
201
202	key = arg;
203
204	if (key->keycode == GPIOKEY_NONE)
205		return;
206
207	gpiokeys_key_event(key->parent_sc, key->keycode, 1);
208
209	callout_reset(&key->repeat_callout, key->repeat,
210		    gpiokey_autorepeat, key);
211}
212
213static void
214gpiokey_debounced_intr(void *arg)
215{
216	struct gpiokey *key;
217	bool active;
218
219	key = arg;
220
221	if (key->keycode == GPIOKEY_NONE)
222		return;
223
224	gpio_pin_is_active(key->pin, &active);
225	if (active) {
226		gpiokeys_key_event(key->parent_sc, key->keycode, 1);
227		if (key->autorepeat) {
228			callout_reset(&key->repeat_callout, key->repeat_delay,
229			    gpiokey_autorepeat, key);
230		}
231	}
232	else {
233		if (key->autorepeat &&
234		    callout_pending(&key->repeat_callout))
235			callout_stop(&key->repeat_callout);
236		gpiokeys_key_event(key->parent_sc, key->keycode, 0);
237	}
238}
239
240static void
241gpiokey_intr(void *arg)
242{
243	struct gpiokey *key;
244	int debounce_ticks;
245
246	key = arg;
247
248	GPIOKEY_LOCK(key);
249	debounce_ticks = (hz * key->debounce_interval) / 1000;
250	if (debounce_ticks == 0)
251		debounce_ticks = 1;
252	if (!callout_pending(&key->debounce_callout))
253		callout_reset(&key->debounce_callout, debounce_ticks,
254		    gpiokey_debounced_intr, key);
255	GPIOKEY_UNLOCK(key);
256}
257
258static void
259gpiokeys_attach_key(struct gpiokeys_softc *sc, phandle_t node,
260    struct gpiokey *key)
261{
262	pcell_t prop;
263	char *name;
264	uint32_t code;
265	int err;
266	const char *key_name;
267
268	GPIOKEY_LOCK_INIT(key);
269	key->parent_sc = sc;
270	callout_init_mtx(&key->debounce_callout, &key->mtx, 0);
271	callout_init_mtx(&key->repeat_callout, &key->mtx, 0);
272
273	name = NULL;
274	if (OF_getprop_alloc(node, "label", 1, (void **)&name) == -1)
275		OF_getprop_alloc(node, "name", 1, (void **)&name);
276
277	if (name != NULL)
278		key_name = name;
279	else
280		key_name = "unknown";
281
282	key->autorepeat = OF_hasprop(node, "autorepeat");
283
284	key->repeat_delay = (hz * AUTOREPEAT_DELAY) / 1000;
285	if (key->repeat_delay == 0)
286		key->repeat_delay = 1;
287
288	key->repeat = (hz * AUTOREPEAT_REPEAT) / 1000;
289	if (key->repeat == 0)
290		key->repeat = 1;
291
292	if ((OF_getprop(node, "debounce-interval", &prop, sizeof(prop))) > 0)
293		key->debounce_interval = fdt32_to_cpu(prop);
294	else
295		key->debounce_interval = 5;
296
297	if ((OF_getprop(node, "freebsd,code", &prop, sizeof(prop))) > 0)
298		key->keycode = fdt32_to_cpu(prop);
299	else if ((OF_getprop(node, "linux,code", &prop, sizeof(prop))) > 0) {
300		code = fdt32_to_cpu(prop);
301		key->keycode = gpiokey_map_linux_code(code);
302		if (key->keycode == GPIOKEY_NONE)
303			device_printf(sc->sc_dev, "<%s> failed to map linux,code value 0x%x\n",
304			    key_name, code);
305	}
306	else
307		device_printf(sc->sc_dev, "<%s> no linux,code or freebsd,code property\n",
308		    key_name);
309
310	err = gpio_pin_get_by_ofw_idx(sc->sc_dev, node, 0, &key->pin);
311	if (err) {
312		device_printf(sc->sc_dev, "<%s> failed to map pin\n", key_name);
313		if (name)
314			OF_prop_free(name);
315		return;
316	}
317
318	key->irq_res = gpio_alloc_intr_resource(sc->sc_dev, &key->irq_rid,
319	    RF_ACTIVE, key->pin, GPIO_INTR_EDGE_BOTH);
320	if (!key->irq_res) {
321		device_printf(sc->sc_dev, "<%s> cannot allocate interrupt\n", key_name);
322		gpio_pin_release(key->pin);
323		key->pin = NULL;
324		if (name)
325			OF_prop_free(name);
326		return;
327	}
328
329	if (bus_setup_intr(sc->sc_dev, key->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
330			NULL, gpiokey_intr, key,
331			&key->intr_hl) != 0) {
332		device_printf(sc->sc_dev, "<%s> unable to setup the irq handler\n", key_name);
333		bus_release_resource(sc->sc_dev, SYS_RES_IRQ, key->irq_rid,
334		    key->irq_res);
335		gpio_pin_release(key->pin);
336		key->pin = NULL;
337		key->irq_res = NULL;
338		if (name)
339			OF_prop_free(name);
340		return;
341	}
342
343	if (bootverbose)
344		device_printf(sc->sc_dev, "<%s> code=%08x, autorepeat=%d, "\
345		    "repeat=%d, repeat_delay=%d\n", key_name, key->keycode,
346		    key->autorepeat, key->repeat, key->repeat_delay);
347
348	if (name)
349		OF_prop_free(name);
350}
351
352static void
353gpiokeys_detach_key(struct gpiokeys_softc *sc, struct gpiokey *key)
354{
355
356	GPIOKEY_LOCK(key);
357	if (key->intr_hl)
358		bus_teardown_intr(sc->sc_dev, key->irq_res, key->intr_hl);
359	if (key->irq_res)
360		bus_release_resource(sc->sc_dev, SYS_RES_IRQ,
361		    key->irq_rid, key->irq_res);
362	if (callout_pending(&key->repeat_callout))
363		callout_drain(&key->repeat_callout);
364	if (callout_pending(&key->debounce_callout))
365		callout_drain(&key->debounce_callout);
366	if (key->pin)
367		gpio_pin_release(key->pin);
368	GPIOKEY_UNLOCK(key);
369
370	GPIOKEY_LOCK_DESTROY(key);
371}
372
373static int
374gpiokeys_probe(device_t dev)
375{
376	if (!ofw_bus_is_compatible(dev, "gpio-keys"))
377		return (ENXIO);
378
379	device_set_desc(dev, "GPIO keyboard");
380
381	return (0);
382}
383
384static int
385gpiokeys_attach(device_t dev)
386{
387	int unit;
388	struct gpiokeys_softc *sc;
389	keyboard_t *kbd;
390	phandle_t keys, child;
391	int total_keys;
392
393	if ((keys = ofw_bus_get_node(dev)) == -1)
394		return (ENXIO);
395
396	sc = device_get_softc(dev);
397	sc->sc_dev = dev;
398	kbd = &sc->sc_kbd;
399
400	GPIOKEYS_LOCK_INIT(sc);
401	unit = device_get_unit(dev);
402	kbd_init_struct(kbd, KBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
403
404	kbd->kb_data = (void *)sc;
405	sc->sc_mode = K_XLATE;
406
407	sc->sc_keymap = key_map;
408	sc->sc_accmap = accent_map;
409
410	kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap,
411	    sc->sc_fkeymap, GPIOKEYS_GLOBAL_NFKEY);
412
413	KBD_FOUND_DEVICE(kbd);
414
415	gpiokeys_clear_state(kbd);
416
417	KBD_PROBE_DONE(kbd);
418
419	KBD_INIT_DONE(kbd);
420
421	if (kbd_register(kbd) < 0) {
422		goto detach;
423	}
424
425	KBD_CONFIG_DONE(kbd);
426
427	gpiokeys_enable(kbd);
428
429#ifdef KBD_INSTALL_CDEV
430	if (kbd_attach(kbd)) {
431		goto detach;
432	}
433#endif
434
435	if (bootverbose) {
436		kbdd_diag(kbd, 1);
437	}
438
439	total_keys = 0;
440
441	/* Traverse the 'gpio-keys' node and count keys */
442	for (child = OF_child(keys); child != 0; child = OF_peer(child)) {
443		if (!OF_hasprop(child, "gpios"))
444			continue;
445		total_keys++;
446	}
447
448	if (total_keys) {
449		sc->sc_keys =  malloc(sizeof(struct gpiokey) * total_keys,
450		    M_DEVBUF, M_WAITOK | M_ZERO);
451
452		sc->sc_total_keys = 0;
453		/* Traverse the 'gpio-keys' node and count keys */
454		for (child = OF_child(keys); child != 0; child = OF_peer(child)) {
455			if (!OF_hasprop(child, "gpios"))
456				continue;
457			gpiokeys_attach_key(sc, child ,&sc->sc_keys[sc->sc_total_keys]);
458			sc->sc_total_keys++;
459		}
460	}
461
462	return (0);
463
464detach:
465	gpiokeys_detach(dev);
466	return (ENXIO);
467}
468
469static int
470gpiokeys_detach(device_t dev)
471{
472	struct gpiokeys_softc *sc;
473	keyboard_t *kbd;
474	int i;
475
476	sc = device_get_softc(dev);
477
478	for (i = 0; i < sc->sc_total_keys; i++)
479		gpiokeys_detach_key(sc, &sc->sc_keys[i]);
480
481	kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME,
482	    device_get_unit(dev)));
483
484#ifdef KBD_INSTALL_CDEV
485	kbd_detach(kbd);
486#endif
487	kbd_unregister(kbd);
488
489	GPIOKEYS_LOCK_DESTROY(sc);
490	if (sc->sc_keys)
491		free(sc->sc_keys, M_DEVBUF);
492
493	return (0);
494}
495
496/* early keyboard probe, not supported */
497static int
498gpiokeys_configure(int flags)
499{
500	return (0);
501}
502
503/* detect a keyboard, not used */
504static int
505gpiokeys__probe(int unit, void *arg, int flags)
506{
507	return (ENXIO);
508}
509
510/* reset and initialize the device, not used */
511static int
512gpiokeys_init(int unit, keyboard_t **kbdp, void *arg, int flags)
513{
514	return (ENXIO);
515}
516
517/* test the interface to the device, not used */
518static int
519gpiokeys_test_if(keyboard_t *kbd)
520{
521	return (0);
522}
523
524/* finish using this keyboard, not used */
525static int
526gpiokeys_term(keyboard_t *kbd)
527{
528	return (ENXIO);
529}
530
531/* keyboard interrupt routine, not used */
532static int
533gpiokeys_intr(keyboard_t *kbd, void *arg)
534{
535	return (0);
536}
537
538/* lock the access to the keyboard, not used */
539static int
540gpiokeys_lock(keyboard_t *kbd, int lock)
541{
542	return (1);
543}
544
545/*
546 * Enable the access to the device; until this function is called,
547 * the client cannot read from the keyboard.
548 */
549static int
550gpiokeys_enable(keyboard_t *kbd)
551{
552	struct gpiokeys_softc *sc;
553
554	sc = kbd->kb_data;
555	GPIOKEYS_LOCK(sc);
556	KBD_ACTIVATE(kbd);
557	GPIOKEYS_UNLOCK(sc);
558
559	return (0);
560}
561
562/* disallow the access to the device */
563static int
564gpiokeys_disable(keyboard_t *kbd)
565{
566	struct gpiokeys_softc *sc;
567
568	sc = kbd->kb_data;
569	GPIOKEYS_LOCK(sc);
570	KBD_DEACTIVATE(kbd);
571	GPIOKEYS_UNLOCK(sc);
572
573	return (0);
574}
575
576static void
577gpiokeys_do_poll(struct gpiokeys_softc *sc, uint8_t wait)
578{
579
580	KASSERT((sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) != 0,
581	    ("gpiokeys_do_poll called when not polling\n"));
582
583	GPIOKEYS_ASSERT_LOCKED(sc);
584
585	if (!kdb_active && !SCHEDULER_STOPPED()) {
586		while (sc->sc_inputs == 0) {
587			kern_yield(PRI_UNCHANGED);
588			if (!wait)
589				break;
590		}
591		return;
592	}
593
594	while ((sc->sc_inputs == 0) && wait) {
595		printf("POLL!\n");
596	}
597}
598
599/* check if data is waiting */
600static int
601gpiokeys_check(keyboard_t *kbd)
602{
603	struct gpiokeys_softc *sc = kbd->kb_data;
604
605	GPIOKEYS_ASSERT_LOCKED(sc);
606
607	if (!KBD_IS_ACTIVE(kbd))
608		return (0);
609
610	if (sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING)
611		gpiokeys_do_poll(sc, 0);
612
613	if (sc->sc_inputs > 0) {
614		return (1);
615	}
616	return (0);
617}
618
619/* check if char is waiting */
620static int
621gpiokeys_check_char_locked(keyboard_t *kbd)
622{
623	if (!KBD_IS_ACTIVE(kbd))
624		return (0);
625
626	return (gpiokeys_check(kbd));
627}
628
629static int
630gpiokeys_check_char(keyboard_t *kbd)
631{
632	int result;
633	struct gpiokeys_softc *sc = kbd->kb_data;
634
635	GPIOKEYS_LOCK(sc);
636	result = gpiokeys_check_char_locked(kbd);
637	GPIOKEYS_UNLOCK(sc);
638
639	return (result);
640}
641
642static int32_t
643gpiokeys_get_key(struct gpiokeys_softc *sc, uint8_t wait)
644{
645	int32_t c;
646
647	KASSERT((!kdb_active && !SCHEDULER_STOPPED())
648	    || (sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) != 0,
649	    ("not polling in kdb or panic\n"));
650
651	GPIOKEYS_ASSERT_LOCKED(sc);
652
653	if (sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING)
654		gpiokeys_do_poll(sc, wait);
655
656	if (sc->sc_inputs == 0) {
657		c = -1;
658	} else {
659		c = sc->sc_input[sc->sc_inputhead];
660		--(sc->sc_inputs);
661		++(sc->sc_inputhead);
662		if (sc->sc_inputhead >= GPIOKEYS_GLOBAL_IN_BUF_SIZE) {
663			sc->sc_inputhead = 0;
664		}
665	}
666
667	return (c);
668}
669
670/* read one byte from the keyboard if it's allowed */
671static int
672gpiokeys_read(keyboard_t *kbd, int wait)
673{
674	struct gpiokeys_softc *sc = kbd->kb_data;
675	int32_t keycode;
676
677	if (!KBD_IS_ACTIVE(kbd))
678		return (-1);
679
680	/* XXX */
681	keycode = gpiokeys_get_key(sc, (wait == FALSE) ? 0 : 1);
682	if (!KBD_IS_ACTIVE(kbd) || (keycode == -1))
683		return (-1);
684
685	++(kbd->kb_count);
686
687	return (keycode);
688}
689
690/* read char from the keyboard */
691static uint32_t
692gpiokeys_read_char_locked(keyboard_t *kbd, int wait)
693{
694	struct gpiokeys_softc *sc = kbd->kb_data;
695	uint32_t action;
696	uint32_t keycode;
697
698	if (!KBD_IS_ACTIVE(kbd))
699		return (NOKEY);
700
701next_code:
702
703	/* see if there is something in the keyboard port */
704	/* XXX */
705	keycode = gpiokeys_get_key(sc, (wait == FALSE) ? 0 : 1);
706	++kbd->kb_count;
707
708	/* return the byte as is for the K_RAW mode */
709	if (sc->sc_mode == K_RAW) {
710		return (keycode);
711	}
712
713	/* return the key code in the K_CODE mode */
714	/* XXX: keycode |= SCAN_RELEASE; */
715
716	if (sc->sc_mode == K_CODE) {
717		return (keycode);
718	}
719
720	/* keycode to key action */
721	action = genkbd_keyaction(kbd, SCAN_CHAR(keycode),
722	    (keycode & SCAN_RELEASE),
723	    &sc->sc_state, &sc->sc_accents);
724	if (action == NOKEY) {
725		goto next_code;
726	}
727
728	return (action);
729}
730
731/* Currently wait is always false. */
732static uint32_t
733gpiokeys_read_char(keyboard_t *kbd, int wait)
734{
735	uint32_t keycode;
736	struct gpiokeys_softc *sc = kbd->kb_data;
737
738	GPIOKEYS_LOCK(sc);
739	keycode = gpiokeys_read_char_locked(kbd, wait);
740	GPIOKEYS_UNLOCK(sc);
741
742	return (keycode);
743}
744
745/* some useful control functions */
746static int
747gpiokeys_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
748{
749	struct gpiokeys_softc *sc = kbd->kb_data;
750#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
751    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
752	int ival;
753
754#endif
755
756	switch (cmd) {
757	case KDGKBMODE:		/* get keyboard mode */
758		*(int *)arg = sc->sc_mode;
759		break;
760#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
761    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
762	case _IO('K', 7):
763		ival = IOCPARM_IVAL(arg);
764		arg = (caddr_t)&ival;
765		/* FALLTHROUGH */
766#endif
767	case KDSKBMODE:		/* set keyboard mode */
768		switch (*(int *)arg) {
769		case K_XLATE:
770			if (sc->sc_mode != K_XLATE) {
771				/* make lock key state and LED state match */
772				sc->sc_state &= ~LOCK_MASK;
773				sc->sc_state |= KBD_LED_VAL(kbd);
774			}
775			/* FALLTHROUGH */
776		case K_RAW:
777		case K_CODE:
778			if (sc->sc_mode != *(int *)arg) {
779				if ((sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) == 0)
780					gpiokeys_clear_state(kbd);
781				sc->sc_mode = *(int *)arg;
782			}
783			break;
784		default:
785			return (EINVAL);
786		}
787		break;
788
789	case KDGETLED:			/* get keyboard LED */
790		*(int *)arg = KBD_LED_VAL(kbd);
791		break;
792#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
793    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
794	case _IO('K', 66):
795		ival = IOCPARM_IVAL(arg);
796		arg = (caddr_t)&ival;
797		/* FALLTHROUGH */
798#endif
799	case KDSETLED:			/* set keyboard LED */
800		KBD_LED_VAL(kbd) = *(int *)arg;
801		break;
802	case KDGKBSTATE:		/* get lock key state */
803		*(int *)arg = sc->sc_state & LOCK_MASK;
804		break;
805#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
806    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
807	case _IO('K', 20):
808		ival = IOCPARM_IVAL(arg);
809		arg = (caddr_t)&ival;
810		/* FALLTHROUGH */
811#endif
812	case KDSKBSTATE:		/* set lock key state */
813		if (*(int *)arg & ~LOCK_MASK) {
814			return (EINVAL);
815		}
816		sc->sc_state &= ~LOCK_MASK;
817		sc->sc_state |= *(int *)arg;
818		return (0);
819
820	case KDSETREPEAT:		/* set keyboard repeat rate (new
821					 * interface) */
822		if (!KBD_HAS_DEVICE(kbd)) {
823			return (0);
824		}
825		if (((int *)arg)[1] < 0) {
826			return (EINVAL);
827		}
828		if (((int *)arg)[0] < 0) {
829			return (EINVAL);
830		}
831		if (((int *)arg)[0] < 200)	/* fastest possible value */
832			kbd->kb_delay1 = 200;
833		else
834			kbd->kb_delay1 = ((int *)arg)[0];
835		kbd->kb_delay2 = ((int *)arg)[1];
836		return (0);
837
838#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
839    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
840	case _IO('K', 67):
841		ival = IOCPARM_IVAL(arg);
842		arg = (caddr_t)&ival;
843		/* FALLTHROUGH */
844#endif
845	case KDSETRAD:			/* set keyboard repeat rate (old
846					 * interface) */
847		return (gpiokeys_set_typematic(kbd, *(int *)arg));
848
849	case PIO_KEYMAP:		/* set keyboard translation table */
850	case OPIO_KEYMAP:		/* set keyboard translation table
851					 * (compat) */
852	case PIO_KEYMAPENT:		/* set keyboard translation table
853					 * entry */
854	case PIO_DEADKEYMAP:		/* set accent key translation table */
855		sc->sc_accents = 0;
856		/* FALLTHROUGH */
857	default:
858		return (genkbd_commonioctl(kbd, cmd, arg));
859	}
860
861	return (0);
862}
863
864static int
865gpiokeys_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
866{
867	int result;
868	struct gpiokeys_softc *sc;
869
870	sc = kbd->kb_data;
871	/*
872	 * XXX Check if someone is calling us from a critical section:
873	 */
874	if (curthread->td_critnest != 0)
875		return (EDEADLK);
876
877	GPIOKEYS_LOCK(sc);
878	result = gpiokeys_ioctl_locked(kbd, cmd, arg);
879	GPIOKEYS_UNLOCK(sc);
880
881	return (result);
882}
883
884/* clear the internal state of the keyboard */
885static void
886gpiokeys_clear_state(keyboard_t *kbd)
887{
888	struct gpiokeys_softc *sc = kbd->kb_data;
889
890	sc->sc_flags &= ~(GPIOKEYS_GLOBAL_FLAG_POLLING);
891	sc->sc_state &= LOCK_MASK;	/* preserve locking key state */
892	sc->sc_accents = 0;
893}
894
895/* get the internal state, not used */
896static int
897gpiokeys_get_state(keyboard_t *kbd, void *buf, size_t len)
898{
899	return (len == 0) ? 1 : -1;
900}
901
902/* set the internal state, not used */
903static int
904gpiokeys_set_state(keyboard_t *kbd, void *buf, size_t len)
905{
906	return (EINVAL);
907}
908
909static int
910gpiokeys_poll(keyboard_t *kbd, int on)
911{
912	struct gpiokeys_softc *sc = kbd->kb_data;
913
914	GPIOKEYS_LOCK(sc);
915	if (on)
916		sc->sc_flags |= GPIOKEYS_GLOBAL_FLAG_POLLING;
917	else
918		sc->sc_flags &= ~GPIOKEYS_GLOBAL_FLAG_POLLING;
919	GPIOKEYS_UNLOCK(sc);
920
921	return (0);
922}
923
924static int
925gpiokeys_set_typematic(keyboard_t *kbd, int code)
926{
927	static const int delays[] = {250, 500, 750, 1000};
928	static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63,
929		68, 76, 84, 92, 100, 110, 118, 126,
930		136, 152, 168, 184, 200, 220, 236, 252,
931	272, 304, 336, 368, 400, 440, 472, 504};
932
933	if (code & ~0x7f) {
934		return (EINVAL);
935	}
936	kbd->kb_delay1 = delays[(code >> 5) & 3];
937	kbd->kb_delay2 = rates[code & 0x1f];
938	return (0);
939}
940
941static void
942gpiokeys_event_keyinput(struct gpiokeys_softc *sc)
943{
944	int c;
945
946	if ((sc->sc_flags & GPIOKEYS_GLOBAL_FLAG_POLLING) != 0)
947		return;
948
949	if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
950	    KBD_IS_BUSY(&sc->sc_kbd)) {
951		/* let the callback function process the input */
952		(sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
953		    sc->sc_kbd.kb_callback.kc_arg);
954	} else {
955		/* read and discard the input, no one is waiting for it */
956		do {
957			c = gpiokeys_read_char(&sc->sc_kbd, 0);
958		} while (c != NOKEY);
959	}
960}
961
962static keyboard_switch_t gpiokeyssw = {
963	.probe = &gpiokeys__probe,
964	.init = &gpiokeys_init,
965	.term = &gpiokeys_term,
966	.intr = &gpiokeys_intr,
967	.test_if = &gpiokeys_test_if,
968	.enable = &gpiokeys_enable,
969	.disable = &gpiokeys_disable,
970	.read = &gpiokeys_read,
971	.check = &gpiokeys_check,
972	.read_char = &gpiokeys_read_char,
973	.check_char = &gpiokeys_check_char,
974	.ioctl = &gpiokeys_ioctl,
975	.lock = &gpiokeys_lock,
976	.clear_state = &gpiokeys_clear_state,
977	.get_state = &gpiokeys_get_state,
978	.set_state = &gpiokeys_set_state,
979	.poll = &gpiokeys_poll,
980};
981
982KEYBOARD_DRIVER(gpiokeys, gpiokeyssw, gpiokeys_configure);
983
984static int
985gpiokeys_driver_load(module_t mod, int what, void *arg)
986{
987	switch (what) {
988	case MOD_LOAD:
989		kbd_add_driver(&gpiokeys_kbd_driver);
990		break;
991	case MOD_UNLOAD:
992		kbd_delete_driver(&gpiokeys_kbd_driver);
993		break;
994	}
995	return (0);
996}
997
998static devclass_t gpiokeys_devclass;
999
1000static device_method_t gpiokeys_methods[] = {
1001	DEVMETHOD(device_probe,		gpiokeys_probe),
1002	DEVMETHOD(device_attach,	gpiokeys_attach),
1003	DEVMETHOD(device_detach,	gpiokeys_detach),
1004
1005	DEVMETHOD_END
1006};
1007
1008static driver_t gpiokeys_driver = {
1009	"gpiokeys",
1010	gpiokeys_methods,
1011	sizeof(struct gpiokeys_softc),
1012};
1013
1014DRIVER_MODULE(gpiokeys, simplebus, gpiokeys_driver, gpiokeys_devclass, gpiokeys_driver_load, 0);
1015MODULE_VERSION(gpiokeys, 1);
1016