furi-hal-usb-hid.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "furi-hal-version.h"
  2. #include "furi-hal-usb_i.h"
  3. #include <furi.h>
  4. #include "usb.h"
  5. #include "usb_hid.h"
  6. #include "hid_usage_desktop.h"
  7. #include "hid_usage_button.h"
  8. #define HID_RIN_EP 0x81
  9. #define HID_RIN_SZ 0x10
  10. struct HidIadDescriptor {
  11. struct usb_iad_descriptor hid_iad;
  12. struct usb_interface_descriptor hid;
  13. struct usb_hid_descriptor hid_desc;
  14. struct usb_endpoint_descriptor hid_ep;
  15. };
  16. struct HidConfigDescriptor {
  17. struct usb_config_descriptor config;
  18. struct HidIadDescriptor iad_0;
  19. } __attribute__((packed));
  20. /* HID mouse report desscriptor. 2 axis 5 buttons */
  21. static const uint8_t hid_report_desc[] = {
  22. HID_USAGE_PAGE(HID_PAGE_DESKTOP),
  23. HID_USAGE(HID_DESKTOP_MOUSE),
  24. HID_COLLECTION(HID_APPLICATION_COLLECTION),
  25. HID_USAGE(HID_DESKTOP_POINTER),
  26. HID_COLLECTION(HID_PHYSICAL_COLLECTION),
  27. HID_USAGE(HID_DESKTOP_X),
  28. HID_USAGE(HID_DESKTOP_Y),
  29. HID_LOGICAL_MINIMUM(-127),
  30. HID_LOGICAL_MAXIMUM(127),
  31. HID_REPORT_SIZE(8),
  32. HID_REPORT_COUNT(2),
  33. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE ),
  34. HID_USAGE_PAGE(HID_PAGE_BUTTON),
  35. HID_USAGE_MINIMUM(1),
  36. HID_USAGE_MAXIMUM(5),
  37. HID_LOGICAL_MINIMUM(0),
  38. HID_LOGICAL_MAXIMUM(1),
  39. HID_REPORT_SIZE(1),
  40. HID_REPORT_COUNT(5),
  41. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE ),
  42. HID_REPORT_SIZE(1),
  43. HID_REPORT_COUNT(3),
  44. HID_INPUT(HID_IOF_CONSTANT),
  45. HID_END_COLLECTION,
  46. HID_END_COLLECTION,
  47. };
  48. static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Logitech");
  49. static const struct usb_string_descriptor dev_prod_desc = USB_STRING_DESC("USB Receiver");
  50. static const struct usb_string_descriptor dev_serial_desc = USB_STRING_DESC("1234567890");
  51. /* Device descriptor */
  52. static const struct usb_device_descriptor hid_device_desc = {
  53. .bLength = sizeof(struct usb_device_descriptor),
  54. .bDescriptorType = USB_DTYPE_DEVICE,
  55. .bcdUSB = VERSION_BCD(2,0,0),
  56. .bDeviceClass = USB_CLASS_IAD,
  57. .bDeviceSubClass = USB_SUBCLASS_IAD,
  58. .bDeviceProtocol = USB_PROTO_IAD,
  59. .bMaxPacketSize0 = USB_EP0_SIZE,
  60. .idVendor = 0x046d,
  61. .idProduct = 0xc529,
  62. .bcdDevice = VERSION_BCD(1,0,0),
  63. .iManufacturer = UsbDevManuf,
  64. .iProduct = UsbDevProduct,
  65. .iSerialNumber = UsbDevSerial,
  66. .bNumConfigurations = 1,
  67. };
  68. /* Device configuration descriptor */
  69. static const struct HidConfigDescriptor hid_cfg_desc = {
  70. .config = {
  71. .bLength = sizeof(struct usb_config_descriptor),
  72. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  73. .wTotalLength = sizeof(struct HidConfigDescriptor),
  74. .bNumInterfaces = 1,
  75. .bConfigurationValue = 1,
  76. .iConfiguration = NO_DESCRIPTOR,
  77. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  78. .bMaxPower = USB_CFG_POWER_MA(100),
  79. },
  80. .iad_0 = {
  81. .hid_iad = {
  82. .bLength = sizeof(struct usb_iad_descriptor),
  83. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  84. .bFirstInterface = 0,
  85. .bInterfaceCount = 1,
  86. .bFunctionClass = USB_CLASS_PER_INTERFACE,
  87. .bFunctionSubClass = USB_SUBCLASS_NONE,
  88. .bFunctionProtocol = USB_PROTO_NONE,
  89. .iFunction = NO_DESCRIPTOR,
  90. },
  91. .hid = {
  92. .bLength = sizeof(struct usb_interface_descriptor),
  93. .bDescriptorType = USB_DTYPE_INTERFACE,
  94. .bInterfaceNumber = 0,
  95. .bAlternateSetting = 0,
  96. .bNumEndpoints = 1,
  97. .bInterfaceClass = USB_CLASS_HID,
  98. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  99. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  100. .iInterface = NO_DESCRIPTOR,
  101. },
  102. .hid_desc = {
  103. .bLength = sizeof(struct usb_hid_descriptor),
  104. .bDescriptorType = USB_DTYPE_HID,
  105. .bcdHID = VERSION_BCD(1,0,0),
  106. .bCountryCode = USB_HID_COUNTRY_NONE,
  107. .bNumDescriptors = 1,
  108. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  109. .wDescriptorLength0 = sizeof(hid_report_desc),
  110. },
  111. .hid_ep = {
  112. .bLength = sizeof(struct usb_endpoint_descriptor),
  113. .bDescriptorType = USB_DTYPE_ENDPOINT,
  114. .bEndpointAddress = HID_RIN_EP,
  115. .bmAttributes = USB_EPTYPE_INTERRUPT,
  116. .wMaxPacketSize = HID_RIN_SZ,
  117. .bInterval = 50,
  118. },
  119. },
  120. };
  121. static struct {
  122. int8_t x;
  123. int8_t y;
  124. uint8_t buttons;
  125. } __attribute__((packed)) hid_report_data;
  126. static void hid_init(usbd_device* dev, struct UsbInterface* intf);
  127. static void hid_deinit(usbd_device *dev);
  128. static void hid_on_wakeup(usbd_device *dev);
  129. static void hid_on_suspend(usbd_device *dev);
  130. static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg);
  131. static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback);
  132. static usbd_device* usb_dev;
  133. struct UsbInterface usb_hid = {
  134. .init = hid_init,
  135. .deinit = hid_deinit,
  136. .wakeup = hid_on_wakeup,
  137. .suspend = hid_on_suspend,
  138. .dev_descr = (struct usb_device_descriptor*)&hid_device_desc,
  139. .str_manuf_descr = (void*)&dev_manuf_desc,
  140. .str_prod_descr = (void*)&dev_prod_desc,
  141. .str_serial_descr = (void*)&dev_serial_desc,
  142. .cfg_descr = (void*)&hid_cfg_desc,
  143. };
  144. static void hid_init(usbd_device* dev, struct UsbInterface* intf) {
  145. usb_dev = dev;
  146. usbd_reg_config(dev, hid_ep_config);
  147. usbd_reg_control(dev, hid_control);
  148. usbd_connect(dev, true);
  149. }
  150. static void hid_deinit(usbd_device *dev) {
  151. usbd_reg_config(dev, NULL);
  152. usbd_reg_control(dev, NULL);
  153. }
  154. static void hid_on_wakeup(usbd_device *dev) {
  155. }
  156. static void hid_on_suspend(usbd_device *dev) {
  157. }
  158. /* HID mouse IN endpoint callback */
  159. static void hid_mouse_move(usbd_device *dev, uint8_t event, uint8_t ep) {
  160. static uint8_t t = 0;
  161. if (t < 0x10) {
  162. hid_report_data.x = 1;
  163. hid_report_data.y = 0;
  164. } else if (t < 0x20) {
  165. hid_report_data.x = 1;
  166. hid_report_data.y = 1;
  167. } else if (t < 0x30) {
  168. hid_report_data.x = 0;
  169. hid_report_data.y = 1;
  170. } else if (t < 0x40) {
  171. hid_report_data.x = -1;
  172. hid_report_data.y = 1;
  173. } else if (t < 0x50) {
  174. hid_report_data.x = -1;
  175. hid_report_data.y = 0;
  176. } else if (t < 0x60) {
  177. hid_report_data.x = -1;
  178. hid_report_data.y = -1;
  179. } else if (t < 0x70) {
  180. hid_report_data.x = 0;
  181. hid_report_data.y = -1;
  182. } else {
  183. hid_report_data.x = 1;
  184. hid_report_data.y = -1;
  185. }
  186. t = (t + 1) & 0x7F;
  187. usbd_ep_write(dev, ep, &hid_report_data, sizeof(hid_report_data));
  188. }
  189. /* Configure endpoints */
  190. static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg) {
  191. switch (cfg) {
  192. case 0:
  193. /* deconfiguring device */
  194. usbd_ep_deconfig(dev, HID_RIN_EP);
  195. usbd_reg_endpoint(dev, HID_RIN_EP, 0);
  196. return usbd_ack;
  197. case 1:
  198. /* configuring device */
  199. usbd_ep_config(dev, HID_RIN_EP, USB_EPTYPE_INTERRUPT, HID_RIN_SZ);
  200. usbd_reg_endpoint(dev, HID_RIN_EP, hid_mouse_move);
  201. usbd_ep_write(dev, HID_RIN_EP, 0, 0);
  202. return usbd_ack;
  203. default:
  204. return usbd_fail;
  205. }
  206. }
  207. /* Control requests handler */
  208. static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {
  209. /* HID control requests */
  210. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS)
  211. && req->wIndex == 0 ) {
  212. switch (req->bRequest) {
  213. case USB_HID_SETIDLE:
  214. return usbd_ack;
  215. case USB_HID_GETREPORT:
  216. dev->status.data_ptr = &hid_report_data;
  217. dev->status.data_count = sizeof(hid_report_data);
  218. return usbd_ack;
  219. default:
  220. return usbd_fail;
  221. }
  222. }
  223. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_STANDARD)
  224. && req->wIndex == 0
  225. && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  226. switch (req->wValue >> 8) {
  227. case USB_DTYPE_HID:
  228. dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.iad_0.hid_desc);
  229. dev->status.data_count = sizeof(hid_cfg_desc.iad_0.hid_desc);
  230. return usbd_ack;
  231. case USB_DTYPE_HID_REPORT:
  232. dev->status.data_ptr = (uint8_t*)hid_report_desc;
  233. dev->status.data_count = sizeof(hid_report_desc);
  234. return usbd_ack;
  235. default:
  236. return usbd_fail;
  237. }
  238. }
  239. return usbd_fail;
  240. }