furi_hal_usb_u2f.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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_RI_LOGICAL_MAXIMUM(16, 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_RI_LOGICAL_MAXIMUM(16, 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");
  46. /* Device descriptor */
  47. static const struct usb_device_descriptor hid_u2f_device_desc = {
  48. .bLength = sizeof(struct usb_device_descriptor),
  49. .bDescriptorType = USB_DTYPE_DEVICE,
  50. .bcdUSB = VERSION_BCD(2, 0, 0),
  51. .bDeviceClass = USB_CLASS_IAD,
  52. .bDeviceSubClass = USB_SUBCLASS_IAD,
  53. .bDeviceProtocol = USB_PROTO_IAD,
  54. .bMaxPacketSize0 = USB_EP0_SIZE,
  55. .idVendor = 0x0483,
  56. .idProduct = 0x5741,
  57. .bcdDevice = VERSION_BCD(1, 0, 0),
  58. .iManufacturer = UsbDevManuf,
  59. .iProduct = UsbDevProduct,
  60. .iSerialNumber = 0,
  61. .bNumConfigurations = 1,
  62. };
  63. /* Device configuration descriptor */
  64. static const struct HidConfigDescriptor hid_u2f_cfg_desc = {
  65. .config =
  66. {
  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. {
  78. .hid_iad =
  79. {
  80. .bLength = sizeof(struct usb_iad_descriptor),
  81. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  82. .bFirstInterface = 0,
  83. .bInterfaceCount = 1,
  84. .bFunctionClass = USB_CLASS_PER_INTERFACE,
  85. .bFunctionSubClass = USB_SUBCLASS_NONE,
  86. .bFunctionProtocol = USB_PROTO_NONE,
  87. .iFunction = NO_DESCRIPTOR,
  88. },
  89. .hid =
  90. {
  91. .bLength = sizeof(struct usb_interface_descriptor),
  92. .bDescriptorType = USB_DTYPE_INTERFACE,
  93. .bInterfaceNumber = 0,
  94. .bAlternateSetting = 0,
  95. .bNumEndpoints = 2,
  96. .bInterfaceClass = USB_CLASS_HID,
  97. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  98. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  99. .iInterface = NO_DESCRIPTOR,
  100. },
  101. .hid_desc =
  102. {
  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_u2f_report_desc),
  110. },
  111. .hid_ep_in =
  112. {
  113. .bLength = sizeof(struct usb_endpoint_descriptor),
  114. .bDescriptorType = USB_DTYPE_ENDPOINT,
  115. .bEndpointAddress = HID_EP_IN,
  116. .bmAttributes = USB_EPTYPE_INTERRUPT,
  117. .wMaxPacketSize = HID_U2F_PACKET_LEN,
  118. .bInterval = 5,
  119. },
  120. .hid_ep_out =
  121. {
  122. .bLength = sizeof(struct usb_endpoint_descriptor),
  123. .bDescriptorType = USB_DTYPE_ENDPOINT,
  124. .bEndpointAddress = HID_EP_OUT,
  125. .bmAttributes = USB_EPTYPE_INTERRUPT,
  126. .wMaxPacketSize = HID_U2F_PACKET_LEN,
  127. .bInterval = 5,
  128. },
  129. },
  130. };
  131. static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
  132. static void hid_u2f_deinit(usbd_device* dev);
  133. static void hid_u2f_on_wakeup(usbd_device* dev);
  134. static void hid_u2f_on_suspend(usbd_device* dev);
  135. //static bool hid_u2f_send_report(uint8_t report_id);
  136. static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg);
  137. static usbd_respond
  138. hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  139. static usbd_device* usb_dev;
  140. static FuriSemaphore* hid_u2f_semaphore = NULL;
  141. static bool hid_u2f_connected = false;
  142. static HidU2fCallback callback;
  143. static void* cb_ctx;
  144. bool furi_hal_hid_u2f_is_connected() {
  145. return hid_u2f_connected;
  146. }
  147. void furi_hal_hid_u2f_set_callback(HidU2fCallback cb, void* ctx) {
  148. if(callback != NULL) {
  149. if(hid_u2f_connected == true) {
  150. callback(HidU2fDisconnected, cb_ctx);
  151. }
  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. }
  161. FuriHalUsbInterface usb_hid_u2f = {
  162. .init = hid_u2f_init,
  163. .deinit = hid_u2f_deinit,
  164. .wakeup = hid_u2f_on_wakeup,
  165. .suspend = hid_u2f_on_suspend,
  166. .dev_descr = (struct usb_device_descriptor*)&hid_u2f_device_desc,
  167. .str_manuf_descr = (void*)&dev_manuf_desc,
  168. .str_prod_descr = (void*)&dev_prod_desc,
  169. .str_serial_descr = NULL,
  170. .cfg_descr = (void*)&hid_u2f_cfg_desc,
  171. };
  172. static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
  173. UNUSED(intf);
  174. UNUSED(ctx);
  175. if(hid_u2f_semaphore == NULL) {
  176. hid_u2f_semaphore = furi_semaphore_alloc(1, 1);
  177. }
  178. usb_dev = dev;
  179. usbd_reg_config(dev, hid_u2f_ep_config);
  180. usbd_reg_control(dev, hid_u2f_control);
  181. usbd_connect(dev, true);
  182. }
  183. static void hid_u2f_deinit(usbd_device* dev) {
  184. usbd_reg_config(dev, NULL);
  185. usbd_reg_control(dev, NULL);
  186. }
  187. static void hid_u2f_on_wakeup(usbd_device* dev) {
  188. UNUSED(dev);
  189. hid_u2f_connected = true;
  190. if(callback != NULL) {
  191. callback(HidU2fConnected, cb_ctx);
  192. }
  193. }
  194. static void hid_u2f_on_suspend(usbd_device* dev) {
  195. UNUSED(dev);
  196. if(hid_u2f_connected) {
  197. hid_u2f_connected = false;
  198. furi_semaphore_release(hid_u2f_semaphore);
  199. if(callback != NULL) {
  200. callback(HidU2fDisconnected, cb_ctx);
  201. }
  202. }
  203. }
  204. void furi_hal_hid_u2f_send_response(uint8_t* data, uint8_t len) {
  205. if((hid_u2f_semaphore == NULL) || (hid_u2f_connected == false)) return;
  206. furi_check(furi_semaphore_acquire(hid_u2f_semaphore, FuriWaitForever) == FuriStatusOk);
  207. if(hid_u2f_connected == true) {
  208. usbd_ep_write(usb_dev, HID_EP_OUT, data, len);
  209. }
  210. }
  211. uint32_t furi_hal_hid_u2f_get_request(uint8_t* data) {
  212. int32_t len = usbd_ep_read(usb_dev, HID_EP_IN, data, HID_U2F_PACKET_LEN);
  213. return ((len < 0) ? 0 : len);
  214. }
  215. static void hid_u2f_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  216. UNUSED(dev);
  217. UNUSED(event);
  218. UNUSED(ep);
  219. if(callback != NULL) {
  220. callback(HidU2fRequest, cb_ctx);
  221. }
  222. }
  223. static void hid_u2f_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  224. UNUSED(dev);
  225. UNUSED(event);
  226. UNUSED(ep);
  227. furi_semaphore_release(hid_u2f_semaphore);
  228. }
  229. static void hid_u2f_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  230. if(event == usbd_evt_eptx) {
  231. hid_u2f_tx_ep_callback(dev, event, ep);
  232. } else {
  233. hid_u2f_rx_ep_callback(dev, event, ep);
  234. }
  235. }
  236. /* Configure endpoints */
  237. static usbd_respond hid_u2f_ep_config(usbd_device* dev, uint8_t cfg) {
  238. switch(cfg) {
  239. case 0:
  240. /* deconfiguring device */
  241. usbd_ep_deconfig(dev, HID_EP_OUT);
  242. usbd_ep_deconfig(dev, HID_EP_IN);
  243. usbd_reg_endpoint(dev, HID_EP_OUT, 0);
  244. usbd_reg_endpoint(dev, HID_EP_IN, 0);
  245. return usbd_ack;
  246. case 1:
  247. /* configuring device */
  248. usbd_ep_config(dev, HID_EP_IN, USB_EPTYPE_INTERRUPT, HID_U2F_PACKET_LEN);
  249. usbd_ep_config(dev, HID_EP_OUT, USB_EPTYPE_INTERRUPT, HID_U2F_PACKET_LEN);
  250. usbd_reg_endpoint(dev, HID_EP_IN, hid_u2f_txrx_ep_callback);
  251. usbd_reg_endpoint(dev, HID_EP_OUT, hid_u2f_txrx_ep_callback);
  252. usbd_ep_write(dev, HID_U2F_PACKET_LEN, 0, 0);
  253. return usbd_ack;
  254. default:
  255. return usbd_fail;
  256. }
  257. }
  258. /* Control requests handler */
  259. static usbd_respond
  260. hid_u2f_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  261. UNUSED(callback);
  262. /* HID control requests */
  263. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  264. (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
  265. req->wIndex == 0) {
  266. switch(req->bRequest) {
  267. case USB_HID_SETIDLE:
  268. return usbd_ack;
  269. default:
  270. return usbd_fail;
  271. }
  272. }
  273. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  274. (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
  275. req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  276. switch(req->wValue >> 8) {
  277. case USB_DTYPE_HID:
  278. dev->status.data_ptr = (uint8_t*)&(hid_u2f_cfg_desc.iad_0.hid_desc);
  279. dev->status.data_count = sizeof(hid_u2f_cfg_desc.iad_0.hid_desc);
  280. return usbd_ack;
  281. case USB_DTYPE_HID_REPORT:
  282. dev->status.data_ptr = (uint8_t*)hid_u2f_report_desc;
  283. dev->status.data_count = sizeof(hid_u2f_report_desc);
  284. return usbd_ack;
  285. default:
  286. return usbd_fail;
  287. }
  288. }
  289. return usbd_fail;
  290. }