M480 BSP V3.05.005
The Board Support Package for M480 Series
hid_parser.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11#include <string.h>
12
13#include "NuMicro.h"
14
15#include "usb.h"
16#include "usbh_lib.h"
17#include "usbh_hid.h"
18
19
21
22
23static int hid_parse_item(HID_DEV_T *hdev, uint8_t *buff);
24
25#if ENABLE_DBG_MSG
26struct string_table
27{
28 char string[32];
29 uint8_t code;
30};
31
32static const struct string_table usage_page_list[] =
33{
34 "Generic Desktop", UP_GENERIC_DESKTOP,
35 "Simulation Controls", UP_SIMULATION_CONTROLS,
36 "VR Controls", UP_VR_CONTROLS,
37 "Sport Controls", UP_SPORT_CONTROLS,
38 "Game Controls", UP_GAME_CONTROLS,
39 "KeyCode", UP_KEYCODE,
40 "LEDs", UP_LEDS,
41 "Button", UP_BUTTON,
42 "Digitizer", UP_DIGITIZER,
43 "Bar Code Scanner", UP_BARCODE_SCANNER,
44};
45
46static const struct string_table desktop_page_list[] =
47{
48 "Pointer", USAGE_ID_POINTER,
49 "Mouse", USAGE_ID_MOUSE,
50 "Joystick", USAGE_ID_JOYSTICK,
51 "Game Pad", USAGE_ID_GAMEPAD,
52 "Keyboard", USAGE_ID_KEYBOARD,
53 "Keypad", USAGE_ID_KEYPAD,
54 "X", USAGE_ID_X,
55 "Y", USAGE_ID_Y,
56 "Z", USAGE_ID_Z,
57 "Rx", 0x33,
58 "Ry", 0x34,
59 "Rz", 0x35,
60 "Slider", 0x36,
61 "Dial", 0x37,
62 "Wheel", USAGE_ID_WHEEL,
63};
64
65#endif
66
67
68/*
69 * Varibles used on parsing HID report descriptor
70 */
71static RP_INFO_T _rp_info; /* describing the current report */
72
73static uint8_t _data_usages[16];
74static int _data_usage_cnt;
75
76static void print_usage_page(void)
77{
78#if ENABLE_DBG_MSG
79 int i;
80
81 for (i = 0; i < sizeof(usage_page_list)/sizeof(struct string_table); i++)
82 {
83 if (usage_page_list[i].code == _rp_info.usage_page)
84 {
85 printf("(%s)", usage_page_list[i].string);
86 return;
87 }
88 }
89 printf("(?? - 0x%x)", _rp_info.usage_page);
90#endif
91}
92
93static void print_usage(uint8_t usage)
94{
95#if ENABLE_DBG_MSG
96 int i, count;
97 struct string_table *p;
98
99 if (_rp_info.usage_page == UP_GENERIC_DESKTOP)
100 {
101 count = sizeof(desktop_page_list)/sizeof(struct string_table);
102 p = (struct string_table *)&desktop_page_list[0];
103 }
104 else
105 return;
106
107 for (i = 0; i < count; i++, p++)
108 {
109 if (p->code == usage)
110 {
111 printf("(%s)", p->string);
112 return;
113 }
114 }
115 printf("(?? - 0x%x)", usage);
116#endif
117}
118
119static void read_main_item_status(uint8_t *buff)
120{
121 HID_DBGMSG("(");
122 if (buff[0] & 0x01)
123 {
124 _rp_info.status.constant = 1;
125 _rp_info.status.variable = 0;
126 HID_DBGMSG("Constant ");
127 }
128 if (buff[0] & 0x02)
129 {
130 _rp_info.status.constant = 0;
131 _rp_info.status.variable = 1;
132 HID_DBGMSG("Variable ");
133 }
134 if (buff[0] & 0x04)
135 {
136 _rp_info.status.relative = 1;
137 HID_DBGMSG("Relative ");
138 }
139 if (buff[0] & 0x08)
140 {
141 _rp_info.status.wrap = 1;
142 HID_DBGMSG("Wrap ");
143 }
144 if (buff[0] & 0x10)
145 {
146 _rp_info.status.non_linear = 1;
147 HID_DBGMSG("Non-linear ");
148 }
149 if (buff[0] & 0x20)
150 {
151 _rp_info.status.no_preferred = 1;
152 HID_DBGMSG("Not-prefered ");
153 }
154 if (buff[0] & 0x40)
155 {
156 _rp_info.status.null_state = 1;
157 HID_DBGMSG("Null-state ");
158 }
159 if (buff[0] & 0x80)
160 {
161 _rp_info.status.is_volatile = 1;
162 HID_DBGMSG("Volatile ");
163 }
164 if (buff[1] & 0x01)
165 {
166 _rp_info.status.buffered_bytes = 1;
167 HID_DBGMSG("Buffered-bytes ");
168 }
169 HID_DBGMSG(")");
170}
171
172
181int hid_parse_report_descriptor(HID_DEV_T *hdev, IFACE_T *iface)
182{
183 UDEV_T *udev = iface->udev;
184 DESC_CONF_T *config;
185 DESC_IF_T *ifd;
186 DESC_HID_T *hidd;
187 uint8_t *bptr;
188 uint8_t *desc_buff;
189 int desc_buff_len, remain_len, size;
190
191 HID_DBGMSG("HID interface %d parsing report descriptor...\n", iface->if_num);
192
193 memset(&_rp_info, 0, sizeof(_rp_info));
194 _data_usage_cnt = 0;
195
196 hdev->rpd.has_report_id = 0;
197
198 bptr = udev->cfd_buff;
199 config = (DESC_CONF_T *)bptr;
200
201 /* step over configuration descritpor */
202 bptr += config->bLength;
203 size = config->wTotalLength - config->bLength;
204
205 /*------------------------------------------------------------------------------------*/
206 /* Find the Interface Descriptor of this HID interface */
207 /*------------------------------------------------------------------------------------*/
208 while (size >= sizeof(DESC_IF_T))
209 {
210 ifd = (DESC_IF_T *)bptr;
211
212 if ((ifd->bDescriptorType == USB_DT_INTERFACE) && (ifd->bInterfaceNumber == iface->if_num) &&
213 (ifd->bInterfaceClass == USB_CLASS_HID))
214 break;
215
216 if (ifd->bLength == 0)
217 return -1;
218
219 bptr += ifd->bLength;
220 size -= ifd->bLength;
221 }
222
223 if (size < sizeof(DESC_IF_T))
224 {
225 HID_ERRMSG("Can't find the HID interface!\n");
226 return HID_RET_PARSING;
227 }
228
229 bptr += ifd->bLength;
230 size -= ifd->bLength;
231
232 /*------------------------------------------------------------------------------------*/
233 /* Continue to find the subsequent HID Descriptor */
234 /*------------------------------------------------------------------------------------*/
235 while (size >= sizeof(DESC_HID_T))
236 {
237 hidd = (DESC_HID_T *)bptr;
238
239 if ((hidd->bDescriptorType == HID_DESCRIPTOR_TYPE) &&
240 (hidd->bRPDescType == REPORT_DESCRIPTOR_TYPE))
241 break;
242
243 if (hidd->bLength == 0)
244 return HID_RET_PARSING;
245
246 bptr += ifd->bLength;
247 size -= ifd->bLength;
248 }
249
250 if (size < sizeof(DESC_HID_T))
251 {
252 HID_ERRMSG("Can't find the HID interface!\n");
253 return HID_RET_PARSING;
254 }
255
256 hidd = (DESC_HID_T *)bptr;
257
258 HID_DBGMSG("[HID Descriptor]\n");
259 HID_DBGMSG("bLength = %d\n", hidd->bLength);
260 HID_DBGMSG("bDescriptorType = 0x%x\n", hidd->bDescriptorType);
261 HID_DBGMSG("bcdHID = 0x%x\n", hidd->bcdHID);
262 HID_DBGMSG("bCountryCode = 0x%x\n", hidd->bCountryCode);
263 HID_DBGMSG("bNumDescriptors = %d\n", hidd->bNumDescriptors);
264 HID_DBGMSG("bRPDescType = 0x%x\n", hidd->bRPDescType);
265 HID_DBGMSG("wDescriptorLength = %d\n", hidd->wDescriptorLength);
266
267 HID_DBGMSG("Report descriptor found, length=%d. %d\n", hidd->wDescriptorLength, hidd->bLength);
268
269 desc_buff_len = hidd->wDescriptorLength+8;
270 desc_buff = (uint8_t *)usbh_alloc_mem(desc_buff_len);
271
272 remain_len = usbh_hid_get_report_descriptor(hdev, desc_buff, desc_buff_len);
273 if (remain_len <= 0)
274 {
275 usbh_free_mem(desc_buff, desc_buff_len);
276 return remain_len;
277 }
278
279 //HID_DBGMSG("\nDump report descriptor =>\n");
280 //dump_buff_hex(desc_buff, remain_len);
281
282 /*------------------------------------------------------------------------------------*/
283 /* Parsing items */
284 /*------------------------------------------------------------------------------------*/
285 bptr = desc_buff;
286 while (remain_len > 0)
287 {
288 size = hid_parse_item(hdev, bptr);
289 //printf("size = %d/%d\n", size, remain_len);
290 if (size <= 0)
291 {
292 usbh_free_mem(desc_buff, desc_buff_len);
293 return HID_RET_PARSING;
294 }
295
296 bptr += size;
297 remain_len -= size;
298 }
299
300 usbh_free_mem(desc_buff, desc_buff_len);
301
302 /*------------------------------------------------------------------------------------*/
303 /* For keyboard device, turn on all LEDs for 0.5 seconds and then turn off. */
304 /*------------------------------------------------------------------------------------*/
305 if ((hdev->bSubClassCode == HID_SUBCLASS_BOOT_DEVICE) && (hdev->bProtocolCode == HID_PROTOCOL_KEYBOARD))
306 {
307 RP_INFO_T *report;
308
309 for (report = hdev->rpd.report; report != NULL; report = report->next)
310 {
311 if ((report->usage_page == UP_LEDS) && (report->report_size == 1) && report->status.variable)
312 {
313 uint8_t i, ret, leds = 0;
314
315 for (i = 0; (i < 8) && (i < report->report_count); i++)
316 leds = (leds << 1) | 0x1;
317
318 /* turn-on keyboard NumLock, CapsLock, ScrollLock LEDs */
319 ret = usbh_hid_set_report(hdev, RT_OUTPUT, 0, &leds, 1);
320 if (ret != 1)
321 {
322 HID_ERRMSG("Failed to turn on LEDs! 0x%x, %d\n", leds, ret);
323 }
324 else
325 {
326 delay_us(500000); /* delay 0.5 conds */
327
328 /* turn-off all LEDs */
329 leds = 0x00;
330 ret = usbh_hid_set_report(hdev, RT_OUTPUT, 0, &leds, 1);
331 if (ret != 1)
332 HID_ERRMSG("Failed to turn off LEDs! %d\n", ret);
333 }
334 }
335 }
336 }
337
338 return 0;
339}
340
341static int hid_add_report(HID_DEV_T *hdev, uint8_t type)
342{
343 RP_INFO_T *report, *p;
344
345 report = (RP_INFO_T *)usbh_alloc_mem(sizeof(RP_INFO_T));
346 if (report == NULL)
347 {
348 HID_ERRMSG("hid_add_report allocate memory failed!!\n");
349 return USBH_ERR_MEMORY_OUT;
350 }
351 memcpy(report, &_rp_info, sizeof(RP_INFO_T));
352 report->type = type;
353
354 HID_DBGMSG("\nCreate a report. %d x %d (%d)\n", report->report_count, report->report_size, report->report_id);
355
356 if (hdev->rpd.report == NULL)
357 hdev->rpd.report = report;
358 else
359 {
360 p = hdev->rpd.report;
361 while (p->next != NULL)
362 p = p->next;
363 p->next = report;
364 }
365 return 0;
366}
367
368static signed int hid_read_item_value(uint8_t bSize, uint8_t *buff)
369{
370 if (bSize == 1)
371 return (signed char)buff[0];
372 else if (bSize == 2)
373 return (signed short)(buff[0] | (buff[1]<<8));
374 else if (bSize == 4)
375 return (signed int)(buff[0] | (buff[1]<<8) | (buff[2]<<16) | (buff[3]<<24));
376 else
377 return 0;
378}
379
380
381static int hid_parse_item(HID_DEV_T *hdev, uint8_t *buff)
382{
383 uint8_t bTag, bSize, tag;
384 int item_len, i;
385
386 bTag = (buff[0] >> 4) & 0xF;
387 //bType = (buff[0] >> 2) & 0x3;
388 bSize = buff[0] & 0x3;
389 tag = (buff[0] & 0xFC);
390
391 if (bTag == 0xF)
392 {
393 bSize = buff[1];
394 item_len = bSize+3;
395 }
396 else
397 {
398 if (bSize == 0x3)
399 bSize = 4;
400 item_len = bSize+1;
401 }
402
403#if ENABLE_DBG_MSG
404 for (i = 0; i < item_len; i++)
405 {
406 printf("%02x ", buff[i]);
407 }
408 printf("- ");
409#endif
410
411 switch (tag)
412 {
413 /*------------------------------------------------------------------------------------*/
414 /* Main Item Tags */
415 /*------------------------------------------------------------------------------------*/
416
417 case TAG_INPUT:
418 HID_DBGMSG("Input ");
419 read_main_item_status(&buff[1]);
420 if (_data_usage_cnt > 0)
421 {
422 int report_count = _rp_info.report_count;
423
424 for (i = 0; i < _data_usage_cnt; i++)
425 {
426 _rp_info.report_count = 1;
427 _rp_info.data_usage = _data_usages[i];
428 if (hid_add_report(hdev, TAG_INPUT) != 0)
429 return USBH_ERR_MEMORY_OUT;
430 report_count--;
431 }
432 _rp_info.report_count = report_count;
433 _rp_info.data_usage = 0;
434 _data_usage_cnt = 0;
435 }
436 if (_rp_info.report_count > 0)
437 {
438 if (hid_add_report(hdev, TAG_INPUT) != 0)
439 return USBH_ERR_MEMORY_OUT;
440 }
441 break;
442
443 case TAG_OUTPUT:
444 HID_DBGMSG("Output ");
445 read_main_item_status(&buff[1]);
446 if (_rp_info.report_count > 0)
447 {
448 if (hid_add_report(hdev, TAG_OUTPUT) != 0)
449 return USBH_ERR_MEMORY_OUT;
450 }
451 break;
452
453 case TAG_FEATURE:
454 HID_DBGMSG("Feature ");
455 read_main_item_status(&buff[1]);
456 break;
457
458 case TAG_COLLECTION:
459 HID_DBGMSG("Collection ");
460 if (buff[1] == 0x00)
461 HID_DBGMSG("Physical");
462 else if (buff[1] == 0x01)
463 HID_DBGMSG("Application");
464 else if (buff[1] == 0x02)
465 HID_DBGMSG("Logical");
466 break;
467
468 case TAG_END_COLLECTION:
469 HID_DBGMSG("End Collection");
470 break;
471
472 /*------------------------------------------------------------------------------------*/
473 /* Global Item Tags */
474 /*------------------------------------------------------------------------------------*/
475
476 case TAG_USAGE_PAGE:
477 HID_DBGMSG("Usage Page ");
478 _rp_info.usage_page = buff[1];
479 print_usage_page();
480 break;
481
482 case TAG_LOGICAL_MIN:
483 _rp_info.logical_min = hid_read_item_value(bSize, &buff[1]);
484 HID_DBGMSG("Logical Minimum (%d)", _rp_info.logical_min);
485 break;
486
487 case TAG_LOGICAL_MAX:
488 _rp_info.logical_max = hid_read_item_value(bSize, &buff[1]);
489 HID_DBGMSG("Logical Maximum (%d)", _rp_info.logical_max);
490 break;
491
492 case TAG_PHYSICAL_MIN:
493 _rp_info.physical_min = hid_read_item_value(bSize, &buff[1]);
494 HID_DBGMSG("Physical Minimum (%d)", _rp_info.physical_min);
495 break;
496
497 case TAG_PHYSICAL_MAX:
498 _rp_info.physical_max = hid_read_item_value(bSize, &buff[1]);
499 HID_DBGMSG("Physical Maximum (%d)", _rp_info.physical_max);
500 break;
501
502 case TAG_UNIT_EXPONENT:
503 _rp_info.unit_exponent = hid_read_item_value(bSize, &buff[1]);
504 HID_DBGMSG("Unit Exponent (%d)", _rp_info.unit_exponent);
505 break;
506
507 case TAG_UNIT:
508 _rp_info.unit = hid_read_item_value(bSize, &buff[1]);
509 HID_DBGMSG("Unit (%d)", _rp_info.unit);
510 break;
511
512 case TAG_REPORT_SIZE:
513 _rp_info.report_size = buff[1];
514 HID_DBGMSG("Report Size (%d)", _rp_info.report_size);
515 break;
516
517 case TAG_REPORT_ID:
518 _rp_info.report_id = buff[1];
519 hdev->rpd.has_report_id = 1;
520 HID_DBGMSG("Report ID (%d)", _rp_info.report_id);
521 break;
522
523 case TAG_REPORT_COUNT:
524 _rp_info.report_count = buff[1];
525 HID_DBGMSG("Report Count (%d)", _rp_info.report_count);
526 break;
527
528 case TAG_PUSH:
529 HID_DBGMSG("PUSH");
530 break;
531
532 case TAG_POP:
533 HID_DBGMSG("POP");
534 break;
535
536 /*------------------------------------------------------------------------------------*/
537 /* Local Item Tags */
538 /*------------------------------------------------------------------------------------*/
539
540 case TAG_USAGE:
541 if ((buff[1] == USAGE_ID_X) || (buff[1] == USAGE_ID_Y) || (buff[1] == USAGE_ID_WHEEL))
542 _data_usages[_data_usage_cnt++] = buff[1]; /* interested usages */
543 else
544 _rp_info.app_usage = buff[1];
545 HID_DBGMSG("Usage ");
546 print_usage(buff[1]);
547 break;
548
549 case TAG_USAGE_MIN:
550 _rp_info.usage_mim = hid_read_item_value(bSize, &buff[1]);
551 HID_DBGMSG("Usage Mimimum (%d)", _rp_info.usage_mim);
552 break;
553
554 case TAG_USAGE_MAX:
555 _rp_info.usage_max = hid_read_item_value(bSize, &buff[1]);
556 HID_DBGMSG("Usage Maximum (%d)", _rp_info.usage_max);
557 break;
558
559 case TAG_DESIGNATOR_INDEX:
560 _rp_info.designator_index = hid_read_item_value(bSize, &buff[1]);
561 HID_DBGMSG("Designator Index (%d)", _rp_info.designator_index);
562 break;
563
564 case TAG_DESIGNATOR_MIN:
565 _rp_info.designator_min = hid_read_item_value(bSize, &buff[1]);
566 HID_DBGMSG("Designator Minimum (%d)", _rp_info.designator_min);
567 break;
568
569 case TAG_DESIGNATOR_MAX:
570 _rp_info.designator_max = hid_read_item_value(bSize, &buff[1]);
571 HID_DBGMSG("Designator Maximum (%d)", _rp_info.designator_max);
572 break;
573
574 case TAG_STRING_INDEX:
575 _rp_info.string_index = hid_read_item_value(bSize, &buff[1]);
576 HID_DBGMSG("String Index (%d)", _rp_info.string_index);
577 break;
578
579 case TAG_STRING_MIN:
580 _rp_info.string_min = hid_read_item_value(bSize, &buff[1]);
581 HID_DBGMSG("String Minimum (%d)", _rp_info.string_min);
582 break;
583
584 case TAG_STRING_MAX:
585 _rp_info.string_max = hid_read_item_value(bSize, &buff[1]);
586 HID_DBGMSG("String Maximum (%d)", _rp_info.string_max);
587 break;
588
589 case TAG_DELIMITER:
590 HID_DBGMSG("Delimiter");
591 break;
592
593 default:
594 HID_DBGMSG("Unknow tag: 0x%x\n", tag);
595 break;
596 }
597 HID_DBGMSG("\n");
598
599 return item_len;
600}
601
602
603int hid_parse_keyboard_reports(HID_DEV_T *hdev, uint8_t *data, int data_len)
604{
605 RP_INFO_T *report;
606 int i, bit;
607 int byte_idx = 0, bit_idx = 0;
608 int has_kbd_event = 0;
609 int report_id;
610 static KEYBOARD_EVENT_T _keyboard_event;
611
612 memset(&_keyboard_event, 0, sizeof(_keyboard_event));
613 _keyboard_event.lock_state = hdev->rpd.lock_state;
614
615 /*
616 * Does this device use report ID?
617 */
618 if (hdev->rpd.has_report_id && (byte_idx == 0))
619 {
620 report_id = data[0];
621 bit_idx = 8;
622 byte_idx = 1;
623 }
624
625 for (report = hdev->rpd.report; report != NULL; report = report->next)
626 {
627 if (hdev->rpd.has_report_id && (report->report_id != report_id))
628 continue;
629
630 if (report->type != TAG_INPUT)
631 continue;
632
633 /*----------------------------------------------------------------------*/
634 /* Extract keyboard report; only KeyCode reports are interested */
635 /*----------------------------------------------------------------------*/
636 if ((report->usage_page == UP_KEYCODE) && (report->app_usage == USAGE_ID_KEYBOARD))
637 {
638 uint32_t usage_val;
639
640 if ((report->report_size != 1) && (report->report_size != 8))
641 {
642 /* unlikely! seems violate HID spec. */
643 HID_ERRMSG("Keycode report size %d is not supported!\n", report->report_size);
645 }
646
647 if (report->report_size == 1)
648 {
649 usage_val = 0;
650 for (i = 0; i < report->report_count; i++)
651 {
652 bit = (data[byte_idx] >> (bit_idx % 8)) & 0x1;
653 usage_val |= (bit << i);
654
655 if (bit_idx < 8) /* is in the first byte */
656 {
657 _keyboard_event.modifier |= usage_val;
658 }
659 else if (bit_idx < 16) /* is in the second byte (reserved) */
660 {
661 }
662 else
663 {
664 if (bit_idx < 8*8)
665 _keyboard_event.keycode[(bit_idx-16)/8] |= usage_val;
666 }
667 bit_idx++;
668 }
669 byte_idx = (bit_idx / 8);
670 }
671 else /* report->report_size == 8 */
672 {
673 for (i = 0; i < report->report_count; i++)
674 {
675 if (byte_idx == 0)
676 {
677 _keyboard_event.modifier = data[byte_idx];
678 }
679 else if (byte_idx == 1)
680 {
681 /* reserved byte */
682 }
683 else
684 {
685 if (byte_idx < 8)
686 {
687 _keyboard_event.keycode[byte_idx-2] = data[byte_idx];
688 }
689 }
690 byte_idx++;
691 }
692 }
693 has_kbd_event = 1;
694 }
695 else
696 {
697 /* not interested, just skip it */
698 bit_idx += report->report_size * report->report_count;
699 byte_idx = (bit_idx / 8);
700 }
701
702 if (byte_idx >= data_len)
703 break;
704 }
705
706 if ((has_kbd_event) && (_keyboard_callback != NULL))
707 {
708 uint8_t pressed_lock_keys = 0;
709 char update_LEDs = 0;
710
711 /*----------------------------------------------------------------------*/
712 /* Scan received key code sequence */
713 /*----------------------------------------------------------------------*/
714 for (i = 0; i < 6; i++)
715 {
716 switch (_keyboard_event.keycode[i])
717 {
718 case KEYCODE_NUM_LOCK:
719 pressed_lock_keys |= STATE_MASK_NUM_LOCK;
720 break;
721 case KEYCODE_CAPS_LOCK:
722 pressed_lock_keys |= STATE_MASK_CAPS_LOCK;
723 break;
724 case KEYCODE_SCROLL_LOCK:
725 pressed_lock_keys |= STATE_MASK_SCROLL_LOCK;
726 break;
727 case 0: /* empty */
728 case 1: /* error */
729 break;
730
731 default:
732 _keyboard_event.keycode[_keyboard_event.key_cnt++] = _keyboard_event.keycode[i];
733 }
734 }
735
736 /*----------------------------------------------------------------------*/
737 /* Update lock keys (Num Lock, Caps Lock, Scroll Lock) */
738 /*----------------------------------------------------------------------*/
739 for (i = 0; i < 3; i++)
740 {
741 if ((pressed_lock_keys & (1<<i)) && (!(hdev->rpd.last_pressed_lock_keys & (1<<i))))
742 {
743 /*
744 * A lock key pressed and it is not pressed in the last time.
745 * It should be a press down of the lock key.
746 */
747 _keyboard_event.lock_state ^= (1<<i); /* switch on/off the corresponding lock state */
748 update_LEDs = 1;
749 }
750 }
751 hdev->rpd.last_pressed_lock_keys = pressed_lock_keys; /* record the lock key press state for next time. */
752 hdev->rpd.lock_state = _keyboard_event.lock_state;
753
754 if (update_LEDs)
755 {
756 usbh_hid_set_report_non_blocking(hdev, RT_OUTPUT, 0, &_keyboard_event.lock_state, 1);
757 }
758
759 _keyboard_callback(hdev, &_keyboard_event);
760 }
761 return 0;
762}
763
764int hid_parse_mouse_reports(HID_DEV_T *hdev, uint8_t *data, int data_len)
765{
766 int byte_idx = 0, bit_idx = 0;
767 RP_INFO_T *report;
768 int i, bit;
769 int has_mouse_event = 0;
770 int report_id;
771 static MOUSE_EVENT_T _mouse_event;
772
773 memset(&_mouse_event, 0, sizeof(_mouse_event));
774
775 /*
776 * Does this device use report ID?
777 */
778 if (hdev->rpd.has_report_id && (byte_idx == 0))
779 {
780 report_id = data[0];
781 bit_idx = 8;
782 byte_idx = 1;
783 }
784
785 for (report = hdev->rpd.report; report != NULL; report = report->next)
786 {
787 if (hdev->rpd.has_report_id && (report->report_id != report_id))
788 continue;
789
790 if (report->type != TAG_INPUT)
791 continue;
792
793 /*----------------------------------------------------------------------*/
794 /* Extract mouse button report */
795 /*----------------------------------------------------------------------*/
796 if ((report->usage_page == UP_BUTTON) &&
797 ((report->app_usage == USAGE_ID_MOUSE) || (report->app_usage == USAGE_ID_POINTER)))
798 {
799 /* Get button data */
800 if (report->status.variable)
801 {
802 _mouse_event.button_cnt = report->report_count;
803 for (i = 0; i < report->report_count; i++)
804 {
805 bit = (data[byte_idx] >> (bit_idx % 8)) & 0x1;
806 _mouse_event.button_map |= (bit << i);
807 bit_idx += report->report_size;
808 byte_idx = (bit_idx / 8);
809 }
810 }
811 else
812 {
813 /* ignore constant padding bits */
814 bit_idx += report->report_count * report->report_size;
815 byte_idx = (bit_idx / 8);
816 }
817 has_mouse_event = 1;
818 }
819
820 /*----------------------------------------------------------------------*/
821 /* Extract mouse X, Y, and WHEEL reports */
822 /*----------------------------------------------------------------------*/
823 else if ((report->usage_page == UP_GENERIC_DESKTOP) &&
824 ((report->app_usage == USAGE_ID_MOUSE) || (report->app_usage == USAGE_ID_POINTER) ||
825 (report->data_usage == USAGE_ID_WHEEL)))
826 {
827 uint32_t usage_val = 0;
828 signed s_val;
829
830 for (i = 0; i < report->report_size; i++)
831 {
832 bit = (data[byte_idx] >> (bit_idx % 8)) & 0x1;
833 usage_val |= (bit << i);
834 bit_idx++;
835 byte_idx = (bit_idx / 8);
836 }
837
838 if (report->report_size <= 8)
839 s_val = (signed char)usage_val;
840 else if (report->report_size <= 16)
841 s_val = (signed short)usage_val;
842
843 if (report->data_usage == USAGE_ID_X)
844 {
845 _mouse_event.X = s_val;
846 _mouse_event.X_raw = usage_val;
847 _mouse_event.X_bits = report->report_size;
848 _mouse_event.axis_relative = report->status.relative;
849 _mouse_event.axis_min = report->logical_min;
850 _mouse_event.axis_max = report->logical_max;
851 }
852 else if (report->data_usage == USAGE_ID_Y)
853 {
854 _mouse_event.Y = s_val;
855 _mouse_event.Y_raw = usage_val;
856 _mouse_event.Y_bits = report->report_size;
857 }
858 else if (report->data_usage == USAGE_ID_WHEEL)
859 {
860 _mouse_event.wheel = s_val;
861 _mouse_event.wheel_raw = usage_val;
862 _mouse_event.wheel_bits = report->report_size;
863 _mouse_event.wheel_relative = report->status.relative;
864 _mouse_event.wheel_min = report->logical_min;
865 _mouse_event.wheel_max = report->logical_max;
866 }
867 has_mouse_event = 1;
868 }
869 else
870 {
871 /* not supported, just skip it */
872 bit_idx += report->report_size;
873 byte_idx = (bit_idx / 8);
874 }
875
876 if (byte_idx >= data_len)
877 break;
878 }
879
880 if ((has_mouse_event) && (_mouse_callback != NULL))
881 {
882 _mouse_callback(hdev, &_mouse_event);
883 // HID_DBGMSG("X: %d, Y: %d, W: %d, button: 0x%x\n", _mouse_event.X, _mouse_event.Y, _mouse_event.wheel, _mouse_event.button_map);
884 }
885
886 return 0;
887}
888
889
891
892
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
Definition: M480.h:605
#define USBH_ERR_NOT_SUPPORTED
Definition: usbh_lib.h:35
#define RT_OUTPUT
Definition: usbh_hid.h:165
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
#define HID_RET_PARSING
Definition: usbh_lib.h:92
signed int wheel_min
Definition: usbh_hid.h:308
signed int Y
Definition: usbh_hid.h:307
uint8_t keycode[6]
Definition: usbh_hid.h:289
uint32_t button_map
Definition: usbh_hid.h:303
int32_t usbh_hid_get_report_descriptor(struct usbhid_dev *hdev, uint8_t *desc_buf, int buf_max_len)
uint8_t button_cnt
Definition: usbh_hid.h:302
uint8_t wheel_relative
Definition: usbh_hid.h:301
signed int wheel
Definition: usbh_hid.h:310
signed int axis_min
Definition: usbh_hid.h:304
uint32_t X_raw
Definition: usbh_hid.h:314
uint32_t wheel_raw
Definition: usbh_hid.h:316
uint32_t Y_raw
Definition: usbh_hid.h:315
signed int wheel_max
Definition: usbh_hid.h:309
uint8_t axis_relative
Definition: usbh_hid.h:300
int32_t usbh_hid_set_report(struct usbhid_dev *hdev, int rtp_typ, int rtp_id, uint8_t *data, int len)
signed int axis_max
Definition: usbh_hid.h:305
signed int X
Definition: usbh_hid.h:306
HIDDEN_SYMBOLS struct usbhid_dev HID_DEV_T
USB Host library header file.
USB Host HID class driver header file.
USB Host library exported header file.