furi-hal-usb-u2f.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "furi-hal-version.h"
  2. #include "furi-hal-usb_i.h"
  3. #include "furi-hal-usb-hid-u2f.h"
  4. #include "furi-hal-usb.h"
  5. #include <furi.h>
  6. #include "usb.h"
  7. #include "usb_hid.h"
  8. #define HID_PAGE_FIDO 0xF1D0
  9. #define HID_FIDO_U2F 0x01
  10. #define HID_FIDO_INPUT 0x20
  11. #define HID_FIDO_OUTPUT 0x21
  12. #define HID_EP_IN 0x81
  13. #define HID_EP_OUT 0x01
  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_in;
  19. struct usb_endpoint_descriptor hid_ep_out;
  20. };
  21. struct HidConfigDescriptor {
  22. struct usb_config_descriptor config;
  23. struct HidIadDescriptor iad_0;
  24. } __attribute__((packed));
  25. /* HID report: FIDO U2F */
  26. static const uint8_t hid_u2f_report_desc[] = {
  27. HID_RI_USAGE_PAGE(16, HID_PAGE_FIDO),
  28. HID_USAGE(HID_FIDO_U2F),
  29. HID_COLLECTION(HID_APPLICATION_COLLECTION),
  30. HID_USAGE(HID_FIDO_INPUT),
  31. HID_LOGICAL_MINIMUM(0x00),
  32. HID_LOGICAL_MAXIMUM(0xFF),
  33. HID_REPORT_SIZE(8),
  34. HID_REPORT_COUNT(HID_U2F_PACKET_LEN),
  35. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
  36. HID_USAGE(HID_FIDO_OUTPUT),
  37. HID_LOGICAL_MINIMUM(0x00),
  38. HID_LOGICAL_MAXIMUM(0xFF),
  39. HID_REPORT_SIZE(8),
  40. HID_REPORT_COUNT(HID_U2F_PACKET_LEN),
  41. HID_OUTPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
  42. HID_END_COLLECTION,
  43. };
  44. static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Flipper Devices Inc.");
  45. static const struct usb_string_descriptor dev_prod_desc = USB_STRING_DESC("U2F Token test");
  46. static const struct usb_string_descriptor dev_serial_desc = USB_STRING_DESC("TODO: serial");
  47. /* Device descriptor */
  48. static const struct usb_device_descriptor hid_u2f_device_desc = {
  49. .bLength = sizeof(struct usb_device_descriptor),
  50. .bDescriptorType = USB_DTYPE_DEVICE,
  51. .bcdUSB = VERSION_BCD(2, 0, 0),
  52. .bDeviceClass = USB_CLASS_IAD,
  53. .bDeviceSubClass = USB_SUBCLASS_IAD,
  54. .bDeviceProtocol = USB_PROTO_IAD,
  55. .bMaxPacketSize0 = USB_EP0_SIZE,
  56. .idVendor = 0x0483,
  57. .idProduct = 0x5741,
  58. .bcdDevice = VERSION_BCD(1, 0, 0),
  59. .iManufacturer = UsbDevManuf,
  60. .iProduct = UsbDevProduct,
  61. .iSerialNumber = UsbDevSerial,
  62. .bNumConfigurations = 1,
  63. };
  64. /* Device configuration descriptor */
  65. static const struct HidConfigDescriptor hid_u2f_cfg_desc = {
  66. .config =
  67. {
  68. .bLength = sizeof(struct usb_config_descriptor),
  69. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  70. .wTotalLength = sizeof(struct HidConfigDescriptor),
  71. .bNumInterfaces = 1,
  72. .bConfigurationValue = 1,
  73. .iConfiguration = NO_DESCRIPTOR,
  74. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  75. .bMaxPower = USB_CFG_POWER_MA(100),
  76. },
  77. .iad_0 =
  78. {
  79. .hid_iad =
  80. {
  81. .bLength = sizeof(struct usb_iad_descriptor),
  82. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  83. .bFirstInterface = 0,
  84. .bInterfaceCount = 1,
  85. .bFunctionClass = USB_CLASS_PER_INTERFACE,
  86. .bFunctionSubClass = USB_SUBCLASS_NONE,
  87. .bFunctionProtocol = USB_PROTO_NONE,
  88. .iFunction = NO_DESCRIPTOR,
  89. },
  90. .hid =
  91. {
  92. .bLength = sizeof(struct usb_interface_descriptor),
  93. .bDescriptorType = USB_DTYPE_INTERFACE,
  94. .bInterfaceNumber = 0,
  95. .bAlternateSetting = 0,
  96. .bNumEndpoints = 2,
  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. {
  104. .bLength = sizeof(struct usb_hid_descriptor),
  105. .bDescriptorType = USB_DTYPE_HID,
  106. .bcdHID = VERSION_BCD(1, 0, 0),
  107. .bCountryCode = USB_HID_COUNTRY_NONE,
  108. .bNumDescriptors = 1,
  109. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  110. .wDescriptorLength0 = sizeof(hid_u2f_report_desc),
  111. },
  112. .hid_ep_in =
  113. {
  114. .bLength = sizeof(struct usb_endpoint_descriptor),
  115. .bDescriptorType = USB_DTYPE_ENDPOINT,
  116. .bEndpointAddress = HID_EP_IN,
  117. .bmAttributes = USB_EPTYPE_INTERRUPT,
  118. .wMaxPacketSize = HID_U2F_PACKET_LEN,
  119. .bInterval = 5,
  120. },
  121. .hid_ep_out =
  122. {
  123. .bLength = sizeof(struct usb_endpoint_descriptor),
  124. .bDescriptorType = USB_DTYPE_ENDPOINT,
  125. .bEndpointAddress = HID_EP_OUT,
  126. .bmAttributes = USB_EPTYPE_INTERRUPT,
  127. .wMaxPacketSize = HID_U2F_PACKET_LEN,
  128. .bInterval = 5,
  129. },
  130. },
  131. };
  132. static void hid_u2f_init(usbd_device* dev, UsbInterface* intf);
  133. static void hid_u2f_deinit(usbd_device* dev);
  134. static void hid_u2f_on_wakeup(usbd_device* dev);
  135. static void hid_u2f_on_suspend(usbd_device* dev);
  136. //static bool hid_u2f_send_report(uint8_t report_id);
  137. static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg);
  138. static usbd_respond
  139. hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  140. static usbd_device* usb_dev;
  141. static osSemaphoreId_t hid_u2f_semaphore = NULL;
  142. static bool hid_u2f_connected = false;
  143. static HidU2fCallback callback;
  144. static void* cb_ctx;
  145. bool furi_hal_hid_u2f_is_connected() {
  146. return hid_u2f_connected;
  147. }
  148. void furi_hal_hid_u2f_set_callback(HidU2fCallback cb, void* ctx) {
  149. if (callback != NULL) {
  150. if (hid_u2f_connected == true)
  151. callback(HidU2fDisconnected, cb_ctx);
  152. }
  153. callback = cb;
  154. cb_ctx = ctx;
  155. if (callback != NULL) {
  156. if (hid_u2f_connected == true)
  157. callback(HidU2fConnected, cb_ctx);
  158. }
  159. }
  160. UsbInterface usb_hid_u2f = {
  161. .init = hid_u2f_init,
  162. .deinit = hid_u2f_deinit,
  163. .wakeup = hid_u2f_on_wakeup,
  164. .suspend = hid_u2f_on_suspend,
  165. .dev_descr = (struct usb_device_descriptor*)&hid_u2f_device_desc,
  166. .str_manuf_descr = (void*)&dev_manuf_desc,
  167. .str_prod_descr = (void*)&dev_prod_desc,
  168. .str_serial_descr = (void*)&dev_serial_desc,
  169. .cfg_descr = (void*)&hid_u2f_cfg_desc,
  170. };
  171. static void hid_u2f_init(usbd_device* dev, UsbInterface* intf) {
  172. if(hid_u2f_semaphore == NULL) hid_u2f_semaphore = osSemaphoreNew(1, 1, NULL);
  173. usb_dev = dev;
  174. usbd_reg_config(dev, hid_u2f_ep_config);
  175. usbd_reg_control(dev, hid_u2f_control);
  176. usbd_connect(dev, true);
  177. }
  178. static void hid_u2f_deinit(usbd_device* dev) {
  179. usbd_reg_config(dev, NULL);
  180. usbd_reg_control(dev, NULL);
  181. }
  182. static void hid_u2f_on_wakeup(usbd_device* dev) {
  183. hid_u2f_connected = true;
  184. if (callback != NULL)
  185. callback(HidU2fConnected, cb_ctx);
  186. }
  187. static void hid_u2f_on_suspend(usbd_device* dev) {
  188. if(hid_u2f_connected == true) {
  189. hid_u2f_connected = false;
  190. osSemaphoreRelease(hid_u2f_semaphore);
  191. if (callback != NULL)
  192. callback(HidU2fDisconnected, cb_ctx);
  193. }
  194. }
  195. void furi_hal_hid_u2f_send_response(uint8_t* data, uint8_t len) {
  196. if ((hid_u2f_semaphore == NULL) || (hid_u2f_connected == false))
  197. return;
  198. furi_check(osSemaphoreAcquire(hid_u2f_semaphore, osWaitForever) == osOK);
  199. if (hid_u2f_connected == true) {
  200. usbd_ep_write(usb_dev, HID_EP_OUT, data, len);
  201. }
  202. }
  203. uint32_t furi_hal_hid_u2f_get_request(uint8_t* data) {
  204. int32_t len = usbd_ep_read(usb_dev, HID_EP_IN, data, HID_U2F_PACKET_LEN);
  205. return ((len < 0) ? 0 : len);
  206. }
  207. static void hid_u2f_rx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  208. if (callback != NULL)
  209. callback(HidU2fRequest, cb_ctx);
  210. }
  211. static void hid_u2f_tx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  212. osSemaphoreRelease(hid_u2f_semaphore);
  213. }
  214. static void hid_u2f_txrx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  215. if (event == usbd_evt_eptx) {
  216. hid_u2f_tx_ep_callback(dev, event, ep);
  217. } else {
  218. hid_u2f_rx_ep_callback(dev, event, ep);
  219. }
  220. }
  221. /* Configure endpoints */
  222. static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg) {
  223. switch(cfg) {
  224. case 0:
  225. /* deconfiguring device */
  226. usbd_ep_deconfig(dev, HID_EP_IN);
  227. usbd_ep_deconfig(dev, HID_EP_OUT);
  228. usbd_reg_endpoint(dev, HID_EP_IN, 0);
  229. usbd_reg_endpoint(dev, HID_EP_OUT, 0);
  230. return usbd_ack;
  231. case 1:
  232. /* configuring device */
  233. usbd_ep_config(dev, HID_EP_IN, USB_EPTYPE_INTERRUPT, HID_U2F_PACKET_LEN);
  234. usbd_ep_config(dev, HID_EP_OUT, USB_EPTYPE_INTERRUPT, HID_U2F_PACKET_LEN);
  235. usbd_reg_endpoint(dev, HID_EP_IN, hid_u2f_txrx_ep_callback);
  236. usbd_reg_endpoint(dev, HID_EP_OUT, hid_u2f_txrx_ep_callback);
  237. usbd_ep_write(dev, HID_U2F_PACKET_LEN, 0, 0);
  238. return usbd_ack;
  239. default:
  240. return usbd_fail;
  241. }
  242. }
  243. /* Control requests handler */
  244. static usbd_respond hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  245. /* HID control requests */
  246. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  247. (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
  248. req->wIndex == 0) {
  249. switch(req->bRequest) {
  250. case USB_HID_SETIDLE:
  251. return usbd_ack;
  252. case USB_HID_GETREPORT:
  253. // dev->status.data_ptr = &hid_u2f_report;
  254. // dev->status.data_count = sizeof(hid_u2f_report);
  255. return usbd_ack;
  256. default:
  257. return usbd_fail;
  258. }
  259. }
  260. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  261. (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
  262. req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  263. switch(req->wValue >> 8) {
  264. case USB_DTYPE_HID:
  265. dev->status.data_ptr = (uint8_t*)&(hid_u2f_cfg_desc.iad_0.hid_desc);
  266. dev->status.data_count = sizeof(hid_u2f_cfg_desc.iad_0.hid_desc);
  267. return usbd_ack;
  268. case USB_DTYPE_HID_REPORT:
  269. dev->status.data_ptr = (uint8_t*)hid_u2f_report_desc;
  270. dev->status.data_count = sizeof(hid_u2f_report_desc);
  271. return usbd_ack;
  272. default:
  273. return usbd_fail;
  274. }
  275. }
  276. return usbd_fail;
  277. }