M480 BSP  V3.05.001
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 
23 static int hid_parse_item(HID_DEV_T *hdev, uint8_t *buff);
24 
25 #if ENABLE_DBG_MSG
26 struct string_table
27 {
28  char string[32];
29  uint8_t code;
30 };
31 
32 static 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 
46 static 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  */
71 static RP_INFO_T _rp_info; /* describing the current report */
72 
73 static uint8_t _data_usages[16];
74 static int _data_usage_cnt;
75 
76 static 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 
93 static 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 
119 static 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 
181 int 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 
341 static 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 
368 static 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 
381 static 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 
603 int 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);
644  return USBH_ERR_NOT_SUPPORTED;
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 
764 int 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 
#define USBH_ERR_NOT_SUPPORTED
Definition: usbh_lib.h:35
int32_t usbh_hid_get_report_descriptor(struct usbhid_dev *hdev, uint8_t *desc_buf, int buf_max_len)
uint8_t keycode[6]
Definition: usbh_hid.h:289
uint8_t axis_relative
Definition: usbh_hid.h:300
NuMicro peripheral access layer header file.
#define RT_OUTPUT
Definition: usbh_hid.h:165
uint32_t X_raw
Definition: usbh_hid.h:314
signed int Y
Definition: usbh_hid.h:307
USB Host HID class driver header file.
uint32_t Y_raw
Definition: usbh_hid.h:315
USB Host library exported header file.
uint8_t button_cnt
Definition: usbh_hid.h:302
uint32_t wheel_raw
Definition: usbh_hid.h:316
signed int axis_max
Definition: usbh_hid.h:305
uint8_t wheel_relative
Definition: usbh_hid.h:301
signed int X
Definition: usbh_hid.h:306
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
signed int axis_min
Definition: usbh_hid.h:304
USB Host library header file.
int32_t usbh_hid_set_report(struct usbhid_dev *hdev, int rtp_typ, int rtp_id, uint8_t *data, int len)
#define HID_RET_PARSING
Definition: usbh_lib.h:92
#define NULL
NULL pointer.
Definition: M480.h:604
signed int wheel
Definition: usbh_hid.h:310
uint32_t button_map
Definition: usbh_hid.h:303
signed int wheel_min
Definition: usbh_hid.h:308
HIDDEN_SYMBOLS struct usbhid_dev HID_DEV_T
signed int wheel_max
Definition: usbh_hid.h:309