furi-hal-usb-u2f.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. .bLength = sizeof(struct usb_config_descriptor),
  68. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  69. .wTotalLength = sizeof(struct HidConfigDescriptor),
  70. .bNumInterfaces = 1,
  71. .bConfigurationValue = 1,
  72. .iConfiguration = NO_DESCRIPTOR,
  73. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  74. .bMaxPower = USB_CFG_POWER_MA(100),
  75. },
  76. .iad_0 = {
  77. .hid_iad =
  78. {
  79. .bLength = sizeof(struct usb_iad_descriptor),
  80. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  81. .bFirstInterface = 0,
  82. .bInterfaceCount = 1,
  83. .bFunctionClass = USB_CLASS_PER_INTERFACE,
  84. .bFunctionSubClass = USB_SUBCLASS_NONE,
  85. .bFunctionProtocol = USB_PROTO_NONE,
  86. .iFunction = NO_DESCRIPTOR,
  87. },
  88. .hid = {
  89. .bLength = sizeof(struct usb_interface_descriptor),
  90. .bDescriptorType = USB_DTYPE_INTERFACE,
  91. .bInterfaceNumber = 0,
  92. .bAlternateSetting = 0,
  93. .bNumEndpoints = 2,
  94. .bInterfaceClass = USB_CLASS_HID,
  95. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  96. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  97. .iInterface = NO_DESCRIPTOR,
  98. },
  99. .hid_desc = {
  100. .bLength = sizeof(struct usb_hid_descriptor),
  101. .bDescriptorType = USB_DTYPE_HID,
  102. .bcdHID = VERSION_BCD(1, 0, 0),
  103. .bCountryCode = USB_HID_COUNTRY_NONE,
  104. .bNumDescriptors = 1,
  105. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  106. .wDescriptorLength0 = sizeof(hid_u2f_report_desc),
  107. },
  108. .hid_ep_in = {
  109. .bLength = sizeof(struct usb_endpoint_descriptor),
  110. .bDescriptorType = USB_DTYPE_ENDPOINT,
  111. .bEndpointAddress = HID_EP_IN,
  112. .bmAttributes = USB_EPTYPE_INTERRUPT,
  113. .wMaxPacketSize = HID_U2F_PACKET_LEN,
  114. .bInterval = 5,
  115. },
  116. .hid_ep_out = {
  117. .bLength = sizeof(struct usb_endpoint_descriptor),
  118. .bDescriptorType = USB_DTYPE_ENDPOINT,
  119. .bEndpointAddress = HID_EP_OUT,
  120. .bmAttributes = USB_EPTYPE_INTERRUPT,
  121. .wMaxPacketSize = HID_U2F_PACKET_LEN,
  122. .bInterval = 5,
  123. },
  124. },
  125. };
  126. static void hid_u2f_init(usbd_device* dev, UsbInterface* intf);
  127. static void hid_u2f_deinit(usbd_device* dev);
  128. static void hid_u2f_on_wakeup(usbd_device* dev);
  129. static void hid_u2f_on_suspend(usbd_device* dev);
  130. //static bool hid_u2f_send_report(uint8_t report_id);
  131. static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg);
  132. static usbd_respond
  133. hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  134. static usbd_device* usb_dev;
  135. static osSemaphoreId_t hid_u2f_semaphore = NULL;
  136. static bool hid_u2f_connected = false;
  137. static HidU2fCallback callback;
  138. static void* cb_ctx;
  139. bool furi_hal_hid_u2f_is_connected() {
  140. return hid_u2f_connected;
  141. }
  142. void furi_hal_hid_u2f_set_callback(HidU2fCallback cb, void* ctx) {
  143. if (callback != NULL) {
  144. if (hid_u2f_connected == true)
  145. callback(HidU2fDisconnected, cb_ctx);
  146. }
  147. callback = cb;
  148. cb_ctx = ctx;
  149. if (callback != NULL) {
  150. if (hid_u2f_connected == true)
  151. callback(HidU2fConnected, cb_ctx);
  152. }
  153. }
  154. UsbInterface usb_hid_u2f = {
  155. .init = hid_u2f_init,
  156. .deinit = hid_u2f_deinit,
  157. .wakeup = hid_u2f_on_wakeup,
  158. .suspend = hid_u2f_on_suspend,
  159. .dev_descr = (struct usb_device_descriptor*)&hid_u2f_device_desc,
  160. .str_manuf_descr = (void*)&dev_manuf_desc,
  161. .str_prod_descr = (void*)&dev_prod_desc,
  162. .str_serial_descr = (void*)&dev_serial_desc,
  163. .cfg_descr = (void*)&hid_u2f_cfg_desc,
  164. };
  165. static void hid_u2f_init(usbd_device* dev, UsbInterface* intf) {
  166. if(hid_u2f_semaphore == NULL) hid_u2f_semaphore = osSemaphoreNew(1, 1, NULL);
  167. usb_dev = dev;
  168. usbd_reg_config(dev, hid_u2f_ep_config);
  169. usbd_reg_control(dev, hid_u2f_control);
  170. usbd_connect(dev, true);
  171. }
  172. static void hid_u2f_deinit(usbd_device* dev) {
  173. usbd_reg_config(dev, NULL);
  174. usbd_reg_control(dev, NULL);
  175. }
  176. static void hid_u2f_on_wakeup(usbd_device* dev) {
  177. hid_u2f_connected = true;
  178. if (callback != NULL)
  179. callback(HidU2fConnected, cb_ctx);
  180. }
  181. static void hid_u2f_on_suspend(usbd_device* dev) {
  182. if(hid_u2f_connected == true) {
  183. hid_u2f_connected = false;
  184. osSemaphoreRelease(hid_u2f_semaphore);
  185. if (callback != NULL)
  186. callback(HidU2fDisconnected, cb_ctx);
  187. }
  188. }
  189. void furi_hal_hid_u2f_send_response(uint8_t* data, uint8_t len) {
  190. if ((hid_u2f_semaphore == NULL) || (hid_u2f_connected == false))
  191. return;
  192. furi_check(osSemaphoreAcquire(hid_u2f_semaphore, osWaitForever) == osOK);
  193. if (hid_u2f_connected == true) {
  194. usbd_ep_write(usb_dev, HID_EP_OUT, data, len);
  195. }
  196. }
  197. uint32_t furi_hal_hid_u2f_get_request(uint8_t* data) {
  198. int32_t len = usbd_ep_read(usb_dev, HID_EP_IN, data, HID_U2F_PACKET_LEN);
  199. return ((len < 0) ? 0 : len);
  200. }
  201. static void hid_u2f_rx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  202. if (callback != NULL)
  203. callback(HidU2fRequest, cb_ctx);
  204. }
  205. static void hid_u2f_tx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  206. osSemaphoreRelease(hid_u2f_semaphore);
  207. }
  208. static void hid_u2f_txrx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  209. if (event == usbd_evt_eptx) {
  210. hid_u2f_tx_ep_callback(dev, event, ep);
  211. } else {
  212. hid_u2f_rx_ep_callback(dev, event, ep);
  213. }
  214. }
  215. /* Configure endpoints */
  216. static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg) {
  217. switch(cfg) {
  218. case 0:
  219. /* deconfiguring device */
  220. usbd_ep_deconfig(dev, HID_EP_OUT);
  221. usbd_ep_deconfig(dev, HID_EP_IN);
  222. usbd_reg_endpoint(dev, HID_EP_OUT, 0);
  223. usbd_reg_endpoint(dev, HID_EP_IN, 0);
  224. return usbd_ack;
  225. case 1:
  226. /* configuring device */
  227. usbd_ep_config(dev, HID_EP_IN, USB_EPTYPE_INTERRUPT, HID_U2F_PACKET_LEN);
  228. usbd_ep_config(dev, HID_EP_OUT, USB_EPTYPE_INTERRUPT, HID_U2F_PACKET_LEN);
  229. usbd_reg_endpoint(dev, HID_EP_IN, hid_u2f_txrx_ep_callback);
  230. usbd_reg_endpoint(dev, HID_EP_OUT, hid_u2f_txrx_ep_callback);
  231. usbd_ep_write(dev, HID_U2F_PACKET_LEN, 0, 0);
  232. return usbd_ack;
  233. default:
  234. return usbd_fail;
  235. }
  236. }
  237. /* Control requests handler */
  238. static usbd_respond hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  239. /* HID control requests */
  240. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  241. (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
  242. req->wIndex == 0) {
  243. switch(req->bRequest) {
  244. case USB_HID_SETIDLE:
  245. return usbd_ack;
  246. default:
  247. return usbd_fail;
  248. }
  249. }
  250. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  251. (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
  252. req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  253. switch(req->wValue >> 8) {
  254. case USB_DTYPE_HID:
  255. dev->status.data_ptr = (uint8_t*)&(hid_u2f_cfg_desc.iad_0.hid_desc);
  256. dev->status.data_count = sizeof(hid_u2f_cfg_desc.iad_0.hid_desc);
  257. return usbd_ack;
  258. case USB_DTYPE_HID_REPORT:
  259. dev->status.data_ptr = (uint8_t*)hid_u2f_report_desc;
  260. dev->status.data_count = sizeof(hid_u2f_report_desc);
  261. return usbd_ack;
  262. default:
  263. return usbd_fail;
  264. }
  265. }
  266. return usbd_fail;
  267. }