~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/SLOF/lib/libusb/usb-hid.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * Copyright (c) 2013 IBM Corporation
 
3
 * All rights reserved.
 
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
 
8
 *
 
9
 * Contributors:
 
10
 *     IBM Corporation - initial implementation
 
11
 *****************************************************************************/
 
12
 
 
13
#include <stdio.h>
 
14
#include <string.h>
 
15
#include <termctrl.h>
 
16
 
 
17
#include "usb-core.h"
 
18
#include "usb-key.h"
 
19
 
 
20
/*
 
21
 * HID Spec Version 1.11
 
22
 */
 
23
 
 
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
 
30
 
 
31
//key position for latin letters
 
32
#define KEYP_LATIN_A 4
 
33
#define KEYP_LATIN_Z 29
 
34
 
 
35
//#define KEY_DEBUG
 
36
 
 
37
/* HID SPEC - 7.2.6 Set_Protocol Request */
 
38
static int usb_hid_set_protocol(struct usb_dev *dev, uint16_t value)
 
39
{
 
40
        struct usb_dev_req req;
 
41
        if (!dev)
 
42
                return false;
 
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);
 
47
        req.wLength = 0;
 
48
        return usb_send_ctrl(dev->control, &req, NULL);
 
49
}
 
50
 
 
51
/* HID SPEC - 7.2.4 Set_Idle Request */
 
52
static int usb_hid_set_idle(struct usb_dev *dev, uint16_t ms_delay)
 
53
{
 
54
        struct usb_dev_req req;
 
55
        if (!dev)
 
56
                return false;
 
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);
 
61
        req.wLength = 0;
 
62
        return usb_send_ctrl(dev->control, &req, NULL);
 
63
}
 
64
 
 
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)
 
67
{
 
68
        struct usb_dev_req req;
 
69
        if (!dev)
 
70
                return false;
 
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);
 
74
 
 
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);
 
78
}
 
79
 
 
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 */
 
84
 
 
85
/* variables for LED status */
 
86
uint8_t set_leds;
 
87
const uint8_t *key_std       = NULL;
 
88
const uint8_t *key_std_shift = NULL;
 
89
 
 
90
 
 
91
/**
 
92
 * read character from Keyboard-Buffer
 
93
 *
 
94
 * @param   -
 
95
 * @return  > 0  Keycode
 
96
 *          = 0  if no key available
 
97
 */
 
98
static int read_key(void)
 
99
{
 
100
        if (r_ptr != w_ptr)
 
101
                return (int)keybuf[r_ptr++];
 
102
        else
 
103
                return false;
 
104
}
 
105
 
 
106
/**
 
107
 * Store character into Keyboard-Buffer
 
108
 *
 
109
 * @param   Key = detected ASCII-Key (> 0)
 
110
 * @return  -
 
111
 */
 
112
static void write_key(uint8_t key)
 
113
{
 
114
        if ((w_ptr + 1) != r_ptr)
 
115
                keybuf[w_ptr++] = key;
 
116
}
 
117
 
 
118
/**
 
119
 * Checks if keypos is a latin key
 
120
 * @param  keypos
 
121
 * @return -
 
122
 */
 
123
static bool is_latin(uint8_t keypos)
 
124
{
 
125
        return keypos >= KEYP_LATIN_A && keypos <= KEYP_LATIN_Z;
 
126
}
 
127
 
 
128
/**
 
129
 * Convert keyboard usage-ID to ANSI-Code
 
130
 *
 
131
 * @param   Ctrl=Modifier Byte
 
132
 *          Key =Usage ID from USB Keyboard
 
133
 * @return  -
 
134
 */
 
135
static void get_char(uint8_t ctrl, uint8_t keypos)
 
136
{
 
137
        uint8_t ch;
 
138
        bool caps = false;
 
139
 
 
140
#ifdef KEY_DEBUG
 
141
        printf("pos %02X\n", keypos);
 
142
#endif
 
143
 
 
144
        if (set_leds & LED_CAPS_LOCK)                   /* is CAPS Lock set ? */
 
145
                caps = true;
 
146
 
 
147
        /* caps is a shift only for latin chars */
 
148
        if ((!caps && ctrl == 0) || (caps && !is_latin(keypos))) {
 
149
                ch = key_std[keypos];
 
150
                if (ch != 0)
 
151
                        write_key(ch);
 
152
                return;
 
153
        }
 
154
 
 
155
        if ((ctrl & MODIFIER_SHIFT) || caps) {
 
156
                ch = key_std_shift[keypos];
 
157
                if (ch != 0)
 
158
                        write_key(ch);
 
159
                return;
 
160
        }
 
161
 
 
162
        if (ctrl & MODIFIER_CTRL) {
 
163
                ch = keycodes_ctrl[keypos];
 
164
                if (ch != 0)
 
165
                        write_key(ch);
 
166
                return;
 
167
        }
 
168
 
 
169
        if (ctrl == MODIFIER_ALT_GR) {
 
170
                ch = keycodes_alt_GR[keypos];
 
171
                if (ch != 0)
 
172
                        write_key(ch);
 
173
                return;
 
174
        }
 
175
}
 
176
 
 
177
static void check_key_code(uint8_t *buf)
 
178
{
 
179
        static uint8_t key_last[6];                 /* list of processed keys */
 
180
        uint8_t i, j, key_pos;
 
181
 
 
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;
 
186
        }
 
187
 
 
188
        if (buf[0] & MODIFIER_SHIFT)       /* any shift key pressed ? */
 
189
                set_leds &= ~LED_CAPS_LOCK;       /* CAPS-LOCK-LED always off */
 
190
 
 
191
        i = 2;  /* skip modifier byte and reserved byte */
 
192
        while (i < 8) {
 
193
                key_pos = buf[i];
 
194
                if ((key_pos != 0) && (key_pos <= 100)) {    /* support for 101 keys */
 
195
                        j = 0;
 
196
                        /* search if already processed */
 
197
                        while ((j < 6) && (key_pos != key_last[j]))
 
198
                                j++;
 
199
 
 
200
                        if (j >= 6) {          /* not found (= not processed) */
 
201
                                switch (key_pos) {
 
202
                                case 0x39:                 /* caps-lock key ? */
 
203
                                case 0x32:                 /* caps-lock key ? */
 
204
                                        set_leds ^= LED_CAPS_LOCK;
 
205
                                        break;
 
206
 
 
207
                                case 0x3a:                              /* F1 */
 
208
                                        write_key(0x1b);
 
209
                                        write_key(0x5b);
 
210
                                        write_key(0x4f);
 
211
                                        write_key(0x50);
 
212
                                        break;
 
213
 
 
214
                                case 0x3b:                              /* F2 */
 
215
                                        write_key(0x1b);
 
216
                                        write_key(0x5b);
 
217
                                        write_key(0x4f);
 
218
                                        write_key(0x51);
 
219
                                        break;
 
220
 
 
221
                                case 0x3c:
 
222
                                        write_key(0x1b);               /* F3 */
 
223
                                        write_key(0x5b);
 
224
                                        write_key(0x4f);
 
225
                                        write_key(0x52);
 
226
                                        break;
 
227
 
 
228
                                case 0x3d:
 
229
                                        write_key(0x1b);                /* F4 */
 
230
                                        write_key(0x5b);
 
231
                                        write_key(0x4f);
 
232
                                        write_key(0x53);
 
233
                                        break;
 
234
 
 
235
                                case 0x3e:
 
236
                                        write_key(0x1b);                /* F5 */
 
237
                                        write_key(0x5b);
 
238
                                        write_key(0x31);
 
239
                                        write_key(0x35);
 
240
                                        write_key(0x7e);
 
241
                                        break;
 
242
 
 
243
                                case 0x3f:
 
244
                                        write_key(0x1b);                /* F6 */
 
245
                                        write_key(0x5b);
 
246
                                        write_key(0x31);
 
247
                                        write_key(0x37);
 
248
                                        write_key(0x7e);
 
249
                                        break;
 
250
 
 
251
                                case 0x40:
 
252
                                        write_key(0x1b);                /* F7 */
 
253
                                        write_key(0x5b);
 
254
                                        write_key(0x31);
 
255
                                        write_key(0x38);
 
256
                                        write_key(0x7e);
 
257
                                        break;
 
258
 
 
259
                                case 0x41:
 
260
                                        write_key(0x1b);                /* F8 */
 
261
                                        write_key(0x5b);
 
262
                                        write_key(0x31);
 
263
                                        write_key(0x39);
 
264
                                        write_key(0x7e);
 
265
                                        break;
 
266
 
 
267
                                case 0x42:
 
268
                                        write_key(0x1b);                /* F9 */
 
269
                                        write_key(0x5b);
 
270
                                        write_key(0x32);
 
271
                                        write_key(0x30);
 
272
                                        write_key(0x7e);
 
273
                                        break;
 
274
 
 
275
                                case 0x43:
 
276
                                        write_key(0x1b);               /* F10 */
 
277
                                        write_key(0x5b);
 
278
                                        write_key(0x32);
 
279
                                        write_key(0x31);
 
280
                                        write_key(0x7e);
 
281
                                        break;
 
282
 
 
283
                                case 0x44:
 
284
                                        write_key(0x1b);               /* F11 */
 
285
                                        write_key(0x5b);
 
286
                                        write_key(0x32);
 
287
                                        write_key(0x33);
 
288
                                        write_key(0x7e);
 
289
                                        break;
 
290
 
 
291
                                case 0x45:
 
292
                                        write_key(0x1b);               /* F12 */
 
293
                                        write_key(0x5b);
 
294
                                        write_key(0x32);
 
295
                                        write_key(0x34);
 
296
                                        write_key(0x7e);
 
297
                                        break;
 
298
 
 
299
                                case 0x47:               /* scroll-lock key ? */
 
300
                                        set_leds ^= LED_SCROLL_LOCK;
 
301
                                        break;
 
302
 
 
303
                                case 0x49:
 
304
                                        write_key(0x1b);               /* INS */
 
305
                                        write_key(0x5b);
 
306
                                        write_key(0x32);
 
307
                                        write_key(0x7e);
 
308
                                        break;
 
309
 
 
310
                                case 0x4a:
 
311
                                        write_key(0x1b);              /* HOME */
 
312
                                        write_key(0x4f);
 
313
                                        write_key(0x48);
 
314
                                        break;
 
315
 
 
316
                                case 0x4b:
 
317
                                        write_key(0x1b);              /* PgUp */
 
318
                                        write_key(0x5b);
 
319
                                        write_key(0x35);
 
320
                                        write_key(0x7e);
 
321
                                        break;
 
322
 
 
323
                                case 0x4c:
 
324
                                        write_key(0x1b);               /* DEL */
 
325
                                        write_key(0x5b);
 
326
                                        write_key(0x33);
 
327
                                        write_key(0x7e);
 
328
                                        break;
 
329
 
 
330
                                case 0x4d:
 
331
                                        write_key(0x1b);               /* END */
 
332
                                        write_key(0x4f);
 
333
                                        write_key(0x46);
 
334
                                        break;
 
335
 
 
336
                                case 0x4e:
 
337
                                        write_key(0x1b);              /* PgDn */
 
338
                                        write_key(0x5b);
 
339
                                        write_key(0x36);
 
340
                                        write_key(0x7e);
 
341
                                        break;
 
342
 
 
343
                                case 0x4f:
 
344
                                        write_key(0x1b);           /* R-Arrow */
 
345
                                        write_key(0x5b);
 
346
                                        write_key(0x43);
 
347
                                        break;
 
348
 
 
349
                                case 0x50:
 
350
                                        write_key(0x1b);           /* L-Arrow */
 
351
                                        write_key(0x5b);
 
352
                                        write_key(0x44);
 
353
                                        break;
 
354
 
 
355
                                case 0x51:
 
356
                                        write_key(0x1b);           /* D-Arrow */
 
357
                                        write_key(0x5b);
 
358
                                        write_key(0x42);
 
359
                                        break;
 
360
 
 
361
                                case 0x52:
 
362
                                        write_key(0x1b);           /* U-Arrow */
 
363
                                        write_key(0x5b);
 
364
                                        write_key(0x41);
 
365
                                        break;
 
366
 
 
367
                                case 0x53:                  /* num-lock key ? */
 
368
                                        set_leds ^= LED_NUM_LOCK;
 
369
                                        break;
 
370
 
 
371
                                default:
 
372
                                        /* convert key position to ASCII code */
 
373
                                        get_char(buf[0], key_pos);
 
374
                                        break;
 
375
                                }
 
376
                        }
 
377
                }
 
378
                i++;
 
379
        }
 
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 */
 
386
}
 
387
 
 
388
#define USB_HID_SIZE 128
 
389
uint32_t *kbd_buffer;
 
390
 
 
391
int usb_hid_kbd_init(struct usb_dev *dev)
 
392
{
 
393
        int i;
 
394
        uint8_t key[8];
 
395
 
 
396
        usb_hid_set_protocol(dev, 0);
 
397
        usb_hid_set_idle(dev, 500);
 
398
 
 
399
        memset(key, 0, 8);
 
400
        if (usb_hid_get_report(dev, key, 8))
 
401
                check_key_code(key);
 
402
 
 
403
        kbd_buffer = SLOF_dma_alloc(USB_HID_SIZE);
 
404
        if (!kbd_buffer) {
 
405
                printf("%s: unable to allocate keyboard buffer\n", __func__);
 
406
                return false;
 
407
        }
 
408
 
 
409
#ifdef KEY_DEBUG
 
410
        printf("HID kbd init %d\n", dev->ep_cnt);
 
411
#endif
 
412
        for (i = 0; i < dev->ep_cnt; i++) {
 
413
                if ((dev->ep[i].bmAttributes & USB_EP_TYPE_MASK)
 
414
                        == USB_EP_TYPE_INTR)
 
415
                        usb_dev_populate_pipe(dev, &dev->ep[i], kbd_buffer, USB_HID_SIZE);
 
416
        }
 
417
        return true;
 
418
}
 
419
 
 
420
int usb_hid_kbd_exit(struct usb_dev *dev)
 
421
{
 
422
        if (dev->intr) {
 
423
                usb_put_pipe(dev->intr);
 
424
                dev->intr = NULL;
 
425
        }
 
426
        SLOF_dma_free(kbd_buffer, USB_HID_SIZE);
 
427
        return true;
 
428
}
 
429
 
 
430
static int usb_poll_key(void *vdev)
 
431
{
 
432
        struct usb_dev *dev = vdev;
 
433
        uint8_t key[8];
 
434
        int rc;
 
435
 
 
436
        memset(key, 0, 8);
 
437
        rc = usb_poll_intr(dev->intr, key);
 
438
        if (rc)
 
439
                check_key_code(key);
 
440
        return rc;
 
441
}
 
442
 
 
443
unsigned char usb_key_available(void *dev)
 
444
{
 
445
        if (!dev)
 
446
                return false;
 
447
 
 
448
        usb_poll_key(dev);
 
449
        if (r_ptr != w_ptr)
 
450
                return true;
 
451
        else
 
452
                return false;
 
453
}
 
454
 
 
455
unsigned char usb_read_keyb(void *vdev)
 
456
{
 
457
        if (usb_key_available(vdev))
 
458
                return read_key();
 
459
        else
 
460
                return 0;
 
461
}