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