usbd_hid.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /**
  2. * @file usbd_hid.c
  3. * @brief
  4. *
  5. * Copyright (c) 2022 sakumisu
  6. *
  7. * Licensed to the Apache Software Foundation (ASF) under one or more
  8. * contributor license agreements. See the NOTICE file distributed with
  9. * this work for additional information regarding copyright ownership. The
  10. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  11. * "License"); you may not use this file except in compliance with the
  12. * License. You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  18. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  19. * License for the specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. */
  23. #include "usbd_core.h"
  24. #include "usbd_hid.h"
  25. #define HID_STATE_IDLE 0
  26. #define HID_STATE_BUSY 1
  27. struct usbd_hid {
  28. const uint8_t *hid_descriptor;
  29. const uint8_t *hid_report_descriptor;
  30. uint32_t hid_report_descriptor_len;
  31. uint8_t intf_num;
  32. uint8_t hid_state;
  33. uint8_t report;
  34. uint8_t idle_state;
  35. uint8_t protocol;
  36. usb_slist_t list;
  37. };
  38. static usb_slist_t usbd_hid_head = USB_SLIST_OBJECT_INIT(usbd_hid_head);
  39. static void usbd_hid_reset(void)
  40. {
  41. usb_slist_t *i;
  42. usb_slist_for_each(i, &usbd_hid_head)
  43. {
  44. struct usbd_hid *hid_intf = usb_slist_entry(i, struct usbd_hid, list);
  45. hid_intf->hid_state = HID_STATE_IDLE;
  46. hid_intf->report = 0;
  47. hid_intf->idle_state = 0;
  48. hid_intf->protocol = 0;
  49. }
  50. }
  51. static int hid_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  52. {
  53. USB_LOG_DBG("HID Custom request: "
  54. "bRequest 0x%02x\r\n",
  55. setup->bRequest);
  56. if (((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_IN) &&
  57. setup->bRequest == USB_REQUEST_GET_DESCRIPTOR) {
  58. uint8_t value = (uint8_t)(setup->wValue >> 8);
  59. uint8_t intf_num = (uint8_t)setup->wIndex;
  60. struct usbd_hid *current_hid_class = NULL;
  61. usb_slist_t *i;
  62. usb_slist_for_each(i, &usbd_hid_head)
  63. {
  64. struct usbd_hid *hid_class = usb_slist_entry(i, struct usbd_hid, list);
  65. if (hid_class->intf_num == intf_num) {
  66. current_hid_class = hid_class;
  67. break;
  68. }
  69. }
  70. if (current_hid_class == NULL) {
  71. return -2;
  72. }
  73. switch (value) {
  74. case HID_DESCRIPTOR_TYPE_HID:
  75. USB_LOG_INFO("get HID Descriptor\r\n");
  76. *data = (uint8_t *)current_hid_class->hid_descriptor;
  77. *len = current_hid_class->hid_descriptor[0];
  78. break;
  79. case HID_DESCRIPTOR_TYPE_HID_REPORT:
  80. USB_LOG_INFO("get Report Descriptor\r\n");
  81. *data = (uint8_t *)current_hid_class->hid_report_descriptor;
  82. *len = current_hid_class->hid_report_descriptor_len;
  83. break;
  84. case HID_DESCRIPTOR_TYPE_HID_PHYSICAL:
  85. USB_LOG_INFO("get PHYSICAL Descriptor\r\n");
  86. break;
  87. default:
  88. return -2;
  89. }
  90. return 0;
  91. }
  92. return -1;
  93. }
  94. static int hid_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  95. {
  96. USB_LOG_DBG("HID Class request: "
  97. "bRequest 0x%02x\r\n",
  98. setup->bRequest);
  99. struct usbd_hid *current_hid_class = NULL;
  100. usb_slist_t *i;
  101. uint8_t intf = LO_BYTE(setup->wIndex);
  102. usb_slist_for_each(i, &usbd_hid_head)
  103. {
  104. struct usbd_hid *hid_class = usb_slist_entry(i, struct usbd_hid, list);
  105. if (hid_class->intf_num == intf) {
  106. current_hid_class = hid_class;
  107. break;
  108. }
  109. }
  110. if (current_hid_class == NULL) {
  111. return -2;
  112. }
  113. switch (setup->bRequest) {
  114. case HID_REQUEST_GET_REPORT:
  115. current_hid_class->report = usbh_hid_get_report(intf, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue)); /*report id ,report type*/
  116. *data = (uint8_t *)&current_hid_class->report;
  117. *len = 1;
  118. break;
  119. case HID_REQUEST_GET_IDLE:
  120. current_hid_class->idle_state = usbh_hid_get_idle(intf, LO_BYTE(setup->wValue));
  121. *data = (uint8_t *)&current_hid_class->idle_state;
  122. *len = 1;
  123. break;
  124. case HID_REQUEST_GET_PROTOCOL:
  125. current_hid_class->protocol = usbh_hid_get_protocol(intf);
  126. *data = (uint8_t *)&current_hid_class->protocol;
  127. *len = 1;
  128. break;
  129. case HID_REQUEST_SET_REPORT:
  130. usbh_hid_set_report(intf, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len); /*report id ,report type,report,report len*/
  131. current_hid_class->report = **data;
  132. break;
  133. case HID_REQUEST_SET_IDLE:
  134. usbh_hid_set_idle(intf, LO_BYTE(setup->wValue), HI_BYTE(setup->wIndex)); /*report id ,duration*/
  135. current_hid_class->idle_state = HI_BYTE(setup->wIndex);
  136. break;
  137. case HID_REQUEST_SET_PROTOCOL:
  138. usbh_hid_set_protocol(intf, LO_BYTE(setup->wValue)); /*protocol*/
  139. current_hid_class->protocol = LO_BYTE(setup->wValue);
  140. break;
  141. default:
  142. USB_LOG_WRN("Unhandled HID Class bRequest 0x%02x\r\n", setup->bRequest);
  143. return -1;
  144. }
  145. return 0;
  146. }
  147. static void hid_notify_handler(uint8_t event, void *arg)
  148. {
  149. switch (event) {
  150. case USBD_EVENT_RESET:
  151. usbd_hid_reset();
  152. break;
  153. default:
  154. break;
  155. }
  156. }
  157. int usbd_hid_alloc(uint8_t intf)
  158. {
  159. struct usbd_hid *hid_class = usb_malloc(sizeof(struct usbd_hid));
  160. if (hid_class == NULL) {
  161. USB_LOG_ERR("no memory to alloc hid_class\r\n");
  162. return -1;
  163. }
  164. memset(hid_class, 0, sizeof(struct usbd_hid));
  165. hid_class->intf_num = intf;
  166. usb_slist_add_tail(&usbd_hid_head, &hid_class->list);
  167. return 0;
  168. }
  169. void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
  170. {
  171. static usbd_class_t *last_class = NULL;
  172. if (last_class != devclass) {
  173. last_class = devclass;
  174. usbd_class_register(devclass);
  175. }
  176. intf->class_handler = hid_class_request_handler;
  177. intf->custom_handler = hid_custom_request_handler;
  178. intf->vendor_handler = NULL;
  179. intf->notify_handler = hid_notify_handler;
  180. usbd_class_add_interface(devclass, intf);
  181. usbd_hid_alloc(intf->intf_num);
  182. }
  183. void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc)
  184. {
  185. // usbd_hid_cfg.hid_descriptor = desc;
  186. }
  187. void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len)
  188. {
  189. usb_slist_t *i;
  190. usb_slist_for_each(i, &usbd_hid_head)
  191. {
  192. struct usbd_hid *hid_class = usb_slist_entry(i, struct usbd_hid, list);
  193. if (hid_class->intf_num == intf_num) {
  194. hid_class->hid_report_descriptor = desc;
  195. hid_class->hid_report_descriptor_len = desc_len;
  196. return;
  197. }
  198. }
  199. }
  200. __WEAK uint8_t usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type)
  201. {
  202. return 0;
  203. }
  204. __WEAK uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id)
  205. {
  206. return 0;
  207. }
  208. __WEAK uint8_t usbh_hid_get_protocol(uint8_t intf)
  209. {
  210. return 0;
  211. }
  212. __WEAK void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len)
  213. {
  214. }
  215. __WEAK void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
  216. {
  217. }
  218. __WEAK void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol)
  219. {
  220. }