1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12/**
13 * @brief USB Keyboard Driver
14 * @see USB HID spec, Appendix B
15 */
16#include <string.h>
17#include <stdlib.h>
18#include <stdio.h>
19
20#include "../services.h"
21#include "hid.h"
22#include "usbkbd.h"
23
24#define KBD_ENABLE_IRQS
25
26#define KBD_REPEAT_RATE_MS   200
27#define KBD_REPEAT_DELAY_MS 1000
28
29/*
30 * Ring buffer for key logging
31 */
32
33struct ringbuf {
34	char b[100];
35	int head;
36	int tail;
37	int size;
38};
39
40static void rb_init(struct ringbuf *rb)
41{
42	rb->head = 0;
43	rb->tail = 0;
44	rb->size = 0;
45}
46
47static int rb_produce(struct ringbuf *rb, const char *str, int size)
48{
49	if (sizeof(rb->b) / sizeof(*rb->b) - rb->size >= size) {
50		while (size--) {
51			rb->b[rb->tail++] = *str++;
52			if (rb->tail == sizeof(rb->b) / sizeof(*rb->b)) {
53				rb->tail = 0;
54			}
55			rb->size++;
56		}
57		return 0;
58	} else {
59		return 1;
60	}
61}
62
63static int rb_consume(struct ringbuf *rb)
64{
65	char c;
66	if (rb->size) {
67		c = rb->b[rb->head++];
68		if (rb->head == sizeof(rb->b) / sizeof(*rb->b)) {
69			rb->head = 0;
70		}
71		rb->size--;
72		return ((int)c) & 0xff;
73	}
74	return -1;
75}
76
77/*
78 * Keyboard driver
79 */
80
81#define KBDRPT_RATE  ((KBD_REPEAT_RATE_MS + 3) / 4)
82#define KBDRPT_DELAY ((KBD_REPEAT_DELAY_MS + 3) / 4)
83#define KBD_PROTOCOL 1
84#define KBD_KEYS_SIZE   8
85
86#define KBDIND_CAPS    0x2
87#define KBDIND_NUM     0x1
88#define KBDIND_SCRL    0x4
89
90struct usb_kbd_device {
91	struct usb_dev *udev;
92	struct usb_hid_device *hid;
93	struct endpoint *ep_int;
94	struct xact int_xact;
95/// Indicator state. This is a pointer to our universal buffer at index 1
96	uint8_t ind;
97/// Store old keys for repeat detection
98	uint8_t old_keys[KBD_KEYS_SIZE];
99/// new keys is a pointer to our interrupt buffer
100	uint8_t *new_keys;
101/// Cache the current repeat rate to avoid USB transfers
102	int repeat_rate;
103/// ring buffer for characters waiting to be read by the application.
104	struct ringbuf rb;
105};
106
107#define KBDFN_CTRL   0x01
108#define KBDFN_SHIFT  0x02
109#define KBDFN_ALT    0x04
110#define KBDFN_WIN    0x08
111#define KBDFN_LEFT(FN)     ((KBDFN_##FN) << 0)
112#define KBDFN_RIGHT(FN)    ((KBDFN_##FN) << 4)
113#define KBDFN_TEST(FN, x)  !!((x) & (KBDFN_LEFT(FN) | KBDFN_RIGHT(FN)))
114static const char std_kcodes[] = {
115	/*       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
116	/*0x00 */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
117	/*0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
118	/*0x20 */ '3', '4', '5', '6', '7', '8', '9', '0', 10, 27, 8, 9, ' ', '-', '=', '[',
119	/*0x30 */ ']', 92, 0, ';', 39, '`', ',', '.', '/'
120};
121
122static const char stdshift_kcodes[] = {
123	/*       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
124	/*0x00 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
125	/*0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
126	/*0x20 */ '#', '$', '%', '^', '&', '*', '(', ')', 10, 27, 8, 9, ' ', '_', '+', '{',
127	/*0x30 */ '}', '|', 0, ':', 39, '~', '<', '>', '?'
128};
129
130static const char num_kcodes[] = {
131	/*       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
132	/*0x50 */ '/', '*', '-', '+', 10, '1', '2', '3', '4', '5', '6', '7',
133	/*0x60 */ '8', '9', '0', '.'
134};
135
136#define KBDKEY_NONE       0x00
137#define KBDKEY_MASH       0x01
138#define KBDKEY_NUMLOCK    0x53
139#define KBDKEY_CAPSLOCK   0x39
140#define KBDKEY_SCROLLLOCK 0x47
141
142static int kbd_update_ind(struct usb_kbd_device *kbd)
143{
144	int err;
145
146	err = usb_hid_set_report(kbd->hid, REPORT_OUTPUT, &kbd->ind, 1);
147
148	return err;
149}
150
151static int kbd_update_repeat_rate(struct usb_kbd_device *kbd)
152{
153	ZF_LOGD("Changing rate to %dms\n", kbd->repeat_rate * 4);
154
155	return usb_hid_set_idle(kbd->hid, kbd->repeat_rate);
156}
157
158static int
159kbd_irq_handler(void *token, enum usb_xact_status stat, int bytes_remaining)
160{
161	struct usb_kbd_device *kbd = (struct usb_kbd_device *)token;
162	uint8_t afn;
163	uint8_t key;
164	int new_rate = -1;
165	char c;
166	int len;
167
168	/* Check the status */
169	if (stat != XACTSTAT_SUCCESS) {
170		ZF_LOGD("Received unsuccessful IRQ\n");
171		return 1;
172	}
173	len = kbd->int_xact.len - bytes_remaining;
174	if (len < 4) {
175		ZF_LOGD("Short read on INT packet (%d)\n", len);
176		return 1;
177	}
178#if defined(KBDIRQ_DEBUG)
179	{
180		int i;
181		for (i = 0; i < len; i++) {
182			printf("[0x%02x]", kbd->new_keys[i]);
183		}
184		printf("\n");
185	}
186#endif
187
188	/* Multiple key press. Ignore input */
189	if (kbd->new_keys[3] != KBDKEY_NONE) {
190		kbd->new_keys[2] = kbd->old_keys[2] = KBDKEY_NONE;
191	}
192	/* Read in key parameters */
193	afn = kbd->new_keys[0];
194	key = kbd->new_keys[2];
195	/* Handle repeat delay */
196	if (key == KBDKEY_NONE) {
197		/* No key pressed or someone is being a jerk - idle */
198		new_rate = 0;
199	} else if (kbd->old_keys[2] == key) {
200		/* Someone is holding down a key */
201		new_rate = KBDRPT_RATE;
202	} else {
203		/* Someone pressed a new key! Start repeat delay */
204		new_rate = KBDRPT_DELAY;
205	}
206	/* Adjust the idle delay if required */
207	if (new_rate != kbd->repeat_rate) {
208		kbd->repeat_rate = new_rate;
209		kbd_update_repeat_rate(kbd);
210	}
211	/* Process the key */
212	memcpy(kbd->old_keys, kbd->new_keys, KBD_KEYS_SIZE);
213	if (key == KBDKEY_NONE || key == KBDKEY_MASH) {
214		/* Ignore it */
215	} else if (key < 0x04) {
216		printf("<!0x%x>", key);
217	} else if (key < 0x39) {
218		char cl;
219		/* Decode the key */
220		c = std_kcodes[key - 0x04];
221		if (KBDFN_TEST(CTRL, afn) && c >= '@' && c <= '_') {
222			c -= '@';
223		} else if (KBDFN_TEST(SHIFT, afn)) {
224			c = stdshift_kcodes[key - 0x04];
225		}
226		/* Check and update for capslock */
227		cl = c | 0x20;
228		if (cl >= 'a' && cl <= 'z' && (kbd->ind & KBDIND_CAPS)) {
229			c ^= 0x20;
230		}
231		/* Register the character */
232		if (KBDFN_TEST(ALT, afn)) {
233			char str[2] = { 0x1B, c };
234			rb_produce(&kbd->rb, str, 2);
235		} else {
236			rb_produce(&kbd->rb, &c, 1);
237		}
238	} else if (key == KBDKEY_NUMLOCK) {
239		kbd->ind ^= KBDIND_NUM;
240		kbd_update_ind(kbd);
241	} else if (key == KBDKEY_CAPSLOCK) {
242		kbd->ind ^= KBDIND_CAPS;
243		kbd_update_ind(kbd);
244	} else if (key == KBDKEY_SCROLLLOCK) {
245		kbd->ind ^= KBDIND_SCRL;
246		kbd_update_ind(kbd);
247	} else if (key < 0x54) {
248		/* TODO handle these codes (see below) */
249		printf("<!0x%x>", key);
250	} else if (key < 0x64 && (kbd->ind & KBDIND_NUM)) {
251		c = num_kcodes[key - 0x54];
252		rb_produce(&kbd->rb, &c, 1);
253	} else if (key < 0x66) {
254		/* TODO find scan codes for these keys and keypad
255		 * with no numlock */
256#if 0
257		F1 - F12 3 a - 45
258		    prntscrn / sysrq 46
259		    pause / break 48
260		    insert 49 home 4 a pgup 4 b delete 4 c end 4 d pgdwn 4e
261 right 4f left 50 down 51 up 52 macro 64 dropdown 65
262#endif
263		    printf("<!0x%x>", key);
264	} else {
265		printf("<!!0x%x>", key);
266	}
267
268	usbdev_schedule_xact(kbd->udev, kbd->ep_int, &kbd->int_xact, 1,
269			     &kbd_irq_handler, kbd);
270
271	return 1;
272}
273
274static ssize_t
275kbd_read(ps_chardevice_t *d, void *vdata, size_t bytes,
276	 chardev_callback_t cb, void *token)
277{
278	struct usb_kbd_device *kbd;
279	char *data;
280	int i;
281	kbd = (struct usb_kbd_device *)d->vaddr;
282	data = (char *)vdata;
283	for (i = 0; i < bytes; i++) {
284		int c;
285		c = rb_consume(&kbd->rb);
286		if (c >= 0) {
287			*data++ = c;
288		} else {
289			break;
290		}
291	}
292	return i;
293}
294
295int usb_kbd_driver_bind(usb_dev_t *usb_dev, struct ps_chardevice *cdev)
296{
297	struct usb_kbd_device *kbd;
298	int err;
299
300	kbd = (struct usb_kbd_device*)usb_malloc(sizeof(struct usb_kbd_device));
301	if (!kbd) {
302		ZF_LOGF("Out of memory\n");
303	}
304
305	usb_dev->dev_data = (struct udev_priv*)kbd;
306	kbd->udev = usb_dev;
307	kbd->repeat_rate = 0;
308	rb_init(&kbd->rb);
309
310	kbd->hid = usb_hid_alloc(usb_dev);
311
312	if (kbd->hid->protocol != 1) {
313		ZF_LOGF("Not a keyboard: %d\n", kbd->hid->protocol);
314	}
315
316	/* Find endpoint */
317	kbd->ep_int = usb_dev->ep[kbd->hid->iface];
318	if (kbd->ep_int == NULL || kbd->ep_int->type != EP_INTERRUPT) {
319		ZF_LOGF("Endpoint not found\n");
320	}
321
322	ZF_LOGD("Configuring keyboard\n");
323
324	err = usb_hid_set_idle(kbd->hid, 0);
325	if (err < 0) {
326		ZF_LOGF("Keyboard initialisation error\n");
327	}
328
329	cdev->vaddr = kbd;
330	cdev->read = kbd_read;
331
332	/* Initialise LEDS */
333	kbd_update_ind(kbd);
334
335	/* Initialise IRQs */
336	if (kbd->ep_int->dir == EP_DIR_IN) {
337		kbd->int_xact.type = PID_IN;
338	} else {
339		kbd->int_xact.type = PID_OUT;
340	}
341
342	kbd->int_xact.len = kbd->ep_int->max_pkt;
343
344	err = usb_alloc_xact(usb_dev->dman, &kbd->int_xact, 1);
345	if (err) {
346		ZF_LOGF("Out of DMA memory\n");
347	}
348
349	kbd->new_keys = xact_get_vaddr(&kbd->int_xact);
350
351#if defined(KBD_ENABLE_IRQS)
352	ZF_LOGD("Scheduling IRQS\n");
353	usbdev_schedule_xact(usb_dev, kbd->ep_int, &kbd->int_xact, 1,
354			     &kbd_irq_handler, kbd);
355#else
356	(void)kbd_irq_handler;
357#endif
358	ZF_LOGD("Successfully initialised\n");
359
360	return 0;
361}
362