furi-hal-usb-hid.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. #include "furi-hal-version.h"
  2. #include "furi-hal-usb_i.h"
  3. #include "furi-hal-usb.h"
  4. #include "furi-hal-usb-hid.h"
  5. #include <furi.h>
  6. #include "usb.h"
  7. #include "usb_hid.h"
  8. #include "hid_usage_desktop.h"
  9. #include "hid_usage_button.h"
  10. #include "hid_usage_keyboard.h"
  11. #define HID_RIN_EP 0x81
  12. #define HID_RIN_SZ 0x10
  13. #define HID_KB_MAX_KEYS 6
  14. struct HidIadDescriptor {
  15. struct usb_iad_descriptor hid_iad;
  16. struct usb_interface_descriptor hid;
  17. struct usb_hid_descriptor hid_desc;
  18. struct usb_endpoint_descriptor hid_ep;
  19. };
  20. struct HidConfigDescriptor {
  21. struct usb_config_descriptor config;
  22. struct HidIadDescriptor iad_0;
  23. } __attribute__((packed));
  24. enum HidReportId {
  25. ReportIdKeyboard = 1,
  26. ReportIdMouse = 2,
  27. };
  28. /* HID report: keyboard+mouse */
  29. static const uint8_t hid_report_desc[] = {
  30. HID_USAGE_PAGE(HID_PAGE_DESKTOP),
  31. HID_USAGE(HID_DESKTOP_KEYBOARD),
  32. HID_COLLECTION(HID_APPLICATION_COLLECTION),
  33. HID_REPORT_ID(ReportIdKeyboard),
  34. HID_USAGE_PAGE(HID_DESKTOP_KEYPAD),
  35. HID_USAGE_MINIMUM(HID_KEYBOARD_L_CTRL),
  36. HID_USAGE_MAXIMUM(HID_KEYBOARD_R_GUI),
  37. HID_LOGICAL_MINIMUM(0),
  38. HID_LOGICAL_MAXIMUM(1),
  39. HID_REPORT_SIZE(1),
  40. HID_REPORT_COUNT(8),
  41. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
  42. HID_REPORT_COUNT(1),
  43. HID_REPORT_SIZE(8),
  44. HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
  45. HID_REPORT_COUNT(6),
  46. HID_REPORT_SIZE(8),
  47. HID_LOGICAL_MINIMUM(0),
  48. HID_LOGICAL_MAXIMUM(101),
  49. HID_USAGE_PAGE(HID_DESKTOP_KEYPAD),
  50. HID_USAGE_MINIMUM(0),
  51. HID_USAGE_MAXIMUM(101),
  52. HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
  53. HID_END_COLLECTION,
  54. HID_USAGE_PAGE(HID_PAGE_DESKTOP),
  55. HID_USAGE(HID_DESKTOP_MOUSE),
  56. HID_COLLECTION(HID_APPLICATION_COLLECTION),
  57. HID_USAGE(HID_DESKTOP_POINTER),
  58. HID_COLLECTION(HID_PHYSICAL_COLLECTION),
  59. HID_REPORT_ID(ReportIdMouse),
  60. HID_USAGE_PAGE(HID_PAGE_BUTTON),
  61. HID_USAGE_MINIMUM(1),
  62. HID_USAGE_MAXIMUM(3),
  63. HID_LOGICAL_MINIMUM(0),
  64. HID_LOGICAL_MAXIMUM(1),
  65. HID_REPORT_COUNT(3),
  66. HID_REPORT_SIZE(1),
  67. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
  68. HID_REPORT_SIZE(1),
  69. HID_REPORT_COUNT(5),
  70. HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
  71. HID_USAGE_PAGE(HID_PAGE_DESKTOP),
  72. HID_USAGE(HID_DESKTOP_X),
  73. HID_USAGE(HID_DESKTOP_Y),
  74. HID_USAGE(HID_DESKTOP_WHEEL),
  75. HID_LOGICAL_MINIMUM(-127),
  76. HID_LOGICAL_MAXIMUM(127),
  77. HID_REPORT_SIZE(8),
  78. HID_REPORT_COUNT(3),
  79. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
  80. HID_END_COLLECTION,
  81. HID_END_COLLECTION,
  82. };
  83. static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Logitech");
  84. static const struct usb_string_descriptor dev_prod_desc = USB_STRING_DESC("USB Receiver");
  85. static const struct usb_string_descriptor dev_serial_desc = USB_STRING_DESC("1234567890");
  86. /* Device descriptor */
  87. static const struct usb_device_descriptor hid_device_desc = {
  88. .bLength = sizeof(struct usb_device_descriptor),
  89. .bDescriptorType = USB_DTYPE_DEVICE,
  90. .bcdUSB = VERSION_BCD(2,0,0),
  91. .bDeviceClass = USB_CLASS_IAD,
  92. .bDeviceSubClass = USB_SUBCLASS_IAD,
  93. .bDeviceProtocol = USB_PROTO_IAD,
  94. .bMaxPacketSize0 = USB_EP0_SIZE,
  95. .idVendor = 0x046d,
  96. .idProduct = 0xc529,
  97. .bcdDevice = VERSION_BCD(1,0,0),
  98. .iManufacturer = UsbDevManuf,
  99. .iProduct = UsbDevProduct,
  100. .iSerialNumber = UsbDevSerial,
  101. .bNumConfigurations = 1,
  102. };
  103. /* Device configuration descriptor */
  104. static const struct HidConfigDescriptor hid_cfg_desc = {
  105. .config = {
  106. .bLength = sizeof(struct usb_config_descriptor),
  107. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  108. .wTotalLength = sizeof(struct HidConfigDescriptor),
  109. .bNumInterfaces = 1,
  110. .bConfigurationValue = 1,
  111. .iConfiguration = NO_DESCRIPTOR,
  112. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  113. .bMaxPower = USB_CFG_POWER_MA(100),
  114. },
  115. .iad_0 = {
  116. .hid_iad = {
  117. .bLength = sizeof(struct usb_iad_descriptor),
  118. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  119. .bFirstInterface = 0,
  120. .bInterfaceCount = 1,
  121. .bFunctionClass = USB_CLASS_PER_INTERFACE,
  122. .bFunctionSubClass = USB_SUBCLASS_NONE,
  123. .bFunctionProtocol = USB_PROTO_NONE,
  124. .iFunction = NO_DESCRIPTOR,
  125. },
  126. .hid = {
  127. .bLength = sizeof(struct usb_interface_descriptor),
  128. .bDescriptorType = USB_DTYPE_INTERFACE,
  129. .bInterfaceNumber = 0,
  130. .bAlternateSetting = 0,
  131. .bNumEndpoints = 1,
  132. .bInterfaceClass = USB_CLASS_HID,
  133. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  134. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  135. .iInterface = NO_DESCRIPTOR,
  136. },
  137. .hid_desc = {
  138. .bLength = sizeof(struct usb_hid_descriptor),
  139. .bDescriptorType = USB_DTYPE_HID,
  140. .bcdHID = VERSION_BCD(1,0,0),
  141. .bCountryCode = USB_HID_COUNTRY_NONE,
  142. .bNumDescriptors = 1,
  143. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  144. .wDescriptorLength0 = sizeof(hid_report_desc),
  145. },
  146. .hid_ep = {
  147. .bLength = sizeof(struct usb_endpoint_descriptor),
  148. .bDescriptorType = USB_DTYPE_ENDPOINT,
  149. .bEndpointAddress = HID_RIN_EP,
  150. .bmAttributes = USB_EPTYPE_INTERRUPT,
  151. .wMaxPacketSize = HID_RIN_SZ,
  152. .bInterval = 10,
  153. },
  154. },
  155. };
  156. struct HidReportMouse {
  157. uint8_t report_id;
  158. uint8_t btn;
  159. int8_t x;
  160. int8_t y;
  161. int8_t wheel;
  162. } __attribute__((packed));
  163. struct HidReportKB {
  164. uint8_t report_id;
  165. uint8_t mods;
  166. uint8_t reserved;
  167. uint8_t btn[HID_KB_MAX_KEYS];
  168. } __attribute__((packed));
  169. static struct HidReport {
  170. struct HidReportKB keyboard;
  171. struct HidReportMouse mouse;
  172. } __attribute__((packed)) hid_report;
  173. static void hid_init(usbd_device* dev, UsbInterface* intf);
  174. static void hid_deinit(usbd_device *dev);
  175. static void hid_on_wakeup(usbd_device *dev);
  176. static void hid_on_suspend(usbd_device *dev);
  177. static bool hid_send_report(uint8_t report_id);
  178. static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg);
  179. static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback);
  180. static usbd_device* usb_dev;
  181. static osSemaphoreId_t hid_semaphore = NULL;
  182. static bool hid_connected = false;
  183. static HidStateCallback callback;
  184. static void* cb_ctx;
  185. bool furi_hal_hid_is_connected() {
  186. return hid_connected;
  187. }
  188. void furi_hal_hid_set_state_callback(HidStateCallback cb, void* ctx) {
  189. if (callback != NULL) {
  190. if (hid_connected == true)
  191. callback(false, cb_ctx);
  192. }
  193. callback = cb;
  194. cb_ctx = ctx;
  195. if (callback != NULL) {
  196. if (hid_connected == true)
  197. callback(true, cb_ctx);
  198. }
  199. }
  200. bool furi_hal_hid_kb_press(uint16_t button) {
  201. for (uint8_t key_nb = 0; key_nb < HID_KB_MAX_KEYS; key_nb++) {
  202. if (hid_report.keyboard.btn[key_nb] == 0) {
  203. hid_report.keyboard.btn[key_nb] = button & 0xFF;
  204. break;
  205. }
  206. }
  207. hid_report.keyboard.mods |= (button >> 8);
  208. return hid_send_report(ReportIdKeyboard);
  209. }
  210. bool furi_hal_hid_kb_release(uint16_t button) {
  211. for (uint8_t key_nb = 0; key_nb < HID_KB_MAX_KEYS; key_nb++) {
  212. if (hid_report.keyboard.btn[key_nb] == (button & 0xFF)) {
  213. hid_report.keyboard.btn[key_nb] = 0;
  214. break;
  215. }
  216. }
  217. hid_report.keyboard.mods &= ~(button >> 8);
  218. return hid_send_report(ReportIdKeyboard);
  219. }
  220. bool furi_hal_hid_kb_release_all() {
  221. for (uint8_t key_nb = 0; key_nb < HID_KB_MAX_KEYS; key_nb++) {
  222. hid_report.keyboard.btn[key_nb] = 0;
  223. }
  224. hid_report.keyboard.mods = 0;
  225. return hid_send_report(ReportIdKeyboard);
  226. }
  227. bool furi_hal_hid_mouse_move(int8_t dx, int8_t dy) {
  228. hid_report.mouse.x = dx;
  229. hid_report.mouse.y = dy;
  230. bool state = hid_send_report(ReportIdMouse);
  231. hid_report.mouse.x = 0;
  232. hid_report.mouse.y = 0;
  233. return state;
  234. }
  235. bool furi_hal_hid_mouse_press(uint8_t button) {
  236. hid_report.mouse.btn |= button;
  237. return hid_send_report(ReportIdMouse);
  238. }
  239. bool furi_hal_hid_mouse_release(uint8_t button) {
  240. hid_report.mouse.btn &= ~button;
  241. return hid_send_report(ReportIdMouse);
  242. }
  243. bool furi_hal_hid_mouse_scroll(int8_t delta) {
  244. hid_report.mouse.wheel = delta;
  245. bool state = hid_send_report(ReportIdMouse);
  246. hid_report.mouse.wheel = 0;
  247. return state;
  248. }
  249. UsbInterface usb_hid = {
  250. .init = hid_init,
  251. .deinit = hid_deinit,
  252. .wakeup = hid_on_wakeup,
  253. .suspend = hid_on_suspend,
  254. .dev_descr = (struct usb_device_descriptor*)&hid_device_desc,
  255. .str_manuf_descr = (void*)&dev_manuf_desc,
  256. .str_prod_descr = (void*)&dev_prod_desc,
  257. .str_serial_descr = (void*)&dev_serial_desc,
  258. .cfg_descr = (void*)&hid_cfg_desc,
  259. };
  260. static void hid_init(usbd_device* dev, UsbInterface* intf) {
  261. if (hid_semaphore == NULL)
  262. hid_semaphore = osSemaphoreNew(1, 1, NULL);
  263. usb_dev = dev;
  264. hid_report.keyboard.report_id = ReportIdKeyboard;
  265. hid_report.mouse.report_id = ReportIdMouse;
  266. usbd_reg_config(dev, hid_ep_config);
  267. usbd_reg_control(dev, hid_control);
  268. usbd_connect(dev, true);
  269. }
  270. static void hid_deinit(usbd_device *dev) {
  271. usbd_reg_config(dev, NULL);
  272. usbd_reg_control(dev, NULL);
  273. }
  274. static void hid_on_wakeup(usbd_device *dev) {
  275. if (hid_connected == false) {
  276. hid_connected = true;
  277. if (callback != NULL)
  278. callback(true, cb_ctx);
  279. }
  280. }
  281. static void hid_on_suspend(usbd_device *dev) {
  282. if (hid_connected == true) {
  283. hid_connected = false;
  284. osSemaphoreRelease(hid_semaphore);
  285. if (callback != NULL)
  286. callback(false, cb_ctx);
  287. }
  288. }
  289. static bool hid_send_report(uint8_t report_id)
  290. {
  291. if ((hid_semaphore == NULL) || (hid_connected == false))
  292. return false;
  293. furi_check(osSemaphoreAcquire(hid_semaphore, osWaitForever) == osOK);
  294. if (hid_connected == true) {
  295. if (report_id == ReportIdKeyboard)
  296. usbd_ep_write(usb_dev, HID_RIN_EP, &hid_report.keyboard, sizeof(hid_report.keyboard));
  297. else
  298. usbd_ep_write(usb_dev, HID_RIN_EP, &hid_report.mouse, sizeof(hid_report.mouse));
  299. return true;
  300. }
  301. return false;
  302. }
  303. static void hid_ep_callback(usbd_device *dev, uint8_t event, uint8_t ep) {
  304. osSemaphoreRelease(hid_semaphore);
  305. }
  306. /* Configure endpoints */
  307. static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg) {
  308. switch (cfg) {
  309. case 0:
  310. /* deconfiguring device */
  311. usbd_ep_deconfig(dev, HID_RIN_EP);
  312. usbd_reg_endpoint(dev, HID_RIN_EP, 0);
  313. return usbd_ack;
  314. case 1:
  315. /* configuring device */
  316. usbd_ep_config(dev, HID_RIN_EP, USB_EPTYPE_INTERRUPT, HID_RIN_SZ);
  317. usbd_reg_endpoint(dev, HID_RIN_EP, hid_ep_callback);
  318. usbd_ep_write(dev, HID_RIN_EP, 0, 0);
  319. return usbd_ack;
  320. default:
  321. return usbd_fail;
  322. }
  323. }
  324. /* Control requests handler */
  325. static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {
  326. /* HID control requests */
  327. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS)
  328. && req->wIndex == 0 ) {
  329. switch (req->bRequest) {
  330. case USB_HID_SETIDLE:
  331. return usbd_ack;
  332. case USB_HID_GETREPORT:
  333. dev->status.data_ptr = &hid_report;
  334. dev->status.data_count = sizeof(hid_report);
  335. return usbd_ack;
  336. default:
  337. return usbd_fail;
  338. }
  339. }
  340. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_STANDARD)
  341. && req->wIndex == 0
  342. && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  343. switch (req->wValue >> 8) {
  344. case USB_DTYPE_HID:
  345. dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.iad_0.hid_desc);
  346. dev->status.data_count = sizeof(hid_cfg_desc.iad_0.hid_desc);
  347. return usbd_ack;
  348. case USB_DTYPE_HID_REPORT:
  349. dev->status.data_ptr = (uint8_t*)hid_report_desc;
  350. dev->status.data_count = sizeof(hid_report_desc);
  351. return usbd_ack;
  352. default:
  353. return usbd_fail;
  354. }
  355. }
  356. return usbd_fail;
  357. }