furi-hal-usb-cdc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. #include "furi-hal-version.h"
  2. #include "furi-hal-usb_i.h"
  3. #include "furi-hal-usb-cdc_i.h"
  4. #include <furi.h>
  5. #include "usb.h"
  6. #include "usb_cdc.h"
  7. #define CDC0_RXD_EP 0x01
  8. #define CDC0_TXD_EP 0x81
  9. #define CDC0_NTF_EP 0x82
  10. #define CDC1_RXD_EP 0x03
  11. #define CDC1_TXD_EP 0x83
  12. #define CDC1_NTF_EP 0x84
  13. #define CDC_NTF_SZ 0x08
  14. #define IF_NUM_MAX 2
  15. struct CdcIadDescriptor {
  16. struct usb_iad_descriptor comm_iad;
  17. struct usb_interface_descriptor comm;
  18. struct usb_cdc_header_desc cdc_hdr;
  19. struct usb_cdc_call_mgmt_desc cdc_mgmt;
  20. struct usb_cdc_acm_desc cdc_acm;
  21. struct usb_cdc_union_desc cdc_union;
  22. struct usb_endpoint_descriptor comm_ep;
  23. struct usb_interface_descriptor data;
  24. struct usb_endpoint_descriptor data_eprx;
  25. struct usb_endpoint_descriptor data_eptx;
  26. };
  27. struct CdcConfigDescriptorSingle {
  28. struct usb_config_descriptor config;
  29. struct CdcIadDescriptor iad_0;
  30. } __attribute__((packed));
  31. struct CdcConfigDescriptorDual {
  32. struct usb_config_descriptor config;
  33. struct CdcIadDescriptor iad_0;
  34. struct CdcIadDescriptor iad_1;
  35. } __attribute__((packed));
  36. static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Flipper Devices Inc.");
  37. /* Device descriptor */
  38. static const struct usb_device_descriptor cdc_device_desc = {
  39. .bLength = sizeof(struct usb_device_descriptor),
  40. .bDescriptorType = USB_DTYPE_DEVICE,
  41. .bcdUSB = VERSION_BCD(2,0,0),
  42. .bDeviceClass = USB_CLASS_IAD,
  43. .bDeviceSubClass = USB_SUBCLASS_IAD,
  44. .bDeviceProtocol = USB_PROTO_IAD,
  45. .bMaxPacketSize0 = USB_EP0_SIZE,
  46. .idVendor = 0x0483,
  47. .idProduct = 0x5740,
  48. .bcdDevice = VERSION_BCD(1,0,0),
  49. .iManufacturer = UsbDevManuf,
  50. .iProduct = UsbDevProduct,
  51. .iSerialNumber = UsbDevSerial,
  52. .bNumConfigurations = 1,
  53. };
  54. /* Device configuration descriptor - single mode*/
  55. static const struct CdcConfigDescriptorSingle cdc_cfg_desc_single = {
  56. .config = {
  57. .bLength = sizeof(struct usb_config_descriptor),
  58. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  59. .wTotalLength = sizeof(struct CdcConfigDescriptorSingle),
  60. .bNumInterfaces = 2,
  61. .bConfigurationValue = 1,
  62. .iConfiguration = NO_DESCRIPTOR,
  63. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  64. .bMaxPower = USB_CFG_POWER_MA(100),
  65. },
  66. .iad_0 = {
  67. .comm_iad = {
  68. .bLength = sizeof(struct usb_iad_descriptor),
  69. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  70. .bFirstInterface = 0,
  71. .bInterfaceCount = 2,
  72. .bFunctionClass = USB_CLASS_CDC,
  73. .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
  74. .bFunctionProtocol = USB_PROTO_NONE,
  75. .iFunction = NO_DESCRIPTOR,
  76. },
  77. .comm = {
  78. .bLength = sizeof(struct usb_interface_descriptor),
  79. .bDescriptorType = USB_DTYPE_INTERFACE,
  80. .bInterfaceNumber = 0,
  81. .bAlternateSetting = 0,
  82. .bNumEndpoints = 1,
  83. .bInterfaceClass = USB_CLASS_CDC,
  84. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  85. .bInterfaceProtocol = USB_PROTO_NONE,
  86. .iInterface = NO_DESCRIPTOR,
  87. },
  88. .cdc_hdr = {
  89. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  90. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  91. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  92. .bcdCDC = VERSION_BCD(1,1,0),
  93. },
  94. .cdc_mgmt = {
  95. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  96. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  97. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  98. .bmCapabilities = 0,
  99. .bDataInterface = 1,
  100. },
  101. .cdc_acm = {
  102. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  103. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  104. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  105. .bmCapabilities = 0,
  106. },
  107. .cdc_union = {
  108. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  109. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  110. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  111. .bMasterInterface0 = 0,
  112. .bSlaveInterface0 = 1,
  113. },
  114. .comm_ep = {
  115. .bLength = sizeof(struct usb_endpoint_descriptor),
  116. .bDescriptorType = USB_DTYPE_ENDPOINT,
  117. .bEndpointAddress = CDC0_NTF_EP,
  118. .bmAttributes = USB_EPTYPE_INTERRUPT,
  119. .wMaxPacketSize = CDC_NTF_SZ,
  120. .bInterval = 0xFF,
  121. },
  122. .data = {
  123. .bLength = sizeof(struct usb_interface_descriptor),
  124. .bDescriptorType = USB_DTYPE_INTERFACE,
  125. .bInterfaceNumber = 1,
  126. .bAlternateSetting = 0,
  127. .bNumEndpoints = 2,
  128. .bInterfaceClass = USB_CLASS_CDC_DATA,
  129. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  130. .bInterfaceProtocol = USB_PROTO_NONE,
  131. .iInterface = NO_DESCRIPTOR,
  132. },
  133. .data_eprx = {
  134. .bLength = sizeof(struct usb_endpoint_descriptor),
  135. .bDescriptorType = USB_DTYPE_ENDPOINT,
  136. .bEndpointAddress = CDC0_RXD_EP,
  137. .bmAttributes = USB_EPTYPE_BULK,
  138. .wMaxPacketSize = CDC_DATA_SZ,
  139. .bInterval = 0x01,
  140. },
  141. .data_eptx = {
  142. .bLength = sizeof(struct usb_endpoint_descriptor),
  143. .bDescriptorType = USB_DTYPE_ENDPOINT,
  144. .bEndpointAddress = CDC0_TXD_EP,
  145. .bmAttributes = USB_EPTYPE_BULK,
  146. .wMaxPacketSize = CDC_DATA_SZ,
  147. .bInterval = 0x01,
  148. },
  149. },
  150. };
  151. /* Device configuration descriptor - dual mode*/
  152. static const struct CdcConfigDescriptorDual cdc_cfg_desc_dual = {
  153. .config = {
  154. .bLength = sizeof(struct usb_config_descriptor),
  155. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  156. .wTotalLength = sizeof(struct CdcConfigDescriptorDual),
  157. .bNumInterfaces = 4,
  158. .bConfigurationValue = 1,
  159. .iConfiguration = NO_DESCRIPTOR,
  160. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  161. .bMaxPower = USB_CFG_POWER_MA(100),
  162. },
  163. .iad_0 = {
  164. .comm_iad = {
  165. .bLength = sizeof(struct usb_iad_descriptor),
  166. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  167. .bFirstInterface = 0,
  168. .bInterfaceCount = 2,
  169. .bFunctionClass = USB_CLASS_CDC,
  170. .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
  171. .bFunctionProtocol = USB_PROTO_NONE,
  172. .iFunction = NO_DESCRIPTOR,
  173. },
  174. .comm = {
  175. .bLength = sizeof(struct usb_interface_descriptor),
  176. .bDescriptorType = USB_DTYPE_INTERFACE,
  177. .bInterfaceNumber = 0,
  178. .bAlternateSetting = 0,
  179. .bNumEndpoints = 1,
  180. .bInterfaceClass = USB_CLASS_CDC,
  181. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  182. .bInterfaceProtocol = USB_PROTO_NONE,
  183. .iInterface = NO_DESCRIPTOR,
  184. },
  185. .cdc_hdr = {
  186. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  187. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  188. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  189. .bcdCDC = VERSION_BCD(1,1,0),
  190. },
  191. .cdc_mgmt = {
  192. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  193. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  194. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  195. .bmCapabilities = 0,
  196. .bDataInterface = 1,
  197. },
  198. .cdc_acm = {
  199. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  200. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  201. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  202. .bmCapabilities = 0,
  203. },
  204. .cdc_union = {
  205. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  206. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  207. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  208. .bMasterInterface0 = 0,
  209. .bSlaveInterface0 = 1,
  210. },
  211. .comm_ep = {
  212. .bLength = sizeof(struct usb_endpoint_descriptor),
  213. .bDescriptorType = USB_DTYPE_ENDPOINT,
  214. .bEndpointAddress = CDC0_NTF_EP,
  215. .bmAttributes = USB_EPTYPE_INTERRUPT,
  216. .wMaxPacketSize = CDC_NTF_SZ,
  217. .bInterval = 0xFF,
  218. },
  219. .data = {
  220. .bLength = sizeof(struct usb_interface_descriptor),
  221. .bDescriptorType = USB_DTYPE_INTERFACE,
  222. .bInterfaceNumber = 1,
  223. .bAlternateSetting = 0,
  224. .bNumEndpoints = 2,
  225. .bInterfaceClass = USB_CLASS_CDC_DATA,
  226. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  227. .bInterfaceProtocol = USB_PROTO_NONE,
  228. .iInterface = NO_DESCRIPTOR,
  229. },
  230. .data_eprx = {
  231. .bLength = sizeof(struct usb_endpoint_descriptor),
  232. .bDescriptorType = USB_DTYPE_ENDPOINT,
  233. .bEndpointAddress = CDC0_RXD_EP,
  234. .bmAttributes = USB_EPTYPE_BULK,
  235. .wMaxPacketSize = CDC_DATA_SZ,
  236. .bInterval = 0x01,
  237. },
  238. .data_eptx = {
  239. .bLength = sizeof(struct usb_endpoint_descriptor),
  240. .bDescriptorType = USB_DTYPE_ENDPOINT,
  241. .bEndpointAddress = CDC0_TXD_EP,
  242. .bmAttributes = USB_EPTYPE_BULK,
  243. .wMaxPacketSize = CDC_DATA_SZ,
  244. .bInterval = 0x01,
  245. },
  246. },
  247. .iad_1 = {
  248. .comm_iad = {
  249. .bLength = sizeof(struct usb_iad_descriptor),
  250. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  251. .bFirstInterface = 2,
  252. .bInterfaceCount = 2,
  253. .bFunctionClass = USB_CLASS_CDC,
  254. .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
  255. .bFunctionProtocol = USB_PROTO_NONE,
  256. .iFunction = NO_DESCRIPTOR,
  257. },
  258. .comm = {
  259. .bLength = sizeof(struct usb_interface_descriptor),
  260. .bDescriptorType = USB_DTYPE_INTERFACE,
  261. .bInterfaceNumber = 2+0,
  262. .bAlternateSetting = 0,
  263. .bNumEndpoints = 1,
  264. .bInterfaceClass = USB_CLASS_CDC,
  265. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  266. .bInterfaceProtocol = USB_PROTO_NONE,
  267. .iInterface = NO_DESCRIPTOR,
  268. },
  269. .cdc_hdr = {
  270. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  271. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  272. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  273. .bcdCDC = VERSION_BCD(1,1,0),
  274. },
  275. .cdc_mgmt = {
  276. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  277. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  278. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  279. .bmCapabilities = 0,
  280. .bDataInterface = 2+1,
  281. },
  282. .cdc_acm = {
  283. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  284. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  285. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  286. .bmCapabilities = 0,
  287. },
  288. .cdc_union = {
  289. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  290. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  291. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  292. .bMasterInterface0 = 2+0,
  293. .bSlaveInterface0 = 2+1,
  294. },
  295. .comm_ep = {
  296. .bLength = sizeof(struct usb_endpoint_descriptor),
  297. .bDescriptorType = USB_DTYPE_ENDPOINT,
  298. .bEndpointAddress = CDC1_NTF_EP,
  299. .bmAttributes = USB_EPTYPE_INTERRUPT,
  300. .wMaxPacketSize = CDC_NTF_SZ,
  301. .bInterval = 0xFF,
  302. },
  303. .data = {
  304. .bLength = sizeof(struct usb_interface_descriptor),
  305. .bDescriptorType = USB_DTYPE_INTERFACE,
  306. .bInterfaceNumber = 2+1,
  307. .bAlternateSetting = 0,
  308. .bNumEndpoints = 2,
  309. .bInterfaceClass = USB_CLASS_CDC_DATA,
  310. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  311. .bInterfaceProtocol = USB_PROTO_NONE,
  312. .iInterface = NO_DESCRIPTOR,
  313. },
  314. .data_eprx = {
  315. .bLength = sizeof(struct usb_endpoint_descriptor),
  316. .bDescriptorType = USB_DTYPE_ENDPOINT,
  317. .bEndpointAddress = CDC1_RXD_EP,
  318. .bmAttributes = USB_EPTYPE_BULK,
  319. .wMaxPacketSize = CDC_DATA_SZ,
  320. .bInterval = 0x01,
  321. },
  322. .data_eptx = {
  323. .bLength = sizeof(struct usb_endpoint_descriptor),
  324. .bDescriptorType = USB_DTYPE_ENDPOINT,
  325. .bEndpointAddress = CDC1_TXD_EP,
  326. .bmAttributes = USB_EPTYPE_BULK,
  327. .wMaxPacketSize = CDC_DATA_SZ,
  328. .bInterval = 0x01,
  329. },
  330. },
  331. };
  332. static struct usb_cdc_line_coding cdc_config[IF_NUM_MAX] = {};
  333. static void cdc_init(usbd_device* dev, struct UsbInterface* intf);
  334. static void cdc_deinit(usbd_device *dev);
  335. static void cdc_on_wakeup(usbd_device *dev);
  336. static void cdc_on_suspend(usbd_device *dev);
  337. static usbd_respond cdc_ep_config (usbd_device *dev, uint8_t cfg);
  338. static usbd_respond cdc_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback);
  339. static usbd_device* usb_dev;
  340. static struct UsbInterface* cdc_if_cur = NULL;
  341. static CdcCallbacks* callbacks[IF_NUM_MAX] = {NULL};
  342. struct UsbInterface usb_cdc_single = {
  343. .init = cdc_init,
  344. .deinit = cdc_deinit,
  345. .wakeup = cdc_on_wakeup,
  346. .suspend = cdc_on_suspend,
  347. .dev_descr = (struct usb_device_descriptor*)&cdc_device_desc,
  348. .str_manuf_descr = (void*)&dev_manuf_desc,
  349. .str_prod_descr = NULL,
  350. .str_serial_descr = NULL,
  351. .cfg_descr = (void*)&cdc_cfg_desc_single,
  352. };
  353. struct UsbInterface usb_cdc_dual = {
  354. .init = cdc_init,
  355. .deinit = cdc_deinit,
  356. .wakeup = cdc_on_wakeup,
  357. .suspend = cdc_on_suspend,
  358. .dev_descr = (struct usb_device_descriptor*)&cdc_device_desc,
  359. .str_manuf_descr = (void*)&dev_manuf_desc,
  360. .str_prod_descr = NULL,
  361. .str_serial_descr = NULL,
  362. .cfg_descr = (void*)&cdc_cfg_desc_dual,
  363. };
  364. static void cdc_init(usbd_device* dev, struct UsbInterface* intf) {
  365. usb_dev = dev;
  366. cdc_if_cur = intf;
  367. char* name = (char*)furi_hal_version_get_device_name_ptr();
  368. uint8_t len = (name == NULL) ? (0) : (strlen(name));
  369. struct usb_string_descriptor* dev_prod_desc = furi_alloc(len * 2 + 2);
  370. dev_prod_desc->bLength = len * 2 + 2;
  371. dev_prod_desc->bDescriptorType = USB_DTYPE_STRING;
  372. for (uint8_t i = 0; i < len; i++)
  373. dev_prod_desc->wString[i] = name[i];
  374. name = (char*)furi_hal_version_get_name_ptr();
  375. len = (name == NULL) ? (0) : (strlen(name));
  376. struct usb_string_descriptor* dev_serial_desc = furi_alloc((len + 5) * 2 + 2);
  377. dev_serial_desc->bLength = (len + 5) * 2 + 2;
  378. dev_serial_desc->bDescriptorType = USB_DTYPE_STRING;
  379. memcpy(dev_serial_desc->wString, "f\0l\0i\0p\0_\0", 5*2);
  380. for (uint8_t i = 0; i < len; i++)
  381. dev_serial_desc->wString[i+5] = name[i];
  382. cdc_if_cur->str_prod_descr = dev_prod_desc;
  383. cdc_if_cur->str_serial_descr = dev_serial_desc;
  384. usbd_reg_config(dev, cdc_ep_config);
  385. usbd_reg_control(dev, cdc_control);
  386. usbd_connect(dev, true);
  387. }
  388. static void cdc_deinit(usbd_device *dev) {
  389. usbd_reg_config(dev, NULL);
  390. usbd_reg_control(dev, NULL);
  391. free(cdc_if_cur->str_prod_descr);
  392. free(cdc_if_cur->str_serial_descr);
  393. cdc_if_cur = NULL;
  394. }
  395. void furi_hal_cdc_set_callbacks(uint8_t if_num, CdcCallbacks* cb) {
  396. if (if_num < 2)
  397. callbacks[if_num] = cb;
  398. }
  399. struct usb_cdc_line_coding* furi_hal_cdc_get_port_settings(uint8_t if_num) {
  400. if (if_num < 2)
  401. return &cdc_config[if_num];
  402. return NULL;
  403. }
  404. void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) {
  405. if (if_num == 0)
  406. usbd_ep_write(usb_dev, CDC0_TXD_EP, buf, len);
  407. else
  408. usbd_ep_write(usb_dev, CDC1_TXD_EP, buf, len);
  409. }
  410. int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) {
  411. if (if_num == 0)
  412. return usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len);
  413. else
  414. return usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len);
  415. }
  416. static void cdc_on_wakeup(usbd_device *dev) {
  417. for (uint8_t i = 0; i < IF_NUM_MAX; i++) {
  418. if (callbacks[i] != NULL) {
  419. if (callbacks[i]->state_callback != NULL)
  420. callbacks[i]->state_callback(1);
  421. }
  422. }
  423. }
  424. static void cdc_on_suspend(usbd_device *dev) {
  425. for (uint8_t i = 0; i < IF_NUM_MAX; i++) {
  426. if (callbacks[i] != NULL) {
  427. if (callbacks[i]->state_callback != NULL)
  428. callbacks[i]->state_callback(0);
  429. }
  430. }
  431. }
  432. static void cdc_rx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  433. uint8_t if_num = 0;
  434. if (ep == CDC0_RXD_EP)
  435. if_num = 0;
  436. else
  437. if_num = 1;
  438. if (callbacks[if_num] != NULL) {
  439. if (callbacks[if_num]->rx_ep_callback != NULL)
  440. callbacks[if_num]->rx_ep_callback();
  441. }
  442. }
  443. static void cdc_tx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  444. uint8_t if_num = 0;
  445. if (ep == CDC0_TXD_EP)
  446. if_num = 0;
  447. else
  448. if_num = 1;
  449. if (callbacks[if_num] != NULL) {
  450. if (callbacks[if_num]->tx_ep_callback != NULL)
  451. callbacks[if_num]->tx_ep_callback();
  452. }
  453. }
  454. static void cdc_txrx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) {
  455. if (event == usbd_evt_eptx) {
  456. cdc_tx_ep_callback(dev, event, ep);
  457. } else {
  458. cdc_rx_ep_callback(dev, event, ep);
  459. }
  460. }
  461. /* Configure endpoints */
  462. static usbd_respond cdc_ep_config (usbd_device *dev, uint8_t cfg) {
  463. uint8_t if_cnt = ((struct usb_config_descriptor*)(cdc_if_cur->cfg_descr))->bNumInterfaces;
  464. switch (cfg) {
  465. case 0:
  466. /* deconfiguring device */
  467. usbd_ep_deconfig(dev, CDC0_NTF_EP);
  468. usbd_ep_deconfig(dev, CDC0_TXD_EP);
  469. usbd_ep_deconfig(dev, CDC0_RXD_EP);
  470. usbd_reg_endpoint(dev, CDC0_RXD_EP, 0);
  471. usbd_reg_endpoint(dev, CDC0_TXD_EP, 0);
  472. if (if_cnt == 4) {
  473. usbd_ep_deconfig(dev, CDC1_NTF_EP);
  474. usbd_ep_deconfig(dev, CDC1_TXD_EP);
  475. usbd_ep_deconfig(dev, CDC1_RXD_EP);
  476. usbd_reg_endpoint(dev, CDC1_RXD_EP, 0);
  477. usbd_reg_endpoint(dev, CDC1_TXD_EP, 0);
  478. }
  479. return usbd_ack;
  480. case 1:
  481. /* configuring device */
  482. if ((CDC0_TXD_EP & 0x7F) != (CDC0_RXD_EP & 0x7F)) {
  483. // 2x unidirectional endpoint mode with dualbuf
  484. usbd_ep_config(dev, CDC0_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  485. usbd_ep_config(dev, CDC0_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  486. usbd_ep_config(dev, CDC0_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  487. usbd_reg_endpoint(dev, CDC0_RXD_EP, cdc_rx_ep_callback);
  488. usbd_reg_endpoint(dev, CDC0_TXD_EP, cdc_tx_ep_callback);
  489. } else {
  490. // 1x bidirectional endpoint mode
  491. usbd_ep_config(dev, CDC0_RXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ);
  492. usbd_ep_config(dev, CDC0_TXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ);
  493. usbd_ep_config(dev, CDC0_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  494. usbd_reg_endpoint(dev, CDC0_RXD_EP, cdc_txrx_ep_callback);
  495. usbd_reg_endpoint(dev, CDC0_TXD_EP, cdc_txrx_ep_callback);
  496. }
  497. usbd_ep_write(dev, CDC0_TXD_EP, 0, 0);
  498. if (if_cnt == 4) {
  499. if ((CDC1_TXD_EP & 0x7F) != (CDC1_RXD_EP & 0x7F)) {
  500. usbd_ep_config(dev, CDC1_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  501. usbd_ep_config(dev, CDC1_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  502. usbd_ep_config(dev, CDC1_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  503. usbd_reg_endpoint(dev, CDC1_RXD_EP, cdc_rx_ep_callback);
  504. usbd_reg_endpoint(dev, CDC1_TXD_EP, cdc_tx_ep_callback);
  505. } else {
  506. usbd_ep_config(dev, CDC1_RXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ);
  507. usbd_ep_config(dev, CDC1_TXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ);
  508. usbd_ep_config(dev, CDC1_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  509. usbd_reg_endpoint(dev, CDC1_RXD_EP, cdc_txrx_ep_callback);
  510. usbd_reg_endpoint(dev, CDC1_TXD_EP, cdc_txrx_ep_callback);
  511. }
  512. usbd_ep_write(dev, CDC1_TXD_EP, 0, 0);
  513. }
  514. return usbd_ack;
  515. default:
  516. return usbd_fail;
  517. }
  518. }
  519. /* Control requests handler */
  520. static usbd_respond cdc_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  521. /* CDC control requests */
  522. uint8_t if_num = 0;
  523. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS)
  524. && (req->wIndex == 0 || req->wIndex == 2)) {
  525. if (req->wIndex == 0)
  526. if_num = 0;
  527. else
  528. if_num = 1;
  529. switch(req->bRequest) {
  530. case USB_CDC_SET_CONTROL_LINE_STATE:
  531. if (callbacks[if_num] != NULL) {
  532. if (callbacks[if_num]->ctrl_line_callback != NULL)
  533. callbacks[if_num]->ctrl_line_callback(req->wValue);
  534. }
  535. return usbd_ack;
  536. case USB_CDC_SET_LINE_CODING:
  537. memcpy(&cdc_config[if_num], req->data, sizeof(cdc_config[0]));
  538. if (callbacks[if_num] != NULL) {
  539. if (callbacks[if_num]->config_callback != NULL)
  540. callbacks[if_num]->config_callback(&cdc_config[if_num]);
  541. }
  542. return usbd_ack;
  543. case USB_CDC_GET_LINE_CODING:
  544. dev->status.data_ptr = &cdc_config[if_num];
  545. dev->status.data_count = sizeof(cdc_config[0]);
  546. return usbd_ack;
  547. default:
  548. return usbd_fail;
  549. }
  550. }
  551. return usbd_fail;
  552. }