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
_cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notifi,rt_uint16_t wValue,rt_uint16_t wLength)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
_ecm_set_eth_packet_filter(ufunction_t func,ureq_t setup)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 */
_interface_handler(ufunction_t func,ureq_t setup)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
_ep_in_handler(ufunction_t func,rt_size_t size)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 */
_ep_out_handler(ufunction_t func,rt_size_t size)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 }
rt_ecm_eth_init(rt_device_t dev)301 static rt_err_t rt_ecm_eth_init(rt_device_t dev)
302 {
303 return RT_EOK;
304 }
305
rt_ecm_eth_open(rt_device_t dev,rt_uint16_t oflag)306 static rt_err_t rt_ecm_eth_open(rt_device_t dev, rt_uint16_t oflag)
307 {
308 return RT_EOK;
309 }
310
rt_ecm_eth_close(rt_device_t dev)311 static rt_err_t rt_ecm_eth_close(rt_device_t dev)
312 {
313 return RT_EOK;
314 }
315
rt_ecm_eth_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)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
rt_ecm_eth_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)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 }
rt_ecm_eth_control(rt_device_t dev,int cmd,void * args)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
rt_ecm_eth_rx(rt_device_t dev)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
rt_ecm_eth_tx(rt_device_t dev,struct pbuf * p)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 */
_ep_cmd_handler(ufunction_t func,rt_size_t size)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 */
_function_enable(ufunction_t func)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 */
_function_disable(ufunction_t func)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 */
_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)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 */
rt_usbd_function_ecm_create(udevice_t device)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
rt_usbd_ecm_class_register(void)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