1
/*****************************************************************************
2
* Copyright (c) 2013 IBM Corporation
4
* This program and the accompanying materials
5
* are made available under the terms of the BSD License
6
* which accompanies this distribution, and is available at
7
* http://www.opensource.org/licenses/bsd-license.php
10
* IBM Corporation - initial implementation
11
*****************************************************************************/
21
* HID Spec Version 1.11
24
#define HID_REQ_GET_REPORT 0x01
25
#define HID_REQ_GET_IDLE 0x02
26
#define HID_REQ_GET_PROTOCOL 0x03
27
#define HID_REQ_SET_REPORT 0x09
28
#define HID_REQ_SET_IDLE 0x0A
29
#define HID_REQ_SET_PROTOCOL 0x0B
31
//key position for latin letters
32
#define KEYP_LATIN_A 4
33
#define KEYP_LATIN_Z 29
37
/* HID SPEC - 7.2.6 Set_Protocol Request */
38
static int usb_hid_set_protocol(struct usb_dev *dev, uint16_t value)
40
struct usb_dev_req req;
43
req.bmRequestType = REQT_TYPE_CLASS | REQT_REC_INTERFACE | REQT_DIR_OUT;
44
req.bRequest = HID_REQ_SET_PROTOCOL;
45
req.wValue = cpu_to_le16(value);
46
req.wIndex = cpu_to_le16(dev->intf_num);
48
return usb_send_ctrl(dev->control, &req, NULL);
51
/* HID SPEC - 7.2.4 Set_Idle Request */
52
static int usb_hid_set_idle(struct usb_dev *dev, uint16_t ms_delay)
54
struct usb_dev_req req;
57
req.bmRequestType = REQT_TYPE_CLASS | REQT_REC_INTERFACE | REQT_DIR_OUT;
58
req.bRequest = HID_REQ_SET_IDLE;
59
req.wValue = cpu_to_le16((ms_delay/4) << 8);
60
req.wIndex = cpu_to_le16(dev->intf_num);
62
return usb_send_ctrl(dev->control, &req, NULL);
65
/* HID SPEC - 7.2.1 Get Report Request */
66
static int usb_hid_get_report(struct usb_dev *dev, void *data, size_t size)
68
struct usb_dev_req req;
71
req.bmRequestType = REQT_TYPE_CLASS | REQT_REC_INTERFACE | REQT_DIR_IN;
72
req.bRequest = HID_REQ_GET_REPORT;
73
req.wIndex = cpu_to_le16(dev->intf_num);
75
req.wLength = cpu_to_le16((uint16_t)size);
76
req.wValue = cpu_to_le16(1 << 8);
77
return usb_send_ctrl(dev->control, &req, data);
80
/* ring buffer with RD/WR indices for key buffering */
81
static uint8_t keybuf[256]; /* size fixed to byte range ! */
82
uint8_t r_ptr = 0; /* RD-index for Keyboard-Buffer */
83
uint8_t w_ptr = 0; /* WR-index for Keyboard-Buffer */
85
/* variables for LED status */
87
const uint8_t *key_std = NULL;
88
const uint8_t *key_std_shift = NULL;
92
* read character from Keyboard-Buffer
96
* = 0 if no key available
98
static int read_key(void)
101
return (int)keybuf[r_ptr++];
107
* Store character into Keyboard-Buffer
109
* @param Key = detected ASCII-Key (> 0)
112
static void write_key(uint8_t key)
114
if ((w_ptr + 1) != r_ptr)
115
keybuf[w_ptr++] = key;
119
* Checks if keypos is a latin key
123
static bool is_latin(uint8_t keypos)
125
return keypos >= KEYP_LATIN_A && keypos <= KEYP_LATIN_Z;
129
* Convert keyboard usage-ID to ANSI-Code
131
* @param Ctrl=Modifier Byte
132
* Key =Usage ID from USB Keyboard
135
static void get_char(uint8_t ctrl, uint8_t keypos)
141
printf("pos %02X\n", keypos);
144
if (set_leds & LED_CAPS_LOCK) /* is CAPS Lock set ? */
147
/* caps is a shift only for latin chars */
148
if ((!caps && ctrl == 0) || (caps && !is_latin(keypos))) {
149
ch = key_std[keypos];
155
if ((ctrl & MODIFIER_SHIFT) || caps) {
156
ch = key_std_shift[keypos];
162
if (ctrl & MODIFIER_CTRL) {
163
ch = keycodes_ctrl[keypos];
169
if (ctrl == MODIFIER_ALT_GR) {
170
ch = keycodes_alt_GR[keypos];
177
static void check_key_code(uint8_t *buf)
179
static uint8_t key_last[6]; /* list of processed keys */
180
uint8_t i, j, key_pos;
182
/* set translation table to defaults */
183
if ((key_std == NULL) || (key_std_shift == NULL)) {
184
key_std = keycodes_std_US;
185
key_std_shift = keycodes_shift_US;
188
if (buf[0] & MODIFIER_SHIFT) /* any shift key pressed ? */
189
set_leds &= ~LED_CAPS_LOCK; /* CAPS-LOCK-LED always off */
191
i = 2; /* skip modifier byte and reserved byte */
194
if ((key_pos != 0) && (key_pos <= 100)) { /* support for 101 keys */
196
/* search if already processed */
197
while ((j < 6) && (key_pos != key_last[j]))
200
if (j >= 6) { /* not found (= not processed) */
202
case 0x39: /* caps-lock key ? */
203
case 0x32: /* caps-lock key ? */
204
set_leds ^= LED_CAPS_LOCK;
222
write_key(0x1b); /* F3 */
229
write_key(0x1b); /* F4 */
236
write_key(0x1b); /* F5 */
244
write_key(0x1b); /* F6 */
252
write_key(0x1b); /* F7 */
260
write_key(0x1b); /* F8 */
268
write_key(0x1b); /* F9 */
276
write_key(0x1b); /* F10 */
284
write_key(0x1b); /* F11 */
292
write_key(0x1b); /* F12 */
299
case 0x47: /* scroll-lock key ? */
300
set_leds ^= LED_SCROLL_LOCK;
304
write_key(0x1b); /* INS */
311
write_key(0x1b); /* HOME */
317
write_key(0x1b); /* PgUp */
324
write_key(0x1b); /* DEL */
331
write_key(0x1b); /* END */
337
write_key(0x1b); /* PgDn */
344
write_key(0x1b); /* R-Arrow */
350
write_key(0x1b); /* L-Arrow */
356
write_key(0x1b); /* D-Arrow */
362
write_key(0x1b); /* U-Arrow */
367
case 0x53: /* num-lock key ? */
368
set_leds ^= LED_NUM_LOCK;
372
/* convert key position to ASCII code */
373
get_char(buf[0], key_pos);
380
/*****************************************/
381
/* all keys are processed, create a copy */
382
/* to flag them as processed */
383
/*****************************************/
384
for (i = 2, j = 0; j < 6; i++, j++)
385
key_last[j] = buf[i]; /* copy all actual keys to last */
388
#define USB_HID_SIZE 128
389
uint32_t *kbd_buffer;
391
int usb_hid_kbd_init(struct usb_dev *dev)
396
usb_hid_set_protocol(dev, 0);
397
usb_hid_set_idle(dev, 500);
400
if (usb_hid_get_report(dev, key, 8))
403
kbd_buffer = SLOF_dma_alloc(USB_HID_SIZE);
405
printf("%s: unable to allocate keyboard buffer\n", __func__);
410
printf("HID kbd init %d\n", dev->ep_cnt);
412
for (i = 0; i < dev->ep_cnt; i++) {
413
if ((dev->ep[i].bmAttributes & USB_EP_TYPE_MASK)
415
usb_dev_populate_pipe(dev, &dev->ep[i], kbd_buffer, USB_HID_SIZE);
420
int usb_hid_kbd_exit(struct usb_dev *dev)
423
usb_put_pipe(dev->intr);
426
SLOF_dma_free(kbd_buffer, USB_HID_SIZE);
430
static int usb_poll_key(void *vdev)
432
struct usb_dev *dev = vdev;
437
rc = usb_poll_intr(dev->intr, key);
443
unsigned char usb_key_available(void *dev)
455
unsigned char usb_read_keyb(void *vdev)
457
if (usb_key_available(vdev))