1
0

ecm.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-11-19 ZYH first version
  9. * 2019-06-10 ZYH fix hotplug
  10. */
  11. #include <rtdevice.h>
  12. #ifdef RT_USB_DEVICE_ECM
  13. #include "cdc.h"
  14. #define DBG_LEVEL DBG_WARNING
  15. #define DBG_SECTION_NAME "ECM"
  16. #include <rtdbg.h>
  17. /* RT-Thread LWIP ethernet interface */
  18. #include <netif/ethernetif.h>
  19. #ifndef USB_ETH_MTU
  20. #define USB_ETH_MTU 1514
  21. #endif
  22. #define MAX_ADDR_LEN 6
  23. #define ECM_INTF_STR_INDEX 10
  24. struct rt_ecm_eth
  25. {
  26. /* inherit from ethernet device */
  27. struct eth_device parent;
  28. struct ufunction * func;
  29. struct cdc_eps eps;
  30. /* interface address info */
  31. rt_uint8_t host_addr[MAX_ADDR_LEN];
  32. rt_uint8_t dev_addr[MAX_ADDR_LEN];
  33. ALIGN(4)
  34. rt_uint8_t rx_pool[512];
  35. ALIGN(4)
  36. rt_size_t rx_size;
  37. ALIGN(4)
  38. rt_size_t rx_offset;
  39. ALIGN(4)
  40. char rx_buffer[USB_ETH_MTU];
  41. char tx_buffer[USB_ETH_MTU];
  42. struct rt_semaphore tx_buffer_free;
  43. };
  44. typedef struct rt_ecm_eth * rt_ecm_eth_t;
  45. ALIGN(4)
  46. static struct udevice_descriptor _dev_desc =
  47. {
  48. USB_DESC_LENGTH_DEVICE, /* bLength */
  49. USB_DESC_TYPE_DEVICE, /* type */
  50. USB_BCD_VERSION, /* bcdUSB */
  51. USB_CLASS_CDC, /* bDeviceClass */
  52. USB_CDC_SUBCLASS_ETH, /* bDeviceSubClass */
  53. USB_CDC_PROTOCOL_NONE, /* bDeviceProtocol */
  54. 0x40, /* bMaxPacketSize0 */
  55. _VENDOR_ID, /* idVendor */
  56. _PRODUCT_ID, /* idProduct */
  57. USB_BCD_DEVICE, /* bcdDevice */
  58. USB_STRING_MANU_INDEX, /* iManufacturer */
  59. USB_STRING_PRODUCT_INDEX, /* iProduct */
  60. USB_STRING_SERIAL_INDEX, /* iSerialNumber */
  61. USB_DYNAMIC /* bNumConfigurations */
  62. };
  63. /* communcation interface descriptor */
  64. ALIGN(4)
  65. const static struct ucdc_eth_descriptor _comm_desc =
  66. {
  67. #ifdef RT_USB_DEVICE_COMPOSITE
  68. /* Interface Association Descriptor */
  69. {
  70. USB_DESC_LENGTH_IAD,
  71. USB_DESC_TYPE_IAD,
  72. USB_DYNAMIC,
  73. 0x02,
  74. USB_CDC_CLASS_COMM,
  75. USB_CDC_SUBCLASS_ETH,
  76. USB_CDC_PROTOCOL_NONE,
  77. 0x00,
  78. },
  79. #endif
  80. /* Interface Descriptor */
  81. {
  82. USB_DESC_LENGTH_INTERFACE,
  83. USB_DESC_TYPE_INTERFACE,
  84. USB_DYNAMIC,
  85. 0x00,
  86. 0x01,
  87. USB_CDC_CLASS_COMM,
  88. USB_CDC_SUBCLASS_ETH,
  89. USB_CDC_PROTOCOL_NONE,
  90. #ifdef RT_USB_DEVICE_COMPOSITE
  91. ECM_INTF_STR_INDEX,
  92. #else
  93. 0x00,
  94. #endif
  95. },
  96. /* Header Functional Descriptor */
  97. {
  98. sizeof(struct ucdc_header_descriptor),
  99. USB_CDC_CS_INTERFACE,
  100. USB_CDC_SCS_HEADER,
  101. 0x0110,
  102. },
  103. /* Union Functional Descriptor */
  104. {
  105. sizeof(struct ucdc_union_descriptor),
  106. USB_CDC_CS_INTERFACE,
  107. USB_CDC_SCS_UNION,
  108. USB_DYNAMIC,
  109. USB_DYNAMIC,
  110. },
  111. /* Abstract Control Management Functional Descriptor */
  112. {
  113. sizeof(struct ucdc_enet_descriptor),
  114. USB_CDC_CS_INTERFACE,
  115. USB_CDC_SCS_ETH,
  116. USB_STRING_SERIAL_INDEX,
  117. {0,0,0,0},
  118. USB_ETH_MTU,
  119. 0x00,
  120. 0x00,
  121. },
  122. /* Endpoint Descriptor */
  123. {
  124. USB_DESC_LENGTH_ENDPOINT,
  125. USB_DESC_TYPE_ENDPOINT,
  126. USB_DIR_IN | USB_DYNAMIC,
  127. USB_EP_ATTR_INT,
  128. 0x08,
  129. 0xFF,
  130. },
  131. };
  132. /* data interface descriptor */
  133. ALIGN(4)
  134. const static struct ucdc_data_descriptor _data_desc =
  135. {
  136. /* interface descriptor */
  137. {
  138. USB_DESC_LENGTH_INTERFACE,
  139. USB_DESC_TYPE_INTERFACE,
  140. USB_DYNAMIC,
  141. 0x00,
  142. 0x02,
  143. USB_CDC_CLASS_DATA,
  144. USB_CDC_SUBCLASS_ETH,
  145. 0x00,
  146. 0x00,
  147. },
  148. /* endpoint, bulk out */
  149. {
  150. USB_DESC_LENGTH_ENDPOINT,
  151. USB_DESC_TYPE_ENDPOINT,
  152. USB_DIR_OUT | USB_DYNAMIC,
  153. USB_EP_ATTR_BULK,
  154. USB_DYNAMIC,
  155. 0x00,
  156. },
  157. /* endpoint, bulk in */
  158. {
  159. USB_DESC_LENGTH_ENDPOINT,
  160. USB_DESC_TYPE_ENDPOINT,
  161. USB_DYNAMIC | USB_DIR_IN,
  162. USB_EP_ATTR_BULK,
  163. USB_DYNAMIC,
  164. 0x00,
  165. },
  166. };
  167. ALIGN(4)
  168. const static char* _ustring[] =
  169. {
  170. "Language", /* LANGID */
  171. "RT-Thread Team.", /* MANU */
  172. "RT-Thread ECM device", /* PRODUCT */
  173. "3497F694ECAB", /* SERIAL (MAC)*/
  174. "Configuration", /* CONFIG */
  175. "Interface", /* INTERFACE */
  176. };
  177. ALIGN(4)
  178. //FS and HS needed
  179. static struct usb_qualifier_descriptor dev_qualifier =
  180. {
  181. sizeof(dev_qualifier), //bLength
  182. USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType
  183. 0x0200, //bcdUSB
  184. USB_CLASS_CDC, //bDeviceClass
  185. USB_CDC_SUBCLASS_ETH, //bDeviceSubClass
  186. USB_CDC_PROTOCOL_NONE, //bDeviceProtocol
  187. 64, //bMaxPacketSize0
  188. 0x01, //bNumConfigurations
  189. 0,
  190. };
  191. static rt_err_t _cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notifi,rt_uint16_t wValue,rt_uint16_t wLength)
  192. {
  193. static struct ucdc_management_element_notifications _notifi;
  194. cdc_eps_t eps;
  195. RT_ASSERT(func!=RT_NULL)
  196. eps = &((rt_ecm_eth_t)func->user_data)->eps;
  197. _notifi.bmRequestType = 0xA1;
  198. _notifi.bNotificatinCode = notifi;
  199. _notifi.wValue = wValue;
  200. _notifi.wLength = wLength;
  201. eps->ep_cmd->request.buffer = (void *)&_notifi;
  202. eps->ep_cmd->request.size = 8;
  203. eps->ep_cmd->request.req_type = UIO_REQUEST_WRITE;
  204. rt_usbd_io_request(func->device, eps->ep_cmd, &eps->ep_cmd->request);
  205. return RT_EOK;
  206. }
  207. static rt_err_t _ecm_set_eth_packet_filter(ufunction_t func, ureq_t setup)
  208. {
  209. rt_ecm_eth_t _ecm_eth = (rt_ecm_eth_t)func->user_data;
  210. dcd_ep0_send_status(func->device->dcd);
  211. /* send link up. */
  212. eth_device_linkchange(&_ecm_eth->parent, RT_TRUE);
  213. _cdc_send_notifi(func, UCDC_NOTIFI_NETWORK_CONNECTION, 1, 0);
  214. #ifdef LWIP_USING_DHCPD
  215. extern void dhcpd_start(const char *netif_name);
  216. dhcpd_start("u0");
  217. #endif
  218. return RT_EOK;
  219. }
  220. /**
  221. * This function will handle rndis interface request.
  222. *
  223. * @param device the usb device object.
  224. * @param setup the setup request.
  225. *
  226. * @return RT_EOK on successful.
  227. */
  228. static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
  229. {
  230. RT_ASSERT(func != RT_NULL);
  231. RT_ASSERT(setup != RT_NULL);
  232. switch(setup->bRequest)
  233. {
  234. case CDC_SET_ETH_PACKET_FILTER:
  235. LOG_D("CDC_SET_ETH_PACKET_FILTER");
  236. _ecm_set_eth_packet_filter(func, setup);
  237. break;
  238. default:
  239. LOG_E("Unknow setup->bRequest: 0x%02X", setup->bRequest);
  240. break;
  241. }
  242. return RT_EOK;
  243. }
  244. /**
  245. * This function will handle rndis bulk in endpoint request.
  246. *
  247. * @param device the usb device object.
  248. * @param size request size.
  249. *
  250. * @return RT_EOK.
  251. */
  252. static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
  253. {
  254. rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data;
  255. rt_sem_release(&ecm_device->tx_buffer_free);
  256. return RT_EOK;
  257. }
  258. /**
  259. * This function will handle RNDIS bulk out endpoint request.
  260. *
  261. * @param device the usb device object.
  262. * @param size request size.
  263. *
  264. * @return RT_EOK.
  265. */
  266. static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
  267. {
  268. rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data;
  269. rt_memcpy((void *)(ecm_device->rx_buffer + ecm_device->rx_offset),ecm_device->rx_pool,size);
  270. ecm_device->rx_offset += size;
  271. if(size < EP_MAXPACKET(ecm_device->eps.ep_out))
  272. {
  273. ecm_device->rx_size = ecm_device->rx_offset;
  274. ecm_device->rx_offset = 0;
  275. eth_device_ready(&ecm_device->parent);
  276. }else
  277. {
  278. ecm_device->eps.ep_out->request.buffer = ecm_device->eps.ep_out->buffer;
  279. ecm_device->eps.ep_out->request.size = EP_MAXPACKET(ecm_device->eps.ep_out);
  280. ecm_device->eps.ep_out->request.req_type = UIO_REQUEST_READ_BEST;
  281. rt_usbd_io_request(ecm_device->func->device, ecm_device->eps.ep_out, &ecm_device->eps.ep_out->request);
  282. }
  283. return RT_EOK;
  284. }
  285. static rt_err_t rt_ecm_eth_init(rt_device_t dev)
  286. {
  287. return RT_EOK;
  288. }
  289. static rt_err_t rt_ecm_eth_open(rt_device_t dev, rt_uint16_t oflag)
  290. {
  291. return RT_EOK;
  292. }
  293. static rt_err_t rt_ecm_eth_close(rt_device_t dev)
  294. {
  295. return RT_EOK;
  296. }
  297. static rt_size_t rt_ecm_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  298. {
  299. rt_set_errno(-RT_ENOSYS);
  300. return 0;
  301. }
  302. static rt_size_t rt_ecm_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  303. {
  304. rt_set_errno(-RT_ENOSYS);
  305. return 0;
  306. }
  307. static rt_err_t rt_ecm_eth_control(rt_device_t dev, int cmd, void *args)
  308. {
  309. rt_ecm_eth_t ecm_eth_dev = (rt_ecm_eth_t)dev;
  310. switch(cmd)
  311. {
  312. case NIOCTL_GADDR:
  313. /* get mac address */
  314. if(args) rt_memcpy(args, ecm_eth_dev->dev_addr, MAX_ADDR_LEN);
  315. else return -RT_ERROR;
  316. break;
  317. default :
  318. break;
  319. }
  320. return RT_EOK;
  321. }
  322. #ifdef RT_USING_DEVICE_OPS
  323. const static struct rt_device_ops ecm_device_ops =
  324. {
  325. rt_ecm_eth_init,
  326. rt_ecm_eth_open,
  327. rt_ecm_eth_close,
  328. rt_ecm_eth_read,
  329. rt_ecm_eth_write,
  330. rt_ecm_eth_control
  331. };
  332. #endif
  333. struct pbuf *rt_ecm_eth_rx(rt_device_t dev)
  334. {
  335. struct pbuf* p = RT_NULL;
  336. rt_uint32_t offset = 0;
  337. rt_ecm_eth_t ecm_eth_dev = (rt_ecm_eth_t)dev;
  338. if(ecm_eth_dev->rx_size != 0)
  339. {
  340. /* allocate buffer */
  341. p = pbuf_alloc(PBUF_RAW, ecm_eth_dev->rx_size, PBUF_RAM);
  342. if (p != RT_NULL)
  343. {
  344. struct pbuf* q;
  345. for (q = p; q != RT_NULL; q= q->next)
  346. {
  347. /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */
  348. rt_memcpy(q->payload,
  349. (rt_uint8_t *)((ecm_eth_dev->rx_buffer) + offset),
  350. q->len);
  351. offset += q->len;
  352. }
  353. }
  354. }
  355. {
  356. if(ecm_eth_dev->func->device->state == USB_STATE_CONFIGURED)
  357. {
  358. ecm_eth_dev->rx_size = 0;
  359. ecm_eth_dev->rx_offset = 0;
  360. ecm_eth_dev->eps.ep_out->request.buffer = ecm_eth_dev->eps.ep_out->buffer;
  361. ecm_eth_dev->eps.ep_out->request.size = EP_MAXPACKET(ecm_eth_dev->eps.ep_out);
  362. ecm_eth_dev->eps.ep_out->request.req_type = UIO_REQUEST_READ_BEST;
  363. rt_usbd_io_request(ecm_eth_dev->func->device, ecm_eth_dev->eps.ep_out, &ecm_eth_dev->eps.ep_out->request);
  364. }
  365. }
  366. return p;
  367. }
  368. rt_err_t rt_ecm_eth_tx(rt_device_t dev, struct pbuf* p)
  369. {
  370. struct pbuf* q;
  371. char * pbuffer;
  372. rt_err_t result = RT_EOK;
  373. rt_ecm_eth_t ecm_eth_dev = (rt_ecm_eth_t)dev;
  374. if(!ecm_eth_dev->parent.link_status)
  375. {
  376. LOG_D("linkdown, drop pkg");
  377. return RT_EOK;
  378. }
  379. if(p->tot_len > USB_ETH_MTU)
  380. {
  381. LOG_W("ECM MTU is:%d, but the send packet size is %d",
  382. USB_ETH_MTU, p->tot_len);
  383. p->tot_len = USB_ETH_MTU;
  384. }
  385. result = rt_sem_take(&ecm_eth_dev->tx_buffer_free, rt_tick_from_millisecond(1000));
  386. if(result != RT_EOK)
  387. {
  388. LOG_W("wait for buffer free timeout");
  389. /* if cost 1s to wait send done it said that connection is close . drop it */
  390. rt_sem_release(&ecm_eth_dev->tx_buffer_free);
  391. return result;
  392. }
  393. pbuffer = (char *)&ecm_eth_dev->tx_buffer;
  394. for (q = p; q != NULL; q = q->next)
  395. {
  396. rt_memcpy(pbuffer, q->payload, q->len);
  397. pbuffer += q->len;
  398. }
  399. {
  400. if(ecm_eth_dev->func->device->state == USB_STATE_CONFIGURED)
  401. {
  402. ecm_eth_dev->eps.ep_in->request.buffer = (void *)&ecm_eth_dev->tx_buffer;
  403. ecm_eth_dev->eps.ep_in->request.size = p->tot_len;
  404. ecm_eth_dev->eps.ep_in->request.req_type = UIO_REQUEST_WRITE;
  405. rt_usbd_io_request(ecm_eth_dev->func->device, ecm_eth_dev->eps.ep_in, &ecm_eth_dev->eps.ep_in->request);
  406. }
  407. }
  408. return result;
  409. }
  410. /**
  411. * This function will handle RNDIS interrupt in endpoint request.
  412. *
  413. * @param device the usb device object.
  414. * @param size request size.
  415. *
  416. * @return RT_EOK.
  417. */
  418. static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
  419. {
  420. return RT_EOK;
  421. }
  422. /**
  423. * This function will run cdc class, it will be called on handle set configuration request.
  424. *
  425. * @param device the usb device object.
  426. *
  427. * @return RT_EOK on successful.
  428. */
  429. static rt_err_t _function_enable(ufunction_t func)
  430. {
  431. cdc_eps_t eps;
  432. rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data;
  433. LOG_D("plugged in");
  434. eps = (cdc_eps_t)&ecm_device->eps;
  435. eps->ep_out->buffer = ecm_device->rx_pool;
  436. /* reset eth rx tx */
  437. ecm_device->rx_size = 0;
  438. ecm_device->rx_offset = 0;
  439. eps->ep_out->request.buffer = (void *)eps->ep_out->buffer;
  440. eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out);
  441. eps->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
  442. rt_usbd_io_request(func->device, eps->ep_out, &eps->ep_out->request);
  443. return RT_EOK;
  444. }
  445. /**
  446. * This function will stop cdc class, it will be called on handle set configuration request.
  447. *
  448. * @param device the usb device object.
  449. *
  450. * @return RT_EOK on successful.
  451. */
  452. static rt_err_t _function_disable(ufunction_t func)
  453. {
  454. LOG_D("plugged out");
  455. eth_device_linkchange(&((rt_ecm_eth_t)func->user_data)->parent, RT_FALSE);
  456. /* reset eth rx tx */
  457. ((rt_ecm_eth_t)func->user_data)->rx_size = 0;
  458. ((rt_ecm_eth_t)func->user_data)->rx_offset = 0;
  459. return RT_EOK;
  460. }
  461. static struct ufunction_ops ops =
  462. {
  463. _function_enable,
  464. _function_disable,
  465. RT_NULL,
  466. };
  467. /**
  468. * This function will configure cdc descriptor.
  469. *
  470. * @param comm the communication interface number.
  471. * @param data the data interface number.
  472. *
  473. * @return RT_EOK on successful.
  474. */
  475. static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr, rt_uint8_t device_is_hs)
  476. {
  477. comm->call_mgmt_desc.data_interface = dintf_nr;
  478. comm->union_desc.master_interface = cintf_nr;
  479. comm->union_desc.slave_interface0 = dintf_nr;
  480. #ifdef RT_USB_DEVICE_COMPOSITE
  481. comm->iad_desc.bFirstInterface = cintf_nr;
  482. #endif
  483. data->ep_out_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
  484. data->ep_in_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
  485. return RT_EOK;
  486. }
  487. /**
  488. * This function will create a cdc ecm class instance.
  489. *
  490. * @param device the usb device object.
  491. *
  492. * @return RT_EOK on successful.
  493. */
  494. ufunction_t rt_usbd_function_ecm_create(udevice_t device)
  495. {
  496. ufunction_t cdc;
  497. rt_ecm_eth_t _ecm_eth;
  498. cdc_eps_t eps;
  499. uintf_t intf_comm, intf_data;
  500. ualtsetting_t comm_setting, data_setting;
  501. ucdc_data_desc_t data_desc;
  502. ucdc_eth_desc_t comm_desc;
  503. /* parameter check */
  504. RT_ASSERT(device != RT_NULL);
  505. /* set usb device string description */
  506. #ifdef RT_USB_DEVICE_COMPOSITE
  507. rt_usbd_device_set_interface_string(device, ECM_INTF_STR_INDEX, _ustring[2]);
  508. #else
  509. rt_usbd_device_set_string(device, _ustring);
  510. #endif
  511. /* create a cdc class */
  512. cdc = rt_usbd_function_new(device, &_dev_desc, &ops);
  513. rt_usbd_device_set_qualifier(device, &dev_qualifier);
  514. _ecm_eth= rt_malloc(sizeof(struct rt_ecm_eth));
  515. RT_ASSERT(_ecm_eth != RT_NULL);
  516. rt_memset(_ecm_eth, 0, sizeof(struct rt_ecm_eth));
  517. cdc->user_data = _ecm_eth;
  518. _ecm_eth->func = cdc;
  519. /* create a cdc class endpoints collection */
  520. eps = &_ecm_eth->eps;
  521. /* create a cdc communication interface and a cdc data interface */
  522. intf_comm = rt_usbd_interface_new(device, _interface_handler);
  523. intf_data = rt_usbd_interface_new(device, _interface_handler);
  524. /* create a communication alternate setting and a data alternate setting */
  525. comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_eth_descriptor));
  526. data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
  527. /* config desc in alternate setting */
  528. rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
  529. (rt_off_t)&((ucdc_eth_desc_t)0)->intf_desc);
  530. rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
  531. /* configure the cdc interface descriptor */
  532. _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num, device->dcd->device_is_hs);
  533. /* create a command endpoint */
  534. comm_desc = (ucdc_eth_desc_t)comm_setting->desc;
  535. eps->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
  536. /* add the command endpoint to the cdc communication interface */
  537. rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd);
  538. /* add the communication alternate setting to the communication interface,
  539. then set default setting of the interface */
  540. rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
  541. rt_usbd_set_altsetting(intf_comm, 0);
  542. /* add the communication interface to the cdc class */
  543. rt_usbd_function_add_interface(cdc, intf_comm);
  544. /* create a bulk in and a bulk out endpoint */
  545. data_desc = (ucdc_data_desc_t)data_setting->desc;
  546. eps->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
  547. eps->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
  548. /* add the bulk out and bulk in endpoints to the data alternate setting */
  549. rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in);
  550. rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out);
  551. /* add the data alternate setting to the data interface
  552. then set default setting of the interface */
  553. rt_usbd_interface_add_altsetting(intf_data, data_setting);
  554. rt_usbd_set_altsetting(intf_data, 0);
  555. /* add the cdc data interface to cdc class */
  556. rt_usbd_function_add_interface(cdc, intf_data);
  557. rt_sem_init(&_ecm_eth->tx_buffer_free, "ue_tx", 1, RT_IPC_FLAG_FIFO);
  558. /* OUI 00-00-00, only for test. */
  559. _ecm_eth->dev_addr[0] = 0x34;
  560. _ecm_eth->dev_addr[1] = 0x97;
  561. _ecm_eth->dev_addr[2] = 0xF6;
  562. /* generate random MAC. */
  563. _ecm_eth->dev_addr[3] = 0x94;//*(const rt_uint8_t *)(0x1fff7a10);
  564. _ecm_eth->dev_addr[4] = 0xEC;//*(const rt_uint8_t *)(0x1fff7a14);
  565. _ecm_eth->dev_addr[5] = 0xAC;//(const rt_uint8_t *)(0x1fff7a18);
  566. /* OUI 00-00-00, only for test. */
  567. _ecm_eth->host_addr[0] = 0x34;
  568. _ecm_eth->host_addr[1] = 0x97;
  569. _ecm_eth->host_addr[2] = 0xF6;
  570. /* generate random MAC. */
  571. _ecm_eth->host_addr[3] = 0x94;//*(const rt_uint8_t *)(0x1fff7a10);
  572. _ecm_eth->host_addr[4] = 0xEC;//*(const rt_uint8_t *)(0x1fff7a14);
  573. _ecm_eth->host_addr[5] = 0xAB;//*(const rt_uint8_t *)(0x1fff7a18);
  574. #ifdef RT_USING_DEVICE_OPS
  575. _ecm_eth->parent.parent.ops = &ecm_device_ops;
  576. #else
  577. _ecm_eth->parent.parent.init = rt_ecm_eth_init;
  578. _ecm_eth->parent.parent.open = rt_ecm_eth_open;
  579. _ecm_eth->parent.parent.close = rt_ecm_eth_close;
  580. _ecm_eth->parent.parent.read = rt_ecm_eth_read;
  581. _ecm_eth->parent.parent.write = rt_ecm_eth_write;
  582. _ecm_eth->parent.parent.control = rt_ecm_eth_control;
  583. #endif
  584. _ecm_eth->parent.parent.user_data = device;
  585. _ecm_eth->parent.eth_rx = rt_ecm_eth_rx;
  586. _ecm_eth->parent.eth_tx = rt_ecm_eth_tx;
  587. /* register eth device */
  588. eth_device_init(&_ecm_eth->parent, "u0");
  589. /* send link up. */
  590. eth_device_linkchange(&_ecm_eth->parent, RT_FALSE);
  591. return cdc;
  592. }
  593. struct udclass ecm_class =
  594. {
  595. .rt_usbd_function_create = rt_usbd_function_ecm_create
  596. };
  597. int rt_usbd_ecm_class_register(void)
  598. {
  599. rt_usbd_class_register(&ecm_class);
  600. return 0;
  601. }
  602. INIT_PREV_EXPORT(rt_usbd_ecm_class_register);
  603. #endif /* RT_USB_DEVICE_ECM */