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