summaryrefslogtreecommitdiff
path: root/firmware/usbstack/usb_hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/usb_hid.c')
-rw-r--r--firmware/usbstack/usb_hid.c424
1 files changed, 346 insertions, 78 deletions
diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c
index 31554eed48..e1ae75c0f9 100644
--- a/firmware/usbstack/usb_hid.c
+++ b/firmware/usbstack/usb_hid.c
@@ -37,17 +37,28 @@
37 37
38#define HID_VER 0x0110 /* 1.1 */ 38#define HID_VER 0x0110 /* 1.1 */
39/* Subclass Codes (HID1_11.pdf, page 18) */ 39/* Subclass Codes (HID1_11.pdf, page 18) */
40#define SUBCLASS_NONE 0
40#define SUBCLASS_BOOT_INTERFACE 1 41#define SUBCLASS_BOOT_INTERFACE 1
41/* Protocol Codes (HID1_11.pdf, page 19) */ 42/* Protocol Codes (HID1_11.pdf, page 19) */
43#define PROTOCOL_CODE_NONE 0
44#define PROTOCOL_CODE_KEYBOARD 1
42#define PROTOCOL_CODE_MOUSE 2 45#define PROTOCOL_CODE_MOUSE 2
43/* HID main items (HID1_11.pdf, page 38) */ 46/* HID main items (HID1_11.pdf, page 38) */
44#define INPUT 0x80 47#define INPUT 0x80
45#define COLLECTION 0xa0 48#define OUTPUT 0x90
49#define COLLECTION 0xA0
46#define COLLECTION_APPLICATION 0x01 50#define COLLECTION_APPLICATION 0x01
47#define END_COLLECTION 0xc0 51#define END_COLLECTION 0xC0
48/* Parts (HID1_11.pdf, page 40) */ 52/* Parts (HID1_11.pdf, page 40) */
49#define PREFERERD (1 << 5) 53#define MAIN_ITEM_CONSTANT BIT_N(0) /* 0x01 */
50#define NULL_STATE (1 << 6) 54#define MAIN_ITEM_VARIABLE BIT_N(1) /* 0x02 */
55#define MAIN_ITEM_RELATIVE BIT_N(2) /* 0x04 */
56#define MAIN_ITEM_WRAP BIT_N(3) /* 0x08 */
57#define MAIN_ITEM_NONLINEAR BIT_N(4) /* 0x10 */
58#define MAIN_ITEM_NO_PREFERRED BIT_N(5) /* 0x20 */
59#define MAIN_ITEM_NULL_STATE BIT_N(6) /* 0x40 */
60#define MAIN_ITEM_VOLATILE BIT_N(7) /* 0x80 */
61#define MAIN_ITEM_BUFFERED_BYTES BIT_N(8) /* 0x0100 */
51/* HID global items (HID1_11.pdf, page 45) */ 62/* HID global items (HID1_11.pdf, page 45) */
52#define USAGE_PAGE 0x04 63#define USAGE_PAGE 0x04
53#define LOGICAL_MINIMUM 0x14 64#define LOGICAL_MINIMUM 0x14
@@ -62,26 +73,44 @@
62#define USB_DT_HID 0x21 73#define USB_DT_HID 0x21
63#define USB_DT_REPORT 0x22 74#define USB_DT_REPORT 0x22
64 75
65/* (Hut1_12.pdf, Table 1, page 14) */
66#define USAGE_PAGE_CONSUMER 0x0c
67
68#define CONSUMER_USAGE 0x09 76#define CONSUMER_USAGE 0x09
69 77
70/* HID-only class specific requests */ 78/* HID-only class specific requests (HID1_11.pdf, page 61) */
71#define USB_HID_GET_REPORT 0x01 79#define USB_HID_GET_REPORT 0x01
72#define USB_HID_GET_IDLE 0x02 80#define USB_HID_GET_IDLE 0x02
73#define USB_HID_GET_PROTOCOL 0x03 81#define USB_HID_GET_PROTOCOL 0x03
74#define USB_HID_SET_REPORT 0x09 82#define USB_HID_SET_REPORT 0x09
75#define USB_HID_SET_IDLE 0x0a 83#define USB_HID_SET_IDLE 0x0A
76#define USB_HID_SET_PROTOCOL 0x0b 84#define USB_HID_SET_PROTOCOL 0x0B
85
86/* Get_Report and Set_Report Report Type field (HID1_11.pdf, page 61) */
87#define REPORT_TYPE_INPUT 0x01
88#define REPORT_TYPE_OUTPUT 0x02
89#define REPORT_TYPE_FEATURE 0x03
77 90
78#define HID_BUF_SIZE_MSG 16 91#define HID_BUF_SIZE_MSG 16
79#define HID_BUF_SIZE_CMD 5 92#define HID_BUF_SIZE_CMD 16
80#define HID_BUG_SIZE_REPORT 32 93#define HID_BUF_SIZE_REPORT 96
81#define HID_NUM_BUFFERS 5 94#define HID_NUM_BUFFERS 5
95#define SET_REPORT_BUF_LEN 2
96
97#ifdef LOGF_ENABLE
98#define BUF_DUMP_BUF_LEN HID_BUF_SIZE_REPORT
99#define BUF_DUMP_PREFIX_SIZE 5
100#define BUF_DUMP_LINE_SIZE (MAX_LOGF_ENTRY - BUF_DUMP_PREFIX_SIZE)
101#define BUF_DUMP_ITEMS_IN_LINE (BUF_DUMP_LINE_SIZE / 3)
102#define BUF_DUMP_NUM_LINES (BUF_DUMP_BUF_LEN / (BUF_DUMP_LINE_SIZE / 3))
103#endif
82 104
83#define HID_BUF_INC(i) do { (i) = ((i) + 1) % HID_NUM_BUFFERS; } while (0) 105#define HID_BUF_INC(i) do { (i) = ((i) + 1) % HID_NUM_BUFFERS; } while (0)
84 106
107typedef enum
108{
109 REPORT_ID_KEYBOARD = 1,
110 REPORT_ID_CONSUMER,
111 REPORT_ID_COUNT,
112} report_id_t;
113
85/* hid interface */ 114/* hid interface */
86static struct usb_interface_descriptor __attribute__((aligned(2))) 115static struct usb_interface_descriptor __attribute__((aligned(2)))
87 interface_descriptor = 116 interface_descriptor =
@@ -93,7 +122,7 @@ static struct usb_interface_descriptor __attribute__((aligned(2)))
93 .bNumEndpoints = 1, 122 .bNumEndpoints = 1,
94 .bInterfaceClass = USB_CLASS_HID, 123 .bInterfaceClass = USB_CLASS_HID,
95 .bInterfaceSubClass = SUBCLASS_BOOT_INTERFACE, 124 .bInterfaceSubClass = SUBCLASS_BOOT_INTERFACE,
96 .bInterfaceProtocol = PROTOCOL_CODE_MOUSE, 125 .bInterfaceProtocol = PROTOCOL_CODE_KEYBOARD,
97 .iInterface = 0 126 .iInterface = 0
98}; 127};
99 128
@@ -129,7 +158,17 @@ static struct usb_endpoint_descriptor __attribute__((aligned(2)))
129 .bInterval = 0 158 .bInterval = 0
130}; 159};
131 160
132static unsigned char report_descriptor[HID_BUG_SIZE_REPORT] 161typedef struct
162{
163 uint8_t usage_page;
164 /* Write the id into the buffer in the appropriate location, and returns the
165 * buffer length */
166 uint8_t (*buf_set)(unsigned char *buf, int id);
167} usb_hid_report_t;
168
169usb_hid_report_t usb_hid_reports[REPORT_ID_COUNT];
170
171static unsigned char report_descriptor[HID_BUF_SIZE_REPORT]
133 USB_DEVBSS_ATTR __attribute__((aligned(32))); 172 USB_DEVBSS_ATTR __attribute__((aligned(32)));
134 173
135static unsigned char send_buffer[HID_NUM_BUFFERS][HID_BUF_SIZE_MSG] 174static unsigned char send_buffer[HID_NUM_BUFFERS][HID_BUF_SIZE_MSG]
@@ -138,16 +177,14 @@ size_t send_buffer_len[HID_NUM_BUFFERS];
138static int cur_buf_prepare; 177static int cur_buf_prepare;
139static int cur_buf_send; 178static int cur_buf_send;
140 179
141static uint16_t report_descriptor_len;
142static bool active = false; 180static bool active = false;
143static int ep_in; 181static int ep_in;
144static int usb_interface; 182static int usb_interface;
145static uint32_t report_id;
146 183
147static void usb_hid_try_send_drv(void); 184static void usb_hid_try_send_drv(void);
148 185
149static void pack_parameter(unsigned char **dest, uint8_t parameter, 186static void pack_parameter(unsigned char **dest, bool is_signed,
150 uint32_t value) 187 uint8_t parameter, uint32_t value)
151{ 188{
152 uint8_t size_value = 1; /* # of bytes */ 189 uint8_t size_value = 1; /* # of bytes */
153 uint32_t v = value; 190 uint32_t v = value;
@@ -155,6 +192,30 @@ static void pack_parameter(unsigned char **dest, uint8_t parameter,
155 while (v >>= 8) 192 while (v >>= 8)
156 size_value++; 193 size_value++;
157 194
195 if (is_signed)
196 {
197 bool is_negative = 0;
198
199 switch (size_value)
200 {
201 case 1:
202 is_negative = (int8_t)value < 0;
203 break;
204 case 2:
205 is_negative = (int16_t)value < 0;
206 break;
207 case 3:
208 case 4:
209 is_negative = (int32_t)value < 0;
210 break;
211 default:
212 break;
213 }
214
215 if (is_negative)
216 size_value++;
217 }
218
158 **dest = parameter | size_value; 219 **dest = parameter | size_value;
159 (*dest)++; 220 (*dest)++;
160 221
@@ -182,48 +243,157 @@ int usb_hid_set_first_interface(int interface)
182 return interface + 1; 243 return interface + 1;
183} 244}
184 245
185int usb_hid_get_config_descriptor(unsigned char *dest,int max_packet_size) 246#ifdef LOGF_ENABLE
247static unsigned char
248 buf_dump_ar[BUF_DUMP_NUM_LINES][BUF_DUMP_LINE_SIZE + 1]
249 USB_DEVBSS_ATTR __attribute__((aligned(32)));
250
251void buf_dump(unsigned char *buf, size_t size)
252{
253 size_t i;
254 int line;
255 static const char v[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
256 'A', 'B', 'C', 'D', 'E', 'F' };
257
258 for (i = 0, line = 0; i < size; line++)
259 {
260 int j, i0 = i;
261 char *b = buf_dump_ar[line];
262
263 for (j = 0; j < BUF_DUMP_ITEMS_IN_LINE && i < size; j++, i++)
264 {
265 *b++ = v[buf[i] >> 4];
266 *b++ = v[buf[i] & 0xF];
267 *b++ = ' ';
268 }
269 *b = 0;
270
271 /* Prefix must be of len BUF_DUMP_PREFIX_SIZE */
272 logf("%03d: %s", i0, buf_dump_ar[line]);
273 }
274}
275#else
276#undef buf_dump
277#define buf_dump(...)
278#endif
279
280uint8_t buf_set_keyboard(unsigned char *buf, int id)
281{
282 memset(buf, 0, 7);
283
284 if (HID_KEYBOARD_LEFT_CONTROL <= id && id <= HID_KEYBOARD_RIGHT_GUI)
285 buf[0] = (1 << (id - HID_KEYBOARD_LEFT_CONTROL));
286 else
287 buf[1] = (uint8_t)id;
288
289 return 7;
290}
291
292uint8_t buf_set_consumer(unsigned char *buf, int id)
293{
294 memset(buf, 0, 4);
295 buf[0] = (uint8_t)id;
296
297 return 4;
298}
299
300static size_t descriptor_report_get(unsigned char *dest)
301{
302 unsigned char *report = dest;
303 usb_hid_report_t *usb_hid_report;
304
305 /* Keyboard control */
306 usb_hid_report = &usb_hid_reports[REPORT_ID_KEYBOARD];
307 usb_hid_report->usage_page = HID_USAGE_PAGE_KEYBOARD_KEYPAD;
308 usb_hid_report->buf_set = buf_set_keyboard;
309
310 pack_parameter(&report, 0, USAGE_PAGE,
311 HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS);
312 PACK_VAL2(report, CONCAT(CONSUMER_USAGE, HID_GENERIC_DESKTOP_KEYBOARD));
313 pack_parameter(&report, 0, COLLECTION, COLLECTION_APPLICATION);
314 pack_parameter(&report, 0, REPORT_ID, REPORT_ID_KEYBOARD);
315 pack_parameter(&report, 0, USAGE_PAGE, HID_GENERIC_DESKTOP_KEYPAD);
316 pack_parameter(&report, 0, USAGE_MINIMUM, HID_KEYBOARD_LEFT_CONTROL);
317 pack_parameter(&report, 0, USAGE_MAXIMUM, HID_KEYBOARD_RIGHT_GUI);
318 pack_parameter(&report, 1, LOGICAL_MINIMUM, 0);
319 pack_parameter(&report, 1, LOGICAL_MAXIMUM, 1);
320 pack_parameter(&report, 0, REPORT_SIZE, 1);
321 pack_parameter(&report, 0, REPORT_COUNT, 8);
322 pack_parameter(&report, 0, INPUT, MAIN_ITEM_VARIABLE);
323 pack_parameter(&report, 0, REPORT_SIZE, 1);
324 pack_parameter(&report, 0, REPORT_COUNT, 5);
325 pack_parameter(&report, 0, USAGE_PAGE, HID_USAGE_PAGE_LEDS);
326 pack_parameter(&report, 0, USAGE_MINIMUM, HID_LED_NUM_LOCK);
327 pack_parameter(&report, 0, USAGE_MAXIMUM, HID_LED_KANA);
328 pack_parameter(&report, 0, OUTPUT, MAIN_ITEM_VARIABLE);
329 pack_parameter(&report, 0, REPORT_SIZE, 3);
330 pack_parameter(&report, 0, REPORT_COUNT, 1);
331 pack_parameter(&report, 0, OUTPUT, MAIN_ITEM_CONSTANT);
332 pack_parameter(&report, 0, REPORT_SIZE, 8);
333 pack_parameter(&report, 0, REPORT_COUNT, 6);
334 pack_parameter(&report, 1, LOGICAL_MINIMUM, 0);
335 pack_parameter(&report, 1, LOGICAL_MAXIMUM, HID_KEYBOARD_EX_SEL);
336 pack_parameter(&report, 0, USAGE_PAGE, HID_USAGE_PAGE_KEYBOARD_KEYPAD);
337 pack_parameter(&report, 0, USAGE_MINIMUM, 0);
338 pack_parameter(&report, 0, USAGE_MAXIMUM, HID_KEYBOARD_EX_SEL);
339 pack_parameter(&report, 0, INPUT, 0);
340 PACK_VAL1(report, END_COLLECTION);
341
342 /* Consumer usage controls - play/pause, stop, etc. */
343 usb_hid_report = &usb_hid_reports[REPORT_ID_CONSUMER];
344 usb_hid_report->usage_page = HID_USAGE_PAGE_CONSUMER;
345 usb_hid_report->buf_set = buf_set_consumer;
346
347 pack_parameter(&report, 0, USAGE_PAGE, HID_USAGE_PAGE_CONSUMER);
348 PACK_VAL2(report, CONCAT(CONSUMER_USAGE,
349 HID_CONSUMER_USAGE_CONSUMER_CONTROL));
350 pack_parameter(&report, 0, COLLECTION, COLLECTION_APPLICATION);
351 pack_parameter(&report, 0, REPORT_ID, REPORT_ID_CONSUMER);
352 pack_parameter(&report, 0, REPORT_SIZE, 16);
353 pack_parameter(&report, 0, REPORT_COUNT, 2);
354 pack_parameter(&report, 1, LOGICAL_MINIMUM, 1);
355 pack_parameter(&report, 1, LOGICAL_MAXIMUM, 652);
356 pack_parameter(&report, 0, USAGE_MINIMUM,
357 HID_CONSUMER_USAGE_CONSUMER_CONTROL);
358 pack_parameter(&report, 0, USAGE_MAXIMUM, HID_CONSUMER_USAGE_AC_SEND);
359 pack_parameter(&report, 0, INPUT, MAIN_ITEM_NO_PREFERRED |
360 MAIN_ITEM_NULL_STATE);
361 PACK_VAL1(report, END_COLLECTION);
362
363 return (size_t)((uint32_t)report - (uint32_t)dest);
364}
365
366static void descriptor_hid_get(unsigned char **dest)
367{
368 hid_descriptor.wDescriptorLength0 =
369 (uint16_t)descriptor_report_get(report_descriptor);
370
371 PACK_DATA(*dest, hid_descriptor);
372}
373
374int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_size)
186{ 375{
187 unsigned char *report, *orig_dest = dest; 376 unsigned char *orig_dest = dest;
188 377
189 logf("hid: config desc."); 378 logf("hid: config desc.");
190 379
191 /* Ignore given max_packet_size */ 380 /* Ignore given max_packet_size */
192 (void)max_packet_size; 381 (void)max_packet_size;
193 382
194 /* TODO: Increment report_id for each report, and send command with 383 /* Interface descriptor */
195 * appropriate report id */
196 report_id = 2;
197
198 /* Initialize report descriptor */
199 report = report_descriptor;
200 pack_parameter(&report, USAGE_PAGE, USAGE_PAGE_CONSUMER);
201 PACK_VAL2(report, CONCAT(CONSUMER_USAGE, CONSUMER_CONTROL));
202 pack_parameter(&report, COLLECTION, COLLECTION_APPLICATION);
203 pack_parameter(&report, REPORT_ID, report_id);
204 pack_parameter(&report, REPORT_SIZE, 16);
205 pack_parameter(&report, REPORT_COUNT, 2);
206 pack_parameter(&report, LOGICAL_MINIMUM, 1);
207 pack_parameter(&report, LOGICAL_MAXIMUM, 652);
208 pack_parameter(&report, USAGE_MINIMUM, CONSUMER_CONTROL);
209 pack_parameter(&report, USAGE_MAXIMUM, AC_SEND);
210 pack_parameter(&report, INPUT, PREFERERD | NULL_STATE);
211 PACK_VAL1(report, END_COLLECTION);
212 report_descriptor_len = (uint16_t)((uint32_t)report -
213 (uint32_t)report_descriptor);
214
215 interface_descriptor.bInterfaceNumber = usb_interface; 384 interface_descriptor.bInterfaceNumber = usb_interface;
216 PACK_DATA(dest, interface_descriptor); 385 PACK_DATA(dest, interface_descriptor);
217 hid_descriptor.wDescriptorLength0 = report_descriptor_len;
218 PACK_DATA(dest, hid_descriptor);
219 386
387 /* HID descriptor */
388 descriptor_hid_get(&dest);
389
390 /* Endpoint descriptor */
220 endpoint_descriptor.wMaxPacketSize = 8; 391 endpoint_descriptor.wMaxPacketSize = 8;
221 endpoint_descriptor.bInterval = 8; 392 endpoint_descriptor.bInterval = 8;
222
223 endpoint_descriptor.bEndpointAddress = ep_in; 393 endpoint_descriptor.bEndpointAddress = ep_in;
224 PACK_DATA(dest, endpoint_descriptor); 394 PACK_DATA(dest, endpoint_descriptor);
225 395
226 return (dest - orig_dest); 396 return (int)(dest - orig_dest);
227} 397}
228 398
229void usb_hid_init_connection(void) 399void usb_hid_init_connection(void)
@@ -263,10 +433,12 @@ void usb_hid_transfer_complete(int ep, int dir, int status, int length)
263 (void)status; 433 (void)status;
264 (void)length; 434 (void)length;
265 435
266 switch (dir) { 436 switch (dir)
437 {
267 case USB_DIR_OUT: 438 case USB_DIR_OUT:
268 break; 439 break;
269 case USB_DIR_IN: { 440 case USB_DIR_IN:
441 {
270 if (status) 442 if (status)
271 break; 443 break;
272 444
@@ -278,26 +450,95 @@ void usb_hid_transfer_complete(int ep, int dir, int status, int length)
278 } 450 }
279} 451}
280 452
453/* The DAP is registered as a keyboard with several LEDs, therefore the OS sends
454 * LED report to notify the DAP whether Num Lock / Caps Lock etc. are enabled.
455 * In order to allow sending info to the DAP, the Set Report mechanism can be
456 * used by defining vendor specific output reports and send them from the host
457 * to the DAP using the host's custom driver */
458static int usb_hid_set_report(struct usb_ctrlrequest *req)
459{
460 static unsigned char buf[SET_REPORT_BUF_LEN]
461 USB_DEVBSS_ATTR __attribute__((aligned(32)));
462 int length;
463 int rc = 0;
464
465 if ((req->wValue >> 8) != REPORT_TYPE_OUTPUT)
466 {
467 logf("Unsopported report type");
468 rc = 1;
469 goto Exit;
470 }
471 if ((req->wValue & 0xff) != REPORT_ID_KEYBOARD)
472 {
473 logf("Wrong report id");
474 rc = 2;
475 goto Exit;
476 }
477 if (req->wIndex != (uint16_t)usb_interface)
478 {
479 logf("Wrong interface");
480 rc = 3;
481 goto Exit;
482 }
483 length = req->wLength;
484 if (length != SET_REPORT_BUF_LEN)
485 {
486 logf("Wrong length");
487 rc = 4;
488 goto Exit;
489 }
490
491 memset(buf, 0, length);
492 usb_drv_recv(EP_CONTROL, buf, length);
493
494#ifdef LOGF_ENABLE
495 if (buf[1] & 0x01)
496 logf("Num Lock enabled");
497 if (buf[1] & 0x02)
498 logf("Caps Lock enabled");
499 if (buf[1] & 0x04)
500 logf("Scroll Lock enabled");
501 if (buf[1] & 0x08)
502 logf("Compose enabled");
503 if (buf[1] & 0x10)
504 logf("Kana enabled");
505#endif
506
507 /* Defining other LEDs and setting them from the USB host (OS) can be used
508 * to send messages to the DAP */
509
510Exit:
511 return rc;
512}
513
281/* called by usb_core_control_request() */ 514/* called by usb_core_control_request() */
282bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest) 515bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest)
283{ 516{
284 bool handled = false; 517 bool handled = false;
285 518
286 switch(req->bRequestType & USB_TYPE_MASK) { 519 switch (req->bRequestType & USB_TYPE_MASK)
287 case USB_TYPE_STANDARD: { 520 {
521 case USB_TYPE_STANDARD:
522 {
288 unsigned char *orig_dest = dest; 523 unsigned char *orig_dest = dest;
289 524
290 switch(req->wValue>>8) { /* type */ 525 switch (req->wValue>>8) /* type */
291 case USB_DT_HID: { 526 {
527 case USB_DT_HID:
528 {
292 logf("hid: type hid"); 529 logf("hid: type hid");
293 hid_descriptor.wDescriptorLength0 = report_descriptor_len; 530 descriptor_hid_get(&dest);
294 PACK_DATA(dest, hid_descriptor);
295 break; 531 break;
296 } 532 }
297 case USB_DT_REPORT: { 533 case USB_DT_REPORT:
534 {
535 int len;
536
298 logf("hid: type report"); 537 logf("hid: type report");
299 memcpy(dest, &report_descriptor, report_descriptor_len); 538
300 dest += report_descriptor_len; 539 len = descriptor_report_get(report_descriptor);
540 memcpy(dest, &report_descriptor, len);
541 dest += len;
301 break; 542 break;
302 } 543 }
303 default: 544 default:
@@ -305,26 +546,37 @@ bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest)
305 break; 546 break;
306 } 547 }
307 if (dest != orig_dest && 548 if (dest != orig_dest &&
308 !usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest)) { 549 !usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest))
550 {
309 usb_core_ack_control(req); 551 usb_core_ack_control(req);
310 handled = true; 552 handled = true;
311 } 553 }
312 break; 554 break;
313 } 555 }
314 556
315 case USB_TYPE_CLASS: { 557 case USB_TYPE_CLASS:
316 switch (req->bRequest) { 558 {
317 case USB_HID_SET_IDLE: 559 switch (req->bRequest)
318 logf("hid: set idle"); 560 {
561 case USB_HID_SET_IDLE:
562 logf("hid: set idle");
563 usb_core_ack_control(req);
564 handled = true;
565 break;
566 case USB_HID_SET_REPORT:
567 logf("hid: set report");
568 if (!usb_hid_set_report(req))
569 {
319 usb_core_ack_control(req); 570 usb_core_ack_control(req);
320 handled = true; 571 handled = true;
321 break; 572 }
322 default: 573 break;
323 logf("%d: unsup. cls. req", req->bRequest); 574 default:
324 break; 575 logf("%d: unsup. cls. req", req->bRequest);
325 } 576 break;
326 break;
327 } 577 }
578 break;
579 }
328 580
329 case USB_TYPE_VENDOR: 581 case USB_TYPE_VENDOR:
330 logf("hid: unsup. ven. req"); 582 logf("hid: unsup. ven. req");
@@ -367,26 +619,42 @@ static void usb_hid_queue(unsigned char *data, int length)
367 HID_BUF_INC(cur_buf_prepare); 619 HID_BUF_INC(cur_buf_prepare);
368} 620}
369 621
370void usb_hid_send_consumer_usage(consumer_usage_page_t id) 622void usb_hid_send(usage_page_t usage_page, int id)
371{ 623{
624 uint8_t report_id, length;
372 static unsigned char buf[HID_BUF_SIZE_CMD] USB_DEVBSS_ATTR 625 static unsigned char buf[HID_BUF_SIZE_CMD] USB_DEVBSS_ATTR
373 __attribute__((aligned(32))); 626 __attribute__((aligned(32)));
374 unsigned char *dest = buf; 627 usb_hid_report_t *report = NULL;
375
376 memset(buf, 0, sizeof(buf));
377 628
378 logf("HID: Sending 0x%x", id); 629 for (report_id = 1; report_id < REPORT_ID_COUNT; report_id++)
630 {
631 if (usb_hid_reports[report_id].usage_page == usage_page)
632 {
633 report = &usb_hid_reports[report_id];
634 break;
635 }
636 }
637 if (!report)
638 {
639 logf("Unsupported usage_page");
640 return;
641 }
379 642
380 pack_parameter(&dest, 0, id); 643 logf("Sending cmd 0x%x", id);
381 buf[0] = report_id; 644 buf[0] = report_id;
645 length = report->buf_set(&buf[1], id) + 1;
646 logf("length %u", length);
382 647
383 /* Key pressed */ 648 /* Key pressed */
384 usb_hid_queue(buf, HID_BUF_SIZE_CMD); 649 buf_dump(buf, length);
650 usb_hid_queue(buf, length);
385 651
386 /* Key released */ 652 /* Key released */
387 memset(buf, 0, sizeof(buf)); 653 memset(buf, 0, length);
388 buf[0] = report_id; 654 buf[0] = report_id;
389 usb_hid_queue(buf, HID_BUF_SIZE_CMD); 655
656 buf_dump(buf, length);
657 usb_hid_queue(buf, length);
390 658
391 usb_hid_try_send_drv(); 659 usb_hid_try_send_drv();
392} 660}