dap_v2_usb.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. #include <furi.h>
  2. #include <usb.h>
  3. #include <usb_std.h>
  4. #include <usb_hid.h>
  5. #include <usb_cdc.h>
  6. #include <furi_hal_console.h>
  7. #include "dap_v2_usb.h"
  8. // #define DAP_USB_LOG
  9. #define HID_EP_IN 0x80
  10. #define HID_EP_OUT 0x00
  11. #define DAP_HID_EP_SEND 1
  12. #define DAP_HID_EP_RECV 2
  13. #define DAP_HID_EP_BULK_RECV 3
  14. #define DAP_HID_EP_BULK_SEND 4
  15. #define DAP_CDC_EP_COMM 5
  16. #define DAP_CDC_EP_SEND 6
  17. #define DAP_CDC_EP_RECV 7
  18. #define DAP_HID_EP_IN (HID_EP_IN | DAP_HID_EP_SEND)
  19. #define DAP_HID_EP_OUT (HID_EP_OUT | DAP_HID_EP_RECV)
  20. #define DAP_HID_EP_BULK_IN (HID_EP_IN | DAP_HID_EP_BULK_SEND)
  21. #define DAP_HID_EP_BULK_OUT (HID_EP_OUT | DAP_HID_EP_BULK_RECV)
  22. #define DAP_HID_EP_SIZE 64
  23. #define DAP_CDC_COMM_EP_SIZE 8
  24. #define DAP_CDC_EP_SIZE 64
  25. #define DAP_BULK_INTERVAL 0
  26. #define DAP_HID_INTERVAL 1
  27. #define DAP_CDC_INTERVAL 0
  28. #define DAP_CDC_COMM_INTERVAL 1
  29. #define DAP_HID_VID 0x0483
  30. #define DAP_HID_PID 0x5740
  31. #define DAP_USB_EP0_SIZE 8
  32. #define EP_CFG_DECONFIGURE 0
  33. #define EP_CFG_CONFIGURE 1
  34. enum {
  35. USB_INTF_HID,
  36. USB_INTF_BULK,
  37. USB_INTF_CDC_COMM,
  38. USB_INTF_CDC_DATA,
  39. USB_INTF_COUNT,
  40. };
  41. enum {
  42. USB_STR_ZERO,
  43. USB_STR_MANUFACTURER,
  44. USB_STR_PRODUCT,
  45. USB_STR_SERIAL_NUMBER,
  46. USB_STR_CMSIS_DAP_V1,
  47. USB_STR_CMSIS_DAP_V2,
  48. USB_STR_COM_PORT,
  49. USB_STR_COUNT,
  50. };
  51. // static const char* usb_str[] = {
  52. // [USB_STR_MANUFACTURER] = "Flipper Devices Inc.",
  53. // [USB_STR_PRODUCT] = "Combined VCP and CMSIS-DAP Adapter",
  54. // [USB_STR_COM_PORT] = "Virtual COM-Port",
  55. // [USB_STR_CMSIS_DAP_V1] = "CMSIS-DAP v1 Adapter",
  56. // [USB_STR_CMSIS_DAP_V2] = "CMSIS-DAP v2 Adapter",
  57. // [USB_STR_SERIAL_NUMBER] = "01234567890ABCDEF",
  58. // };
  59. static const struct usb_string_descriptor dev_manuf_descr =
  60. USB_STRING_DESC("Flipper Devices Inc.");
  61. static const struct usb_string_descriptor dev_prod_descr =
  62. USB_STRING_DESC("Combined VCP and CMSIS-DAP Adapter");
  63. static struct usb_string_descriptor* dev_serial_descr = NULL;
  64. static const struct usb_string_descriptor dev_dap_v1_descr =
  65. USB_STRING_DESC("CMSIS-DAP v1 Adapter");
  66. static const struct usb_string_descriptor dev_dap_v2_descr =
  67. USB_STRING_DESC("CMSIS-DAP v2 Adapter");
  68. static const struct usb_string_descriptor dev_com_descr = USB_STRING_DESC("Virtual COM-Port");
  69. struct HidConfigDescriptor {
  70. struct usb_config_descriptor configuration;
  71. // CMSIS-DAP v1
  72. struct usb_interface_descriptor hid_interface;
  73. struct usb_hid_descriptor hid;
  74. struct usb_endpoint_descriptor hid_ep_in;
  75. struct usb_endpoint_descriptor hid_ep_out;
  76. // CMSIS-DAP v2
  77. struct usb_interface_descriptor bulk_interface;
  78. struct usb_endpoint_descriptor bulk_ep_out;
  79. struct usb_endpoint_descriptor bulk_ep_in;
  80. // CDC
  81. struct usb_iad_descriptor iad;
  82. struct usb_interface_descriptor interface_comm;
  83. struct usb_cdc_header_desc cdc_header;
  84. struct usb_cdc_call_mgmt_desc cdc_acm;
  85. struct usb_cdc_acm_desc cdc_call_mgmt;
  86. struct usb_cdc_union_desc cdc_union;
  87. struct usb_endpoint_descriptor ep_comm;
  88. struct usb_interface_descriptor interface_data;
  89. struct usb_endpoint_descriptor ep_in;
  90. struct usb_endpoint_descriptor ep_out;
  91. } __attribute__((packed));
  92. static const struct usb_device_descriptor hid_device_desc = {
  93. .bLength = sizeof(struct usb_device_descriptor),
  94. .bDescriptorType = USB_DTYPE_DEVICE,
  95. .bcdUSB = VERSION_BCD(2, 1, 0),
  96. .bDeviceClass = USB_CLASS_MISC,
  97. .bDeviceSubClass = USB_SUBCLASS_IAD,
  98. .bDeviceProtocol = USB_PROTO_IAD,
  99. .bMaxPacketSize0 = DAP_USB_EP0_SIZE,
  100. .idVendor = DAP_HID_VID,
  101. .idProduct = DAP_HID_PID,
  102. .bcdDevice = VERSION_BCD(1, 0, 0),
  103. .iManufacturer = USB_STR_MANUFACTURER,
  104. .iProduct = USB_STR_PRODUCT,
  105. .iSerialNumber = USB_STR_SERIAL_NUMBER,
  106. .bNumConfigurations = 1,
  107. };
  108. static const uint8_t hid_report_desc[] = {
  109. 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
  110. 0x09, 0x00, // Usage (Undefined)
  111. 0xa1, 0x01, // Collection (Application)
  112. 0x15, 0x00, // Logical Minimum (0)
  113. 0x26, 0xff, 0x00, // Logical Maximum (255)
  114. 0x75, 0x08, // Report Size (8)
  115. 0x95, 0x40, // Report Count (64)
  116. 0x09, 0x00, // Usage (Undefined)
  117. 0x81, 0x82, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
  118. 0x75, 0x08, // Report Size (8)
  119. 0x95, 0x40, // Report Count (64)
  120. 0x09, 0x00, // Usage (Undefined)
  121. 0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
  122. 0xc0, // End Collection
  123. };
  124. static const struct HidConfigDescriptor hid_cfg_desc = {
  125. .configuration =
  126. {
  127. .bLength = sizeof(struct usb_config_descriptor),
  128. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  129. .wTotalLength = sizeof(struct HidConfigDescriptor),
  130. .bNumInterfaces = USB_INTF_COUNT,
  131. .bConfigurationValue = 1,
  132. .iConfiguration = NO_DESCRIPTOR,
  133. .bmAttributes = USB_CFG_ATTR_RESERVED,
  134. .bMaxPower = USB_CFG_POWER_MA(500),
  135. },
  136. // CMSIS-DAP v1
  137. .hid_interface =
  138. {
  139. .bLength = sizeof(struct usb_interface_descriptor),
  140. .bDescriptorType = USB_DTYPE_INTERFACE,
  141. .bInterfaceNumber = USB_INTF_HID,
  142. .bAlternateSetting = 0,
  143. .bNumEndpoints = 2,
  144. .bInterfaceClass = USB_CLASS_HID,
  145. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  146. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  147. .iInterface = USB_STR_CMSIS_DAP_V1,
  148. },
  149. .hid =
  150. {
  151. .bLength = sizeof(struct usb_hid_descriptor),
  152. .bDescriptorType = USB_DTYPE_HID,
  153. .bcdHID = VERSION_BCD(1, 1, 1),
  154. .bCountryCode = USB_HID_COUNTRY_NONE,
  155. .bNumDescriptors = 1,
  156. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  157. .wDescriptorLength0 = sizeof(hid_report_desc),
  158. },
  159. .hid_ep_in =
  160. {
  161. .bLength = sizeof(struct usb_endpoint_descriptor),
  162. .bDescriptorType = USB_DTYPE_ENDPOINT,
  163. .bEndpointAddress = DAP_HID_EP_IN,
  164. .bmAttributes = USB_EPTYPE_INTERRUPT,
  165. .wMaxPacketSize = DAP_HID_EP_SIZE,
  166. .bInterval = DAP_HID_INTERVAL,
  167. },
  168. .hid_ep_out =
  169. {
  170. .bLength = sizeof(struct usb_endpoint_descriptor),
  171. .bDescriptorType = USB_DTYPE_ENDPOINT,
  172. .bEndpointAddress = DAP_HID_EP_OUT,
  173. .bmAttributes = USB_EPTYPE_INTERRUPT,
  174. .wMaxPacketSize = DAP_HID_EP_SIZE,
  175. .bInterval = DAP_HID_INTERVAL,
  176. },
  177. // CMSIS-DAP v2
  178. .bulk_interface =
  179. {
  180. .bLength = sizeof(struct usb_interface_descriptor),
  181. .bDescriptorType = USB_DTYPE_INTERFACE,
  182. .bInterfaceNumber = USB_INTF_BULK,
  183. .bAlternateSetting = 0,
  184. .bNumEndpoints = 2,
  185. .bInterfaceClass = USB_CLASS_VENDOR,
  186. .bInterfaceSubClass = 0,
  187. .bInterfaceProtocol = 0,
  188. .iInterface = USB_STR_CMSIS_DAP_V2,
  189. },
  190. .bulk_ep_out =
  191. {
  192. .bLength = sizeof(struct usb_endpoint_descriptor),
  193. .bDescriptorType = USB_DTYPE_ENDPOINT,
  194. .bEndpointAddress = DAP_HID_EP_BULK_OUT,
  195. .bmAttributes = USB_EPTYPE_BULK,
  196. .wMaxPacketSize = DAP_HID_EP_SIZE,
  197. .bInterval = DAP_BULK_INTERVAL,
  198. },
  199. .bulk_ep_in =
  200. {
  201. .bLength = sizeof(struct usb_endpoint_descriptor),
  202. .bDescriptorType = USB_DTYPE_ENDPOINT,
  203. .bEndpointAddress = DAP_HID_EP_BULK_IN,
  204. .bmAttributes = USB_EPTYPE_BULK,
  205. .wMaxPacketSize = DAP_HID_EP_SIZE,
  206. .bInterval = DAP_BULK_INTERVAL,
  207. },
  208. // CDC
  209. .iad =
  210. {
  211. .bLength = sizeof(struct usb_iad_descriptor),
  212. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  213. .bFirstInterface = USB_INTF_CDC_COMM,
  214. .bInterfaceCount = 2,
  215. .bFunctionClass = USB_CLASS_CDC,
  216. .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
  217. .bFunctionProtocol = USB_PROTO_NONE,
  218. .iFunction = USB_STR_COM_PORT,
  219. },
  220. .interface_comm =
  221. {
  222. .bLength = sizeof(struct usb_interface_descriptor),
  223. .bDescriptorType = USB_DTYPE_INTERFACE,
  224. .bInterfaceNumber = USB_INTF_CDC_COMM,
  225. .bAlternateSetting = 0,
  226. .bNumEndpoints = 1,
  227. .bInterfaceClass = USB_CLASS_CDC,
  228. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  229. .bInterfaceProtocol = USB_PROTO_NONE,
  230. .iInterface = 0,
  231. },
  232. .cdc_header =
  233. {
  234. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  235. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  236. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  237. .bcdCDC = VERSION_BCD(1, 1, 0),
  238. },
  239. .cdc_acm =
  240. {
  241. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  242. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  243. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  244. // .bmCapabilities = USB_CDC_CAP_LINE | USB_CDC_CAP_BRK,
  245. .bmCapabilities = 0,
  246. },
  247. .cdc_call_mgmt =
  248. {
  249. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  250. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  251. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  252. .bmCapabilities = USB_CDC_CALL_MGMT_CAP_DATA_INTF,
  253. // .bDataInterface = USB_INTF_CDC_DATA,
  254. },
  255. .cdc_union =
  256. {
  257. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  258. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  259. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  260. .bMasterInterface0 = USB_INTF_CDC_COMM,
  261. .bSlaveInterface0 = USB_INTF_CDC_DATA,
  262. },
  263. .ep_comm =
  264. {
  265. .bLength = sizeof(struct usb_endpoint_descriptor),
  266. .bDescriptorType = USB_DTYPE_ENDPOINT,
  267. .bEndpointAddress = HID_EP_IN | DAP_CDC_EP_COMM,
  268. .bmAttributes = USB_EPTYPE_INTERRUPT,
  269. .wMaxPacketSize = DAP_CDC_COMM_EP_SIZE,
  270. .bInterval = DAP_CDC_COMM_INTERVAL,
  271. },
  272. .interface_data =
  273. {
  274. .bLength = sizeof(struct usb_interface_descriptor),
  275. .bDescriptorType = USB_DTYPE_INTERFACE,
  276. .bInterfaceNumber = USB_INTF_CDC_DATA,
  277. .bAlternateSetting = 0,
  278. .bNumEndpoints = 2,
  279. .bInterfaceClass = USB_CLASS_CDC_DATA,
  280. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  281. .bInterfaceProtocol = USB_PROTO_NONE,
  282. .iInterface = NO_DESCRIPTOR,
  283. },
  284. .ep_in =
  285. {
  286. .bLength = sizeof(struct usb_endpoint_descriptor),
  287. .bDescriptorType = USB_DTYPE_ENDPOINT,
  288. .bEndpointAddress = HID_EP_IN | DAP_CDC_EP_SEND,
  289. .bmAttributes = USB_EPTYPE_BULK,
  290. .wMaxPacketSize = DAP_CDC_EP_SIZE,
  291. .bInterval = DAP_CDC_INTERVAL,
  292. },
  293. .ep_out =
  294. {
  295. .bLength = sizeof(struct usb_endpoint_descriptor),
  296. .bDescriptorType = USB_DTYPE_ENDPOINT,
  297. .bEndpointAddress = HID_EP_OUT | DAP_CDC_EP_RECV,
  298. .bmAttributes = USB_EPTYPE_BULK,
  299. .wMaxPacketSize = DAP_CDC_EP_SIZE,
  300. .bInterval = DAP_CDC_INTERVAL,
  301. },
  302. };
  303. // WinUSB
  304. #include "usb_winusb.h"
  305. typedef struct USB_PACK {
  306. usb_binary_object_store_descriptor_t bos;
  307. usb_winusb_capability_descriptor_t winusb;
  308. } usb_bos_hierarchy_t;
  309. typedef struct USB_PACK {
  310. usb_winusb_subset_header_function_t header;
  311. usb_winusb_feature_compatble_id_t comp_id;
  312. usb_winusb_feature_reg_property_guids_t property;
  313. } usb_msos_descriptor_subset_t;
  314. typedef struct USB_PACK {
  315. usb_winusb_set_header_descriptor_t header;
  316. usb_msos_descriptor_subset_t subset;
  317. } usb_msos_descriptor_set_t;
  318. #define USB_DTYPE_BINARY_OBJECT_STORE 15
  319. #define USB_DTYPE_DEVICE_CAPABILITY_DESCRIPTOR 16
  320. #define USB_DC_TYPE_PLATFORM 5
  321. const usb_bos_hierarchy_t usb_bos_hierarchy = {
  322. .bos =
  323. {
  324. .bLength = sizeof(usb_binary_object_store_descriptor_t),
  325. .bDescriptorType = USB_DTYPE_BINARY_OBJECT_STORE,
  326. .wTotalLength = sizeof(usb_bos_hierarchy_t),
  327. .bNumDeviceCaps = 1,
  328. },
  329. .winusb =
  330. {
  331. .bLength = sizeof(usb_winusb_capability_descriptor_t),
  332. .bDescriptorType = USB_DTYPE_DEVICE_CAPABILITY_DESCRIPTOR,
  333. .bDevCapabilityType = USB_DC_TYPE_PLATFORM,
  334. .bReserved = 0,
  335. .PlatformCapabilityUUID = USB_WINUSB_PLATFORM_CAPABILITY_ID,
  336. .dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION,
  337. .wMSOSDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t),
  338. .bMS_VendorCode = USB_WINUSB_VENDOR_CODE,
  339. .bAltEnumCode = 0,
  340. },
  341. };
  342. const usb_msos_descriptor_set_t usb_msos_descriptor_set = {
  343. .header =
  344. {
  345. .wLength = sizeof(usb_winusb_set_header_descriptor_t),
  346. .wDescriptorType = USB_WINUSB_SET_HEADER_DESCRIPTOR,
  347. .dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION,
  348. .wDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t),
  349. },
  350. .subset =
  351. {
  352. .header =
  353. {
  354. .wLength = sizeof(usb_winusb_subset_header_function_t),
  355. .wDescriptorType = USB_WINUSB_SUBSET_HEADER_FUNCTION,
  356. .bFirstInterface = USB_INTF_BULK,
  357. .bReserved = 0,
  358. .wSubsetLength = sizeof(usb_msos_descriptor_subset_t),
  359. },
  360. .comp_id =
  361. {
  362. .wLength = sizeof(usb_winusb_feature_compatble_id_t),
  363. .wDescriptorType = USB_WINUSB_FEATURE_COMPATBLE_ID,
  364. .CompatibleID = "WINUSB\0\0",
  365. .SubCompatibleID = {0},
  366. },
  367. .property =
  368. {
  369. .wLength = sizeof(usb_winusb_feature_reg_property_guids_t),
  370. .wDescriptorType = USB_WINUSB_FEATURE_REG_PROPERTY,
  371. .wPropertyDataType = USB_WINUSB_PROPERTY_DATA_TYPE_MULTI_SZ,
  372. .wPropertyNameLength =
  373. sizeof(usb_msos_descriptor_set.subset.property.PropertyName),
  374. .PropertyName = {'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, 'I', 0,
  375. 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0,
  376. 'e', 0, 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0},
  377. .wPropertyDataLength =
  378. sizeof(usb_msos_descriptor_set.subset.property.PropertyData),
  379. .PropertyData = {'{', 0, 'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0,
  380. 'A', 0, 'D', 0, '-', 0, '2', 0, '9', 0, '3', 0, 'B', 0,
  381. '-', 0, '4', 0, '6', 0, '6', 0, '3', 0, '-', 0, 'A', 0,
  382. 'A', 0, '3', 0, '6', 0, '-', 0, '1', 0, 'A', 0, 'A', 0,
  383. 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0,
  384. '7', 0, '6', 0, '}', 0, 0, 0, 0, 0},
  385. },
  386. },
  387. };
  388. typedef struct {
  389. FuriSemaphore* semaphore_v1;
  390. FuriSemaphore* semaphore_v2;
  391. FuriSemaphore* semaphore_cdc;
  392. bool connected;
  393. usbd_device* usb_dev;
  394. DapStateCallback state_callback;
  395. DapRxCallback rx_callback_v1;
  396. DapRxCallback rx_callback_v2;
  397. DapRxCallback rx_callback_cdc;
  398. DapCDCControlLineCallback control_line_callback_cdc;
  399. DapCDCConfigCallback config_callback_cdc;
  400. void* context;
  401. void* context_cdc;
  402. } DAPState;
  403. static DAPState dap_state = {
  404. .semaphore_v1 = NULL,
  405. .semaphore_v2 = NULL,
  406. .semaphore_cdc = NULL,
  407. .connected = false,
  408. .usb_dev = NULL,
  409. .state_callback = NULL,
  410. .rx_callback_v1 = NULL,
  411. .rx_callback_v2 = NULL,
  412. .rx_callback_cdc = NULL,
  413. .control_line_callback_cdc = NULL,
  414. .config_callback_cdc = NULL,
  415. .context = NULL,
  416. .context_cdc = NULL,
  417. };
  418. static struct usb_cdc_line_coding cdc_config = {0};
  419. static uint8_t cdc_ctrl_line_state = 0;
  420. #ifdef DAP_USB_LOG
  421. void furi_console_log_printf(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
  422. void furi_console_log_printf(const char* format, ...) {
  423. char buffer[256];
  424. va_list args;
  425. va_start(args, format);
  426. vsnprintf(buffer, sizeof(buffer), format, args);
  427. va_end(args);
  428. furi_hal_console_puts(buffer);
  429. furi_hal_console_puts("\r\n");
  430. UNUSED(format);
  431. }
  432. #else
  433. #define furi_console_log_printf(...)
  434. #endif
  435. int32_t dap_v1_usb_tx(uint8_t* buffer, uint8_t size) {
  436. if((dap_state.semaphore_v1 == NULL) || (dap_state.connected == false)) return 0;
  437. furi_check(furi_semaphore_acquire(dap_state.semaphore_v1, FuriWaitForever) == FuriStatusOk);
  438. if(dap_state.connected) {
  439. int32_t len = usbd_ep_write(dap_state.usb_dev, DAP_HID_EP_IN, buffer, size);
  440. furi_console_log_printf("v1 tx %ld", len);
  441. return len;
  442. } else {
  443. return 0;
  444. }
  445. }
  446. int32_t dap_v2_usb_tx(uint8_t* buffer, uint8_t size) {
  447. if((dap_state.semaphore_v2 == NULL) || (dap_state.connected == false)) return 0;
  448. furi_check(furi_semaphore_acquire(dap_state.semaphore_v2, FuriWaitForever) == FuriStatusOk);
  449. if(dap_state.connected) {
  450. int32_t len = usbd_ep_write(dap_state.usb_dev, DAP_HID_EP_BULK_IN, buffer, size);
  451. furi_console_log_printf("v2 tx %ld", len);
  452. return len;
  453. } else {
  454. return 0;
  455. }
  456. }
  457. int32_t dap_cdc_usb_tx(uint8_t* buffer, uint8_t size) {
  458. if((dap_state.semaphore_cdc == NULL) || (dap_state.connected == false)) return 0;
  459. furi_check(furi_semaphore_acquire(dap_state.semaphore_cdc, FuriWaitForever) == FuriStatusOk);
  460. if(dap_state.connected) {
  461. int32_t len = usbd_ep_write(dap_state.usb_dev, HID_EP_IN | DAP_CDC_EP_SEND, buffer, size);
  462. furi_console_log_printf("cdc tx %ld", len);
  463. return len;
  464. } else {
  465. return 0;
  466. }
  467. }
  468. void dap_v1_usb_set_rx_callback(DapRxCallback callback) {
  469. dap_state.rx_callback_v1 = callback;
  470. }
  471. void dap_v2_usb_set_rx_callback(DapRxCallback callback) {
  472. dap_state.rx_callback_v2 = callback;
  473. }
  474. void dap_cdc_usb_set_rx_callback(DapRxCallback callback) {
  475. dap_state.rx_callback_cdc = callback;
  476. }
  477. void dap_cdc_usb_set_control_line_callback(DapCDCControlLineCallback callback) {
  478. dap_state.control_line_callback_cdc = callback;
  479. }
  480. void dap_cdc_usb_set_config_callback(DapCDCConfigCallback callback) {
  481. dap_state.config_callback_cdc = callback;
  482. }
  483. void dap_cdc_usb_set_context(void* context) {
  484. dap_state.context_cdc = context;
  485. }
  486. void dap_common_usb_set_context(void* context) {
  487. dap_state.context = context;
  488. }
  489. void dap_common_usb_set_state_callback(DapStateCallback callback) {
  490. dap_state.state_callback = callback;
  491. }
  492. static void* dap_usb_alloc_string_descr(const char* str) {
  493. furi_assert(str);
  494. uint8_t len = strlen(str);
  495. uint8_t wlen = (len + 1) * sizeof(uint16_t);
  496. struct usb_string_descriptor* dev_str_desc = malloc(wlen);
  497. dev_str_desc->bLength = wlen;
  498. dev_str_desc->bDescriptorType = USB_DTYPE_STRING;
  499. for(uint8_t i = 0; i < len; i++) {
  500. dev_str_desc->wString[i] = str[i];
  501. }
  502. return dev_str_desc;
  503. }
  504. void dap_common_usb_alloc_name(const char* name) {
  505. dev_serial_descr = dap_usb_alloc_string_descr(name);
  506. }
  507. void dap_common_usb_free_name() {
  508. free(dev_serial_descr);
  509. }
  510. static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
  511. static void hid_deinit(usbd_device* dev);
  512. static void hid_on_wakeup(usbd_device* dev);
  513. static void hid_on_suspend(usbd_device* dev);
  514. static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg);
  515. static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  516. FuriHalUsbInterface dap_v2_usb_hid = {
  517. .init = hid_init,
  518. .deinit = hid_deinit,
  519. .wakeup = hid_on_wakeup,
  520. .suspend = hid_on_suspend,
  521. .dev_descr = (struct usb_device_descriptor*)&hid_device_desc,
  522. .cfg_descr = (void*)&hid_cfg_desc,
  523. };
  524. static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
  525. UNUSED(intf);
  526. UNUSED(ctx);
  527. dap_v2_usb_hid.str_manuf_descr = (void*)&dev_manuf_descr;
  528. dap_v2_usb_hid.str_prod_descr = (void*)&dev_prod_descr;
  529. dap_v2_usb_hid.str_serial_descr = (void*)dev_serial_descr;
  530. dap_state.usb_dev = dev;
  531. if(dap_state.semaphore_v1 == NULL) dap_state.semaphore_v1 = furi_semaphore_alloc(1, 1);
  532. if(dap_state.semaphore_v2 == NULL) dap_state.semaphore_v2 = furi_semaphore_alloc(1, 1);
  533. if(dap_state.semaphore_cdc == NULL) dap_state.semaphore_cdc = furi_semaphore_alloc(1, 1);
  534. usb_hid.dev_descr->idVendor = DAP_HID_VID;
  535. usb_hid.dev_descr->idProduct = DAP_HID_PID;
  536. usbd_reg_config(dev, hid_ep_config);
  537. usbd_reg_control(dev, hid_control);
  538. usbd_connect(dev, true);
  539. }
  540. static bool deinit_flag = false;
  541. void dap_common_wait_for_deinit() {
  542. while(!deinit_flag) {
  543. furi_delay_ms(50);
  544. }
  545. }
  546. static void hid_deinit(usbd_device* dev) {
  547. dap_state.usb_dev = NULL;
  548. furi_semaphore_free(dap_state.semaphore_v1);
  549. furi_semaphore_free(dap_state.semaphore_v2);
  550. furi_semaphore_free(dap_state.semaphore_cdc);
  551. dap_state.semaphore_v1 = NULL;
  552. dap_state.semaphore_v2 = NULL;
  553. dap_state.semaphore_cdc = NULL;
  554. usbd_reg_config(dev, NULL);
  555. usbd_reg_control(dev, NULL);
  556. free(usb_hid.str_manuf_descr);
  557. free(usb_hid.str_prod_descr);
  558. FURI_SW_MEMBARRIER();
  559. deinit_flag = true;
  560. }
  561. static void hid_on_wakeup(usbd_device* dev) {
  562. UNUSED(dev);
  563. if(!dap_state.connected) {
  564. dap_state.connected = true;
  565. if(dap_state.state_callback != NULL) {
  566. dap_state.state_callback(dap_state.connected, dap_state.context);
  567. }
  568. }
  569. }
  570. static void hid_on_suspend(usbd_device* dev) {
  571. UNUSED(dev);
  572. if(dap_state.connected) {
  573. dap_state.connected = false;
  574. if(dap_state.state_callback != NULL) {
  575. dap_state.state_callback(dap_state.connected, dap_state.context);
  576. }
  577. }
  578. }
  579. size_t dap_v1_usb_rx(uint8_t* buffer, size_t size) {
  580. size_t len = 0;
  581. if(dap_state.connected) {
  582. len = usbd_ep_read(dap_state.usb_dev, DAP_HID_EP_OUT, buffer, size);
  583. }
  584. return len;
  585. }
  586. size_t dap_v2_usb_rx(uint8_t* buffer, size_t size) {
  587. size_t len = 0;
  588. if(dap_state.connected) {
  589. len = usbd_ep_read(dap_state.usb_dev, DAP_HID_EP_BULK_OUT, buffer, size);
  590. }
  591. return len;
  592. }
  593. size_t dap_cdc_usb_rx(uint8_t* buffer, size_t size) {
  594. size_t len = 0;
  595. if(dap_state.connected) {
  596. len = usbd_ep_read(dap_state.usb_dev, HID_EP_OUT | DAP_CDC_EP_RECV, buffer, size);
  597. }
  598. return len;
  599. }
  600. static void hid_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  601. UNUSED(dev);
  602. UNUSED(ep);
  603. switch(event) {
  604. case usbd_evt_eptx:
  605. furi_semaphore_release(dap_state.semaphore_v1);
  606. furi_console_log_printf("hid tx complete");
  607. break;
  608. case usbd_evt_eprx:
  609. if(dap_state.rx_callback_v1 != NULL) {
  610. dap_state.rx_callback_v1(dap_state.context);
  611. }
  612. break;
  613. default:
  614. furi_console_log_printf("hid %d, %d", event, ep);
  615. break;
  616. }
  617. }
  618. static void hid_txrx_ep_bulk_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  619. UNUSED(dev);
  620. UNUSED(ep);
  621. switch(event) {
  622. case usbd_evt_eptx:
  623. furi_semaphore_release(dap_state.semaphore_v2);
  624. furi_console_log_printf("bulk tx complete");
  625. break;
  626. case usbd_evt_eprx:
  627. if(dap_state.rx_callback_v2 != NULL) {
  628. dap_state.rx_callback_v2(dap_state.context);
  629. }
  630. break;
  631. default:
  632. furi_console_log_printf("bulk %d, %d", event, ep);
  633. break;
  634. }
  635. }
  636. static void cdc_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  637. UNUSED(dev);
  638. UNUSED(ep);
  639. switch(event) {
  640. case usbd_evt_eptx:
  641. furi_semaphore_release(dap_state.semaphore_cdc);
  642. furi_console_log_printf("cdc tx complete");
  643. break;
  644. case usbd_evt_eprx:
  645. if(dap_state.rx_callback_cdc != NULL) {
  646. dap_state.rx_callback_cdc(dap_state.context_cdc);
  647. }
  648. break;
  649. default:
  650. furi_console_log_printf("cdc %d, %d", event, ep);
  651. break;
  652. }
  653. }
  654. static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg) {
  655. switch(cfg) {
  656. case EP_CFG_DECONFIGURE:
  657. usbd_ep_deconfig(dev, DAP_HID_EP_OUT);
  658. usbd_ep_deconfig(dev, DAP_HID_EP_IN);
  659. usbd_ep_deconfig(dev, DAP_HID_EP_BULK_IN);
  660. usbd_ep_deconfig(dev, DAP_HID_EP_BULK_OUT);
  661. usbd_ep_deconfig(dev, HID_EP_IN | DAP_CDC_EP_COMM);
  662. usbd_ep_deconfig(dev, HID_EP_IN | DAP_CDC_EP_SEND);
  663. usbd_ep_deconfig(dev, HID_EP_OUT | DAP_CDC_EP_RECV);
  664. usbd_reg_endpoint(dev, DAP_HID_EP_OUT, NULL);
  665. usbd_reg_endpoint(dev, DAP_HID_EP_IN, NULL);
  666. usbd_reg_endpoint(dev, DAP_HID_EP_BULK_IN, NULL);
  667. usbd_reg_endpoint(dev, DAP_HID_EP_BULK_OUT, NULL);
  668. usbd_reg_endpoint(dev, HID_EP_IN | DAP_CDC_EP_SEND, 0);
  669. usbd_reg_endpoint(dev, HID_EP_OUT | DAP_CDC_EP_RECV, 0);
  670. return usbd_ack;
  671. case EP_CFG_CONFIGURE:
  672. usbd_ep_config(dev, DAP_HID_EP_IN, USB_EPTYPE_INTERRUPT, DAP_HID_EP_SIZE);
  673. usbd_ep_config(dev, DAP_HID_EP_OUT, USB_EPTYPE_INTERRUPT, DAP_HID_EP_SIZE);
  674. usbd_ep_config(dev, DAP_HID_EP_BULK_OUT, USB_EPTYPE_BULK, DAP_HID_EP_SIZE);
  675. usbd_ep_config(dev, DAP_HID_EP_BULK_IN, USB_EPTYPE_BULK, DAP_HID_EP_SIZE);
  676. usbd_ep_config(dev, HID_EP_OUT | DAP_CDC_EP_RECV, USB_EPTYPE_BULK, DAP_CDC_EP_SIZE);
  677. usbd_ep_config(dev, HID_EP_IN | DAP_CDC_EP_SEND, USB_EPTYPE_BULK, DAP_CDC_EP_SIZE);
  678. usbd_ep_config(dev, HID_EP_IN | DAP_CDC_EP_COMM, USB_EPTYPE_INTERRUPT, DAP_CDC_EP_SIZE);
  679. usbd_reg_endpoint(dev, DAP_HID_EP_IN, hid_txrx_ep_callback);
  680. usbd_reg_endpoint(dev, DAP_HID_EP_OUT, hid_txrx_ep_callback);
  681. usbd_reg_endpoint(dev, DAP_HID_EP_BULK_OUT, hid_txrx_ep_bulk_callback);
  682. usbd_reg_endpoint(dev, DAP_HID_EP_BULK_IN, hid_txrx_ep_bulk_callback);
  683. usbd_reg_endpoint(dev, HID_EP_OUT | DAP_CDC_EP_RECV, cdc_txrx_ep_callback);
  684. usbd_reg_endpoint(dev, HID_EP_IN | DAP_CDC_EP_SEND, cdc_txrx_ep_callback);
  685. // usbd_ep_write(dev, DAP_HID_EP_IN, NULL, 0);
  686. // usbd_ep_write(dev, DAP_HID_EP_BULK_IN, NULL, 0);
  687. // usbd_ep_write(dev, HID_EP_IN | DAP_CDC_EP_SEND, NULL, 0);
  688. return usbd_ack;
  689. default:
  690. return usbd_fail;
  691. }
  692. }
  693. #ifdef DAP_USB_LOG
  694. static void dump_request_type(uint8_t type) {
  695. switch(type & USB_REQ_DIRECTION) {
  696. case USB_REQ_HOSTTODEV:
  697. furi_hal_console_puts("host to dev, ");
  698. break;
  699. case USB_REQ_DEVTOHOST:
  700. furi_hal_console_puts("dev to host, ");
  701. break;
  702. }
  703. switch(type & USB_REQ_TYPE) {
  704. case USB_REQ_STANDARD:
  705. furi_hal_console_puts("standard, ");
  706. break;
  707. case USB_REQ_CLASS:
  708. furi_hal_console_puts("class, ");
  709. break;
  710. case USB_REQ_VENDOR:
  711. furi_hal_console_puts("vendor, ");
  712. break;
  713. }
  714. switch(type & USB_REQ_RECIPIENT) {
  715. case USB_REQ_DEVICE:
  716. furi_hal_console_puts("device");
  717. break;
  718. case USB_REQ_INTERFACE:
  719. furi_hal_console_puts("interface");
  720. break;
  721. case USB_REQ_ENDPOINT:
  722. furi_hal_console_puts("endpoint");
  723. break;
  724. case USB_REQ_OTHER:
  725. furi_hal_console_puts("other");
  726. break;
  727. }
  728. furi_hal_console_puts("\r\n");
  729. }
  730. #else
  731. #define dump_request_type(...)
  732. #endif
  733. static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  734. UNUSED(callback);
  735. dump_request_type(req->bmRequestType);
  736. furi_console_log_printf(
  737. "control: RT %02x, R %02x, V %04x, I %04x, L %04x",
  738. req->bmRequestType,
  739. req->bRequest,
  740. req->wValue,
  741. req->wIndex,
  742. req->wLength);
  743. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE | USB_REQ_DIRECTION) & req->bmRequestType) ==
  744. (USB_REQ_STANDARD | USB_REQ_VENDOR | USB_REQ_DEVTOHOST)) {
  745. // vendor request, device to host
  746. furi_console_log_printf("vendor request");
  747. if(USB_WINUSB_VENDOR_CODE == req->bRequest) {
  748. // WINUSB request
  749. if(USB_WINUSB_DESCRIPTOR_INDEX == req->wIndex) {
  750. furi_console_log_printf("WINUSB descriptor");
  751. uint16_t length = req->wLength;
  752. if(length > sizeof(usb_msos_descriptor_set_t)) {
  753. length = sizeof(usb_msos_descriptor_set_t);
  754. }
  755. dev->status.data_ptr = (uint8_t*)&usb_msos_descriptor_set;
  756. dev->status.data_count = length;
  757. return usbd_ack;
  758. }
  759. }
  760. }
  761. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  762. (USB_REQ_STANDARD | USB_REQ_DEVICE)) {
  763. // device request
  764. if(req->bRequest == USB_STD_GET_DESCRIPTOR) {
  765. const uint8_t dtype = req->wValue >> 8;
  766. const uint8_t dnumber = req->wValue & 0xFF;
  767. // get string descriptor
  768. if(USB_DTYPE_STRING == dtype) {
  769. if(dnumber == USB_STR_CMSIS_DAP_V1) {
  770. furi_console_log_printf("str CMSIS-DAP v1");
  771. dev->status.data_ptr = (uint8_t*)&dev_dap_v1_descr;
  772. dev->status.data_count = dev_dap_v1_descr.bLength;
  773. return usbd_ack;
  774. } else if(dnumber == USB_STR_CMSIS_DAP_V2) {
  775. furi_console_log_printf("str CMSIS-DAP v2");
  776. dev->status.data_ptr = (uint8_t*)&dev_dap_v2_descr;
  777. dev->status.data_count = dev_dap_v2_descr.bLength;
  778. return usbd_ack;
  779. } else if(dnumber == USB_STR_COM_PORT) {
  780. furi_console_log_printf("str COM port");
  781. dev->status.data_ptr = (uint8_t*)&dev_com_descr;
  782. dev->status.data_count = dev_com_descr.bLength;
  783. return usbd_ack;
  784. }
  785. } else if(USB_DTYPE_BINARY_OBJECT_STORE == dtype) {
  786. furi_console_log_printf("BOS descriptor");
  787. uint16_t length = req->wLength;
  788. if(length > sizeof(usb_bos_hierarchy_t)) {
  789. length = sizeof(usb_bos_hierarchy_t);
  790. }
  791. dev->status.data_ptr = (uint8_t*)&usb_bos_hierarchy;
  792. dev->status.data_count = length;
  793. return usbd_ack;
  794. }
  795. }
  796. }
  797. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  798. (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
  799. req->wIndex == 0) {
  800. // class request
  801. switch(req->bRequest) {
  802. // get hid descriptor
  803. case USB_HID_GETREPORT:
  804. furi_console_log_printf("get report");
  805. return usbd_fail;
  806. // set hid idle
  807. case USB_HID_SETIDLE:
  808. furi_console_log_printf("set idle");
  809. return usbd_ack;
  810. default:
  811. break;
  812. }
  813. }
  814. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  815. (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
  816. req->wIndex == 2) {
  817. // class request
  818. switch(req->bRequest) {
  819. // control line state
  820. case USB_CDC_SET_CONTROL_LINE_STATE:
  821. furi_console_log_printf("set control line state");
  822. cdc_ctrl_line_state = req->wValue;
  823. if(dap_state.control_line_callback_cdc != NULL) {
  824. dap_state.control_line_callback_cdc(cdc_ctrl_line_state, dap_state.context_cdc);
  825. }
  826. return usbd_ack;
  827. // set cdc line coding
  828. case USB_CDC_SET_LINE_CODING:
  829. furi_console_log_printf("set line coding");
  830. memcpy(&cdc_config, req->data, sizeof(cdc_config));
  831. if(dap_state.config_callback_cdc != NULL) {
  832. dap_state.config_callback_cdc(&cdc_config, dap_state.context_cdc);
  833. }
  834. return usbd_ack;
  835. // get cdc line coding
  836. case USB_CDC_GET_LINE_CODING:
  837. furi_console_log_printf("get line coding");
  838. dev->status.data_ptr = &cdc_config;
  839. dev->status.data_count = sizeof(cdc_config);
  840. return usbd_ack;
  841. default:
  842. break;
  843. }
  844. }
  845. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  846. (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
  847. req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  848. // standard request
  849. switch(req->wValue >> 8) {
  850. // get hid descriptor
  851. case USB_DTYPE_HID:
  852. furi_console_log_printf("get hid descriptor");
  853. dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.hid);
  854. dev->status.data_count = sizeof(hid_cfg_desc.hid);
  855. return usbd_ack;
  856. // get hid report descriptor
  857. case USB_DTYPE_HID_REPORT:
  858. furi_console_log_printf("get hid report descriptor");
  859. dev->status.data_ptr = (uint8_t*)hid_report_desc;
  860. dev->status.data_count = sizeof(hid_report_desc);
  861. return usbd_ack;
  862. default:
  863. break;
  864. }
  865. }
  866. return usbd_fail;
  867. }