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