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 * 2012-12-24 heyuanjie87 first version
9*10465441SEvalZero * 2013-04-13 aozima update ethernet driver.
10*10465441SEvalZero * 2013-04-26 aozima align the desc to 4byte.
11*10465441SEvalZero * 2013-05-08 aozima pad a dummy when send MAX_PKT_SIZE.
12*10465441SEvalZero * 2013-05-09 aozima add delay linkup feature.
13*10465441SEvalZero * 2013-07-09 aozima support respone chain list.
14*10465441SEvalZero * 2013-07-18 aozima re-initial respone chain list when RNDIS restart.
15*10465441SEvalZero * 2017-11-25 ZYH fix it and add OS descriptor
16*10465441SEvalZero */
17*10465441SEvalZero
18*10465441SEvalZero #include <rtdevice.h>
19*10465441SEvalZero #include "cdc.h"
20*10465441SEvalZero #include "rndis.h"
21*10465441SEvalZero #include "ndis.h"
22*10465441SEvalZero
23*10465441SEvalZero //#define RNDIS_DEBUG
24*10465441SEvalZero //#define RNDIS_DELAY_LINK_UP
25*10465441SEvalZero
26*10465441SEvalZero #ifdef RNDIS_DEBUG
27*10465441SEvalZero #define RNDIS_PRINTF rt_kprintf("[RNDIS] "); rt_kprintf
28*10465441SEvalZero #else
29*10465441SEvalZero #define RNDIS_PRINTF(...)
30*10465441SEvalZero #endif /* RNDIS_DEBUG */
31*10465441SEvalZero
32*10465441SEvalZero /* RT-Thread LWIP ethernet interface */
33*10465441SEvalZero #include <netif/ethernetif.h>
34*10465441SEvalZero
35*10465441SEvalZero
36*10465441SEvalZero struct rt_rndis_response
37*10465441SEvalZero {
38*10465441SEvalZero struct rt_list_node list;
39*10465441SEvalZero const void * buffer;
40*10465441SEvalZero };
41*10465441SEvalZero
42*10465441SEvalZero #define MAX_ADDR_LEN 6
43*10465441SEvalZero struct rt_rndis_eth
44*10465441SEvalZero {
45*10465441SEvalZero /* inherit from ethernet device */
46*10465441SEvalZero struct eth_device parent;
47*10465441SEvalZero struct ufunction *func;
48*10465441SEvalZero /* interface address info */
49*10465441SEvalZero rt_uint8_t host_addr[MAX_ADDR_LEN];
50*10465441SEvalZero rt_uint8_t dev_addr[MAX_ADDR_LEN];
51*10465441SEvalZero
52*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
53*10465441SEvalZero struct rt_timer timer;
54*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
55*10465441SEvalZero
56*10465441SEvalZero ALIGN(4)
57*10465441SEvalZero rt_uint8_t rx_pool[512];
58*10465441SEvalZero ALIGN(4)
59*10465441SEvalZero rt_uint8_t tx_pool[512];
60*10465441SEvalZero
61*10465441SEvalZero rt_uint32_t cmd_pool[2];
62*10465441SEvalZero ALIGN(4)
63*10465441SEvalZero char rx_buffer[sizeof(struct rndis_packet_msg) + USB_ETH_MTU + 14];
64*10465441SEvalZero rt_size_t rx_offset;
65*10465441SEvalZero rt_size_t rx_length;
66*10465441SEvalZero rt_bool_t rx_flag;
67*10465441SEvalZero rt_bool_t rx_frist;
68*10465441SEvalZero
69*10465441SEvalZero ALIGN(4)
70*10465441SEvalZero char tx_buffer[sizeof(struct rndis_packet_msg) + USB_ETH_MTU + 14];
71*10465441SEvalZero struct rt_semaphore tx_buffer_free;
72*10465441SEvalZero
73*10465441SEvalZero struct rt_list_node response_list;
74*10465441SEvalZero rt_bool_t need_notify;
75*10465441SEvalZero struct cdc_eps eps;
76*10465441SEvalZero };
77*10465441SEvalZero typedef struct rt_rndis_eth * rt_rndis_eth_t;
78*10465441SEvalZero static rt_uint32_t oid_packet_filter = 0x0000000;
79*10465441SEvalZero
80*10465441SEvalZero ALIGN(4)
81*10465441SEvalZero static struct udevice_descriptor _dev_desc =
82*10465441SEvalZero {
83*10465441SEvalZero USB_DESC_LENGTH_DEVICE, /* bLength */
84*10465441SEvalZero USB_DESC_TYPE_DEVICE, /* type */
85*10465441SEvalZero USB_BCD_VERSION, /* bcdUSB */
86*10465441SEvalZero 0xEF, /* bDeviceClass */
87*10465441SEvalZero 0x04, /* bDeviceSubClass */
88*10465441SEvalZero 0x01, /* bDeviceProtocol */
89*10465441SEvalZero USB_CDC_BUFSIZE, /* bMaxPacketSize0 */
90*10465441SEvalZero _VENDOR_ID, /* idVendor */
91*10465441SEvalZero _PRODUCT_ID, /* idProduct */
92*10465441SEvalZero USB_BCD_DEVICE, /* bcdDevice */
93*10465441SEvalZero USB_STRING_MANU_INDEX, /* iManufacturer */
94*10465441SEvalZero USB_STRING_PRODUCT_INDEX, /* iProduct */
95*10465441SEvalZero USB_STRING_SERIAL_INDEX, /* iSerialNumber */
96*10465441SEvalZero USB_DYNAMIC /* bNumConfigurations */
97*10465441SEvalZero };
98*10465441SEvalZero
99*10465441SEvalZero /* communcation interface descriptor */
100*10465441SEvalZero ALIGN(4)
101*10465441SEvalZero const static struct ucdc_comm_descriptor _comm_desc =
102*10465441SEvalZero {
103*10465441SEvalZero #ifdef RT_USB_DEVICE_COMPOSITE
104*10465441SEvalZero /* Interface Association Descriptor */
105*10465441SEvalZero {
106*10465441SEvalZero USB_DESC_LENGTH_IAD,
107*10465441SEvalZero USB_DESC_TYPE_IAD,
108*10465441SEvalZero USB_DYNAMIC,
109*10465441SEvalZero 0x02,
110*10465441SEvalZero USB_CDC_CLASS_COMM,
111*10465441SEvalZero USB_CDC_SUBCLASS_ACM,
112*10465441SEvalZero USB_CDC_PROTOCOL_VENDOR,
113*10465441SEvalZero 0x00,
114*10465441SEvalZero },
115*10465441SEvalZero #endif
116*10465441SEvalZero /* Interface Descriptor */
117*10465441SEvalZero {
118*10465441SEvalZero USB_DESC_LENGTH_INTERFACE,
119*10465441SEvalZero USB_DESC_TYPE_INTERFACE,
120*10465441SEvalZero USB_DYNAMIC,
121*10465441SEvalZero 0x00,
122*10465441SEvalZero 0x01,
123*10465441SEvalZero USB_CDC_CLASS_COMM,
124*10465441SEvalZero USB_CDC_SUBCLASS_ACM,
125*10465441SEvalZero USB_CDC_PROTOCOL_VENDOR,
126*10465441SEvalZero 0x00,
127*10465441SEvalZero },
128*10465441SEvalZero /* Header Functional Descriptor */
129*10465441SEvalZero {
130*10465441SEvalZero 0x05,
131*10465441SEvalZero USB_CDC_CS_INTERFACE,
132*10465441SEvalZero USB_CDC_SCS_HEADER,
133*10465441SEvalZero 0x0110,
134*10465441SEvalZero },
135*10465441SEvalZero /* Call Management Functional Descriptor */
136*10465441SEvalZero {
137*10465441SEvalZero 0x05,
138*10465441SEvalZero USB_CDC_CS_INTERFACE,
139*10465441SEvalZero USB_CDC_SCS_CALL_MGMT,
140*10465441SEvalZero 0x00,
141*10465441SEvalZero USB_DYNAMIC,
142*10465441SEvalZero },
143*10465441SEvalZero /* Abstract Control Management Functional Descriptor */
144*10465441SEvalZero {
145*10465441SEvalZero 0x04,
146*10465441SEvalZero USB_CDC_CS_INTERFACE,
147*10465441SEvalZero USB_CDC_SCS_ACM,
148*10465441SEvalZero 0x02,
149*10465441SEvalZero },
150*10465441SEvalZero /* Union Functional Descriptor */
151*10465441SEvalZero {
152*10465441SEvalZero 0x05,
153*10465441SEvalZero USB_CDC_CS_INTERFACE,
154*10465441SEvalZero USB_CDC_SCS_UNION,
155*10465441SEvalZero USB_DYNAMIC,
156*10465441SEvalZero USB_DYNAMIC,
157*10465441SEvalZero },
158*10465441SEvalZero /* Endpoint Descriptor */
159*10465441SEvalZero {
160*10465441SEvalZero USB_DESC_LENGTH_ENDPOINT,
161*10465441SEvalZero USB_DESC_TYPE_ENDPOINT,
162*10465441SEvalZero USB_DIR_IN | USB_DYNAMIC,
163*10465441SEvalZero USB_EP_ATTR_INT,
164*10465441SEvalZero 0x08,
165*10465441SEvalZero 0x0A,
166*10465441SEvalZero },
167*10465441SEvalZero };
168*10465441SEvalZero
169*10465441SEvalZero /* data interface descriptor */
170*10465441SEvalZero ALIGN(4)
171*10465441SEvalZero const static struct ucdc_data_descriptor _data_desc =
172*10465441SEvalZero {
173*10465441SEvalZero /* interface descriptor */
174*10465441SEvalZero {
175*10465441SEvalZero USB_DESC_LENGTH_INTERFACE,
176*10465441SEvalZero USB_DESC_TYPE_INTERFACE,
177*10465441SEvalZero USB_DYNAMIC,
178*10465441SEvalZero 0x00,
179*10465441SEvalZero 0x02,
180*10465441SEvalZero USB_CDC_CLASS_DATA,
181*10465441SEvalZero 0x00,
182*10465441SEvalZero 0x00,
183*10465441SEvalZero 0x00,
184*10465441SEvalZero },
185*10465441SEvalZero /* endpoint, bulk out */
186*10465441SEvalZero {
187*10465441SEvalZero USB_DESC_LENGTH_ENDPOINT,
188*10465441SEvalZero USB_DESC_TYPE_ENDPOINT,
189*10465441SEvalZero USB_DIR_OUT | USB_DYNAMIC,
190*10465441SEvalZero USB_EP_ATTR_BULK,
191*10465441SEvalZero USB_DYNAMIC,
192*10465441SEvalZero 0x00,
193*10465441SEvalZero },
194*10465441SEvalZero /* endpoint, bulk in */
195*10465441SEvalZero {
196*10465441SEvalZero USB_DESC_LENGTH_ENDPOINT,
197*10465441SEvalZero USB_DESC_TYPE_ENDPOINT,
198*10465441SEvalZero USB_DYNAMIC | USB_DIR_IN,
199*10465441SEvalZero USB_EP_ATTR_BULK,
200*10465441SEvalZero USB_DYNAMIC,
201*10465441SEvalZero 0x00,
202*10465441SEvalZero },
203*10465441SEvalZero };
204*10465441SEvalZero
205*10465441SEvalZero ALIGN(4)
206*10465441SEvalZero const static char* _ustring[] =
207*10465441SEvalZero {
208*10465441SEvalZero "Language", /* LANGID */
209*10465441SEvalZero "RT-Thread Team.", /* MANU */
210*10465441SEvalZero "RT-Thread RNDIS device", /* PRODUCT */
211*10465441SEvalZero "1.1.0", /* SERIAL */
212*10465441SEvalZero "Configuration", /* CONFIG */
213*10465441SEvalZero "Interface", /* INTERFACE */
214*10465441SEvalZero USB_STRING_OS
215*10465441SEvalZero };
216*10465441SEvalZero
217*10465441SEvalZero ALIGN(4)
218*10465441SEvalZero struct usb_os_function_comp_id_descriptor rndis_func_comp_id_desc =
219*10465441SEvalZero {
220*10465441SEvalZero .bFirstInterfaceNumber = USB_DYNAMIC,
221*10465441SEvalZero .reserved1 = 0x01,
222*10465441SEvalZero .compatibleID = {'R', 'N', 'D', 'I', 'S', 0x00, 0x00, 0x00},
223*10465441SEvalZero .subCompatibleID = {'5', '1', '6', '2', '0', '0', '1', 0x00},
224*10465441SEvalZero .reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
225*10465441SEvalZero };
226*10465441SEvalZero
227*10465441SEvalZero //FS and HS needed
228*10465441SEvalZero ALIGN(4)
229*10465441SEvalZero static struct usb_qualifier_descriptor dev_qualifier =
230*10465441SEvalZero {
231*10465441SEvalZero sizeof(dev_qualifier), //bLength
232*10465441SEvalZero USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType
233*10465441SEvalZero 0x0200, //bcdUSB
234*10465441SEvalZero USB_CLASS_CDC, //bDeviceClass
235*10465441SEvalZero USB_CDC_SUBCLASS_ACM, //bDeviceSubClass
236*10465441SEvalZero USB_CDC_PROTOCOL_VENDOR, //bDeviceProtocol
237*10465441SEvalZero 64, //bMaxPacketSize0
238*10465441SEvalZero 0x01, //bNumConfigurations
239*10465441SEvalZero 0,
240*10465441SEvalZero };
241*10465441SEvalZero
242*10465441SEvalZero /* supported OIDs */
243*10465441SEvalZero ALIGN(4)
244*10465441SEvalZero const static rt_uint32_t oid_supported_list[] =
245*10465441SEvalZero {
246*10465441SEvalZero /* General OIDs */
247*10465441SEvalZero OID_GEN_SUPPORTED_LIST,
248*10465441SEvalZero OID_GEN_HARDWARE_STATUS,
249*10465441SEvalZero OID_GEN_MEDIA_SUPPORTED,
250*10465441SEvalZero OID_GEN_MEDIA_IN_USE,
251*10465441SEvalZero OID_GEN_MAXIMUM_FRAME_SIZE,
252*10465441SEvalZero OID_GEN_LINK_SPEED,
253*10465441SEvalZero OID_GEN_TRANSMIT_BLOCK_SIZE,
254*10465441SEvalZero OID_GEN_RECEIVE_BLOCK_SIZE,
255*10465441SEvalZero OID_GEN_VENDOR_ID,
256*10465441SEvalZero OID_GEN_VENDOR_DESCRIPTION,
257*10465441SEvalZero OID_GEN_VENDOR_DRIVER_VERSION,
258*10465441SEvalZero OID_GEN_CURRENT_PACKET_FILTER,
259*10465441SEvalZero OID_GEN_MAXIMUM_TOTAL_SIZE,
260*10465441SEvalZero OID_GEN_MEDIA_CONNECT_STATUS,
261*10465441SEvalZero
262*10465441SEvalZero OID_GEN_PHYSICAL_MEDIUM,
263*10465441SEvalZero
264*10465441SEvalZero /* General Statistic OIDs */
265*10465441SEvalZero OID_GEN_XMIT_OK,
266*10465441SEvalZero OID_GEN_RCV_OK,
267*10465441SEvalZero OID_GEN_XMIT_ERROR,
268*10465441SEvalZero OID_GEN_RCV_ERROR,
269*10465441SEvalZero OID_GEN_RCV_NO_BUFFER,
270*10465441SEvalZero
271*10465441SEvalZero /* Please configure us */
272*10465441SEvalZero OID_GEN_RNDIS_CONFIG_PARAMETER,
273*10465441SEvalZero
274*10465441SEvalZero /* 802.3 OIDs */
275*10465441SEvalZero OID_802_3_PERMANENT_ADDRESS,
276*10465441SEvalZero OID_802_3_CURRENT_ADDRESS,
277*10465441SEvalZero OID_802_3_MULTICAST_LIST,
278*10465441SEvalZero OID_802_3_MAXIMUM_LIST_SIZE,
279*10465441SEvalZero
280*10465441SEvalZero /* 802.3 Statistic OIDs */
281*10465441SEvalZero OID_802_3_RCV_ERROR_ALIGNMENT,
282*10465441SEvalZero OID_802_3_XMIT_ONE_COLLISION,
283*10465441SEvalZero OID_802_3_XMIT_MORE_COLLISIONS,
284*10465441SEvalZero
285*10465441SEvalZero OID_802_3_MAC_OPTIONS,
286*10465441SEvalZero };
287*10465441SEvalZero
288*10465441SEvalZero static rt_uint8_t rndis_message_buffer[RNDIS_MESSAGE_BUFFER_SIZE];
289*10465441SEvalZero
_rndis_response_available(ufunction_t func)290*10465441SEvalZero static void _rndis_response_available(ufunction_t func)
291*10465441SEvalZero {
292*10465441SEvalZero rt_rndis_eth_t device = (rt_rndis_eth_t)func->user_data;
293*10465441SEvalZero rt_uint32_t * data;
294*10465441SEvalZero if(device->need_notify == RT_TRUE)
295*10465441SEvalZero {
296*10465441SEvalZero device->need_notify = RT_FALSE;
297*10465441SEvalZero data = (rt_uint32_t *)device->eps.ep_cmd->buffer;
298*10465441SEvalZero data[0] = RESPONSE_AVAILABLE;
299*10465441SEvalZero data[1] = 0;
300*10465441SEvalZero device->eps.ep_cmd->request.buffer = device->eps.ep_cmd->buffer;
301*10465441SEvalZero device->eps.ep_cmd->request.size = 8;
302*10465441SEvalZero device->eps.ep_cmd->request.req_type = UIO_REQUEST_WRITE;
303*10465441SEvalZero rt_usbd_io_request(func->device, device->eps.ep_cmd, &device->eps.ep_cmd->request);
304*10465441SEvalZero }
305*10465441SEvalZero }
306*10465441SEvalZero
_rndis_init_response(ufunction_t func,rndis_init_msg_t msg)307*10465441SEvalZero static rt_err_t _rndis_init_response(ufunction_t func, rndis_init_msg_t msg)
308*10465441SEvalZero {
309*10465441SEvalZero rndis_init_cmplt_t resp;
310*10465441SEvalZero struct rt_rndis_response * response;
311*10465441SEvalZero
312*10465441SEvalZero response = rt_malloc(sizeof(struct rt_rndis_response));
313*10465441SEvalZero resp = rt_malloc(sizeof(struct rndis_init_cmplt));
314*10465441SEvalZero
315*10465441SEvalZero if( (response == RT_NULL) || (resp == RT_NULL) )
316*10465441SEvalZero {
317*10465441SEvalZero RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
318*10465441SEvalZero
319*10465441SEvalZero if(response != RT_NULL)
320*10465441SEvalZero rt_free(response);
321*10465441SEvalZero
322*10465441SEvalZero if(resp != RT_NULL)
323*10465441SEvalZero rt_free(resp);
324*10465441SEvalZero
325*10465441SEvalZero return -RT_ENOMEM;
326*10465441SEvalZero }
327*10465441SEvalZero
328*10465441SEvalZero resp->RequestId = msg->RequestId;
329*10465441SEvalZero resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
330*10465441SEvalZero resp->MessageLength = sizeof(struct rndis_init_cmplt);
331*10465441SEvalZero resp->MajorVersion = RNDIS_MAJOR_VERSION;
332*10465441SEvalZero resp->MinorVersion = RNDIS_MAJOR_VERSION;
333*10465441SEvalZero resp->Status = RNDIS_STATUS_SUCCESS;
334*10465441SEvalZero resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
335*10465441SEvalZero resp->Medium = RNDIS_MEDIUM_802_3;
336*10465441SEvalZero resp->MaxPacketsPerTransfer = 1;
337*10465441SEvalZero resp->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header,
338*10465441SEvalZero RNDIS messages */
339*10465441SEvalZero resp->PacketAlignmentFactor = 3;
340*10465441SEvalZero resp->AfListOffset = 0;
341*10465441SEvalZero resp->AfListSize = 0;
342*10465441SEvalZero
343*10465441SEvalZero response->buffer = resp;
344*10465441SEvalZero
345*10465441SEvalZero {
346*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
347*10465441SEvalZero rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
348*10465441SEvalZero rt_hw_interrupt_enable(level);
349*10465441SEvalZero }
350*10465441SEvalZero
351*10465441SEvalZero
352*10465441SEvalZero return RT_EOK;
353*10465441SEvalZero }
354*10465441SEvalZero
_create_resp(rt_size_t size)355*10465441SEvalZero static rndis_query_cmplt_t _create_resp(rt_size_t size)
356*10465441SEvalZero {
357*10465441SEvalZero rndis_query_cmplt_t resp;
358*10465441SEvalZero
359*10465441SEvalZero resp = rt_malloc(sizeof(struct rndis_query_cmplt) + size);
360*10465441SEvalZero
361*10465441SEvalZero if(resp == RT_NULL)
362*10465441SEvalZero {
363*10465441SEvalZero RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
364*10465441SEvalZero return RT_NULL;
365*10465441SEvalZero }
366*10465441SEvalZero
367*10465441SEvalZero resp->InformationBufferLength = size;
368*10465441SEvalZero
369*10465441SEvalZero return resp;
370*10465441SEvalZero }
371*10465441SEvalZero
_copy_resp(rndis_query_cmplt_t resp,const void * buffer)372*10465441SEvalZero static void _copy_resp(rndis_query_cmplt_t resp, const void * buffer)
373*10465441SEvalZero {
374*10465441SEvalZero char * resp_buffer = (char *)resp + sizeof(struct rndis_query_cmplt);
375*10465441SEvalZero memcpy(resp_buffer, buffer, resp->InformationBufferLength);
376*10465441SEvalZero }
377*10465441SEvalZero
_set_resp(rndis_query_cmplt_t resp,rt_uint32_t value)378*10465441SEvalZero static void _set_resp(rndis_query_cmplt_t resp, rt_uint32_t value)
379*10465441SEvalZero {
380*10465441SEvalZero rt_uint32_t * response = (rt_uint32_t *)((char *)resp + sizeof(struct rndis_query_cmplt));
381*10465441SEvalZero *response = value;
382*10465441SEvalZero }
383*10465441SEvalZero
_rndis_query_response(ufunction_t func,rndis_query_msg_t msg)384*10465441SEvalZero static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg)
385*10465441SEvalZero {
386*10465441SEvalZero rndis_query_cmplt_t resp = RT_NULL;
387*10465441SEvalZero struct rt_rndis_response * response;
388*10465441SEvalZero rt_err_t ret = RT_EOK;
389*10465441SEvalZero
390*10465441SEvalZero switch (msg->Oid)
391*10465441SEvalZero {
392*10465441SEvalZero /*
393*10465441SEvalZero * general OIDs
394*10465441SEvalZero */
395*10465441SEvalZero case OID_GEN_SUPPORTED_LIST:
396*10465441SEvalZero resp = _create_resp(sizeof(oid_supported_list));
397*10465441SEvalZero if(resp == RT_NULL) break;
398*10465441SEvalZero _copy_resp(resp, oid_supported_list);
399*10465441SEvalZero break;
400*10465441SEvalZero
401*10465441SEvalZero case OID_GEN_PHYSICAL_MEDIUM:
402*10465441SEvalZero resp = _create_resp(4);
403*10465441SEvalZero if(resp == RT_NULL) break;
404*10465441SEvalZero _set_resp(resp, NDIS_MEDIUM_802_3);
405*10465441SEvalZero break;
406*10465441SEvalZero
407*10465441SEvalZero case OID_GEN_MAXIMUM_FRAME_SIZE:
408*10465441SEvalZero case OID_GEN_TRANSMIT_BLOCK_SIZE:
409*10465441SEvalZero case OID_GEN_RECEIVE_BLOCK_SIZE:
410*10465441SEvalZero resp = _create_resp(4);
411*10465441SEvalZero if(resp == RT_NULL) break;
412*10465441SEvalZero _set_resp(resp, USB_ETH_MTU);
413*10465441SEvalZero break;
414*10465441SEvalZero
415*10465441SEvalZero case OID_GEN_MAXIMUM_TOTAL_SIZE:
416*10465441SEvalZero resp = _create_resp(4);
417*10465441SEvalZero if(resp == RT_NULL) break;
418*10465441SEvalZero _set_resp(resp, USB_ETH_MTU + RNDIS_MESSAGE_BUFFER_SIZE);
419*10465441SEvalZero break;
420*10465441SEvalZero
421*10465441SEvalZero case OID_GEN_LINK_SPEED:
422*10465441SEvalZero resp = _create_resp(4);
423*10465441SEvalZero if(resp == RT_NULL) break;
424*10465441SEvalZero _set_resp(resp, func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000) / 100);
425*10465441SEvalZero break;
426*10465441SEvalZero
427*10465441SEvalZero case OID_GEN_MEDIA_CONNECT_STATUS:
428*10465441SEvalZero /* link_status */
429*10465441SEvalZero resp = _create_resp(4);
430*10465441SEvalZero if(resp == RT_NULL) break;
431*10465441SEvalZero
432*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
433*10465441SEvalZero if(((rt_rndis_eth_t)func->user_data)->parent.link_status)
434*10465441SEvalZero {
435*10465441SEvalZero _set_resp(resp, NDIS_MEDIA_STATE_CONNECTED);
436*10465441SEvalZero }
437*10465441SEvalZero else
438*10465441SEvalZero {
439*10465441SEvalZero _set_resp(resp, NDIS_MEDIA_STATE_DISCONNECTED);
440*10465441SEvalZero }
441*10465441SEvalZero #else
442*10465441SEvalZero _set_resp(resp, NDIS_MEDIA_STATE_CONNECTED);
443*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
444*10465441SEvalZero break;
445*10465441SEvalZero
446*10465441SEvalZero case OID_GEN_VENDOR_ID:
447*10465441SEvalZero resp = _create_resp(4);
448*10465441SEvalZero if(resp == RT_NULL) break;
449*10465441SEvalZero _set_resp(resp, 0x12345678); /* only for test */
450*10465441SEvalZero break;
451*10465441SEvalZero
452*10465441SEvalZero case OID_GEN_VENDOR_DESCRIPTION:
453*10465441SEvalZero {
454*10465441SEvalZero const char vendor_desc[] = "RT-Thread RNDIS";
455*10465441SEvalZero
456*10465441SEvalZero resp = _create_resp(sizeof(vendor_desc));
457*10465441SEvalZero if(resp == RT_NULL) break;
458*10465441SEvalZero _copy_resp(resp, vendor_desc);
459*10465441SEvalZero }
460*10465441SEvalZero break;
461*10465441SEvalZero
462*10465441SEvalZero case OID_GEN_VENDOR_DRIVER_VERSION:
463*10465441SEvalZero resp = _create_resp(4);
464*10465441SEvalZero if(resp == RT_NULL) break;
465*10465441SEvalZero _set_resp(resp, 0x0000200);
466*10465441SEvalZero break;
467*10465441SEvalZero
468*10465441SEvalZero /* statistics OIDs */
469*10465441SEvalZero case OID_GEN_XMIT_OK:
470*10465441SEvalZero case OID_GEN_RCV_OK:
471*10465441SEvalZero resp = _create_resp(4);
472*10465441SEvalZero if(resp == RT_NULL) break;
473*10465441SEvalZero _set_resp(resp, 1);
474*10465441SEvalZero break;
475*10465441SEvalZero
476*10465441SEvalZero case OID_GEN_XMIT_ERROR:
477*10465441SEvalZero case OID_GEN_RCV_ERROR:
478*10465441SEvalZero case OID_GEN_RCV_NO_BUFFER:
479*10465441SEvalZero resp = _create_resp(4);
480*10465441SEvalZero if(resp == RT_NULL) break;
481*10465441SEvalZero _set_resp(resp, 0);
482*10465441SEvalZero break;
483*10465441SEvalZero
484*10465441SEvalZero /*
485*10465441SEvalZero * ieee802.3 OIDs
486*10465441SEvalZero */
487*10465441SEvalZero case OID_802_3_MAXIMUM_LIST_SIZE:
488*10465441SEvalZero resp = _create_resp(4);
489*10465441SEvalZero if(resp == RT_NULL) break;
490*10465441SEvalZero _set_resp(resp, 1);
491*10465441SEvalZero break;
492*10465441SEvalZero
493*10465441SEvalZero case OID_802_3_PERMANENT_ADDRESS:
494*10465441SEvalZero case OID_802_3_CURRENT_ADDRESS:
495*10465441SEvalZero resp = _create_resp(sizeof(((rt_rndis_eth_t)func->user_data)->host_addr));
496*10465441SEvalZero if(resp == RT_NULL) break;
497*10465441SEvalZero _copy_resp(resp, ((rt_rndis_eth_t)func->user_data)->host_addr);
498*10465441SEvalZero break;
499*10465441SEvalZero
500*10465441SEvalZero case OID_802_3_MULTICAST_LIST:
501*10465441SEvalZero resp = _create_resp(4);
502*10465441SEvalZero if(resp == RT_NULL) break;
503*10465441SEvalZero _set_resp(resp, 0xE000000);
504*10465441SEvalZero break;
505*10465441SEvalZero
506*10465441SEvalZero case OID_802_3_MAC_OPTIONS:
507*10465441SEvalZero resp = _create_resp(4);
508*10465441SEvalZero if(resp == RT_NULL) break;
509*10465441SEvalZero _set_resp(resp, 0);
510*10465441SEvalZero break;
511*10465441SEvalZero
512*10465441SEvalZero default:
513*10465441SEvalZero RNDIS_PRINTF("OID %X\n", msg->Oid);
514*10465441SEvalZero ret = -RT_ERROR;
515*10465441SEvalZero break;
516*10465441SEvalZero }
517*10465441SEvalZero
518*10465441SEvalZero response = rt_malloc(sizeof(struct rt_rndis_response));
519*10465441SEvalZero if( (response == RT_NULL) || (resp == RT_NULL) )
520*10465441SEvalZero {
521*10465441SEvalZero RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
522*10465441SEvalZero
523*10465441SEvalZero if(response != RT_NULL)
524*10465441SEvalZero rt_free(response);
525*10465441SEvalZero
526*10465441SEvalZero if(resp != RT_NULL)
527*10465441SEvalZero rt_free(resp);
528*10465441SEvalZero
529*10465441SEvalZero return -RT_ENOMEM;
530*10465441SEvalZero }
531*10465441SEvalZero
532*10465441SEvalZero resp->RequestId = msg->RequestId;
533*10465441SEvalZero resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
534*10465441SEvalZero resp->InformationBufferOffset = 16;
535*10465441SEvalZero
536*10465441SEvalZero resp->Status = RNDIS_STATUS_SUCCESS;
537*10465441SEvalZero resp->MessageLength = sizeof(struct rndis_query_cmplt) + resp->InformationBufferLength;
538*10465441SEvalZero
539*10465441SEvalZero response->buffer = resp;
540*10465441SEvalZero
541*10465441SEvalZero {
542*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
543*10465441SEvalZero rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
544*10465441SEvalZero rt_hw_interrupt_enable(level);
545*10465441SEvalZero }
546*10465441SEvalZero
547*10465441SEvalZero return ret;
548*10465441SEvalZero }
549*10465441SEvalZero
_rndis_set_response(ufunction_t func,rndis_set_msg_t msg)550*10465441SEvalZero static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg)
551*10465441SEvalZero {
552*10465441SEvalZero rndis_set_cmplt_t resp;
553*10465441SEvalZero struct rt_rndis_response * response;
554*10465441SEvalZero
555*10465441SEvalZero response = rt_malloc(sizeof(struct rt_rndis_response));
556*10465441SEvalZero resp = rt_malloc(sizeof(struct rndis_set_cmplt));
557*10465441SEvalZero
558*10465441SEvalZero if( (response == RT_NULL) || (resp == RT_NULL) )
559*10465441SEvalZero {
560*10465441SEvalZero RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
561*10465441SEvalZero
562*10465441SEvalZero if(response != RT_NULL)
563*10465441SEvalZero rt_free(response);
564*10465441SEvalZero
565*10465441SEvalZero if(resp != RT_NULL)
566*10465441SEvalZero rt_free(resp);
567*10465441SEvalZero
568*10465441SEvalZero return -RT_ENOMEM;
569*10465441SEvalZero }
570*10465441SEvalZero
571*10465441SEvalZero resp->RequestId = msg->RequestId;
572*10465441SEvalZero resp->MessageType = REMOTE_NDIS_SET_CMPLT;
573*10465441SEvalZero resp->MessageLength = sizeof(struct rndis_set_cmplt);
574*10465441SEvalZero
575*10465441SEvalZero switch (msg->Oid)
576*10465441SEvalZero {
577*10465441SEvalZero case OID_GEN_CURRENT_PACKET_FILTER:
578*10465441SEvalZero oid_packet_filter = *((rt_uint32_t *)((rt_uint8_t *)&(msg->RequestId) + \
579*10465441SEvalZero msg->InformationBufferOffset));
580*10465441SEvalZero oid_packet_filter = oid_packet_filter;
581*10465441SEvalZero RNDIS_PRINTF("OID_GEN_CURRENT_PACKET_FILTER\r\n");
582*10465441SEvalZero
583*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
584*10465441SEvalZero /* link up. */
585*10465441SEvalZero rt_timer_start(&((rt_rndis_eth_t)func->user_data)->timer);
586*10465441SEvalZero #else
587*10465441SEvalZero eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_TRUE);
588*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
589*10465441SEvalZero break;
590*10465441SEvalZero
591*10465441SEvalZero case OID_802_3_MULTICAST_LIST:
592*10465441SEvalZero break;
593*10465441SEvalZero
594*10465441SEvalZero default:
595*10465441SEvalZero resp->Status = RNDIS_STATUS_FAILURE;
596*10465441SEvalZero return RT_EOK;
597*10465441SEvalZero }
598*10465441SEvalZero
599*10465441SEvalZero resp->Status = RNDIS_STATUS_SUCCESS;
600*10465441SEvalZero
601*10465441SEvalZero response->buffer = resp;
602*10465441SEvalZero
603*10465441SEvalZero {
604*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
605*10465441SEvalZero rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
606*10465441SEvalZero rt_hw_interrupt_enable(level);
607*10465441SEvalZero }
608*10465441SEvalZero
609*10465441SEvalZero return RT_EOK;
610*10465441SEvalZero }
611*10465441SEvalZero
_rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg)612*10465441SEvalZero static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg)
613*10465441SEvalZero {
614*10465441SEvalZero rndis_keepalive_cmplt_t resp;
615*10465441SEvalZero struct rt_rndis_response * response;
616*10465441SEvalZero
617*10465441SEvalZero response = rt_malloc(sizeof(struct rt_rndis_response));
618*10465441SEvalZero resp = rt_malloc(sizeof(struct rndis_keepalive_cmplt));
619*10465441SEvalZero
620*10465441SEvalZero if( (response == RT_NULL) || (resp == RT_NULL) )
621*10465441SEvalZero {
622*10465441SEvalZero RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
623*10465441SEvalZero
624*10465441SEvalZero if(response != RT_NULL)
625*10465441SEvalZero rt_free(response);
626*10465441SEvalZero
627*10465441SEvalZero if(resp != RT_NULL)
628*10465441SEvalZero rt_free(resp);
629*10465441SEvalZero
630*10465441SEvalZero return -RT_ENOMEM;
631*10465441SEvalZero }
632*10465441SEvalZero
633*10465441SEvalZero resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
634*10465441SEvalZero resp->MessageLength = sizeof(struct rndis_keepalive_cmplt);
635*10465441SEvalZero resp->Status = RNDIS_STATUS_SUCCESS;
636*10465441SEvalZero
637*10465441SEvalZero response->buffer = resp;
638*10465441SEvalZero
639*10465441SEvalZero {
640*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
641*10465441SEvalZero rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
642*10465441SEvalZero rt_hw_interrupt_enable(level);
643*10465441SEvalZero }
644*10465441SEvalZero
645*10465441SEvalZero return RT_EOK;
646*10465441SEvalZero }
647*10465441SEvalZero
_rndis_msg_parser(ufunction_t func,rt_uint8_t * msg)648*10465441SEvalZero static rt_err_t _rndis_msg_parser(ufunction_t func, rt_uint8_t *msg)
649*10465441SEvalZero {
650*10465441SEvalZero rt_err_t ret = -RT_ERROR;
651*10465441SEvalZero
652*10465441SEvalZero switch (((rndis_gen_msg_t) msg)->MessageType)
653*10465441SEvalZero {
654*10465441SEvalZero case REMOTE_NDIS_INITIALIZE_MSG:
655*10465441SEvalZero ret = _rndis_init_response(func, (rndis_init_msg_t) msg);
656*10465441SEvalZero break;
657*10465441SEvalZero
658*10465441SEvalZero case REMOTE_NDIS_HALT_MSG:
659*10465441SEvalZero RNDIS_PRINTF("halt\n");
660*10465441SEvalZero /* link down. */
661*10465441SEvalZero eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE);
662*10465441SEvalZero break;
663*10465441SEvalZero
664*10465441SEvalZero case REMOTE_NDIS_QUERY_MSG:
665*10465441SEvalZero ret = _rndis_query_response(func,(rndis_query_msg_t) msg);
666*10465441SEvalZero break;
667*10465441SEvalZero
668*10465441SEvalZero case REMOTE_NDIS_SET_MSG:
669*10465441SEvalZero ret = _rndis_set_response(func,(rndis_set_msg_t) msg);
670*10465441SEvalZero RNDIS_PRINTF("set\n");
671*10465441SEvalZero break;
672*10465441SEvalZero
673*10465441SEvalZero case REMOTE_NDIS_RESET_MSG:
674*10465441SEvalZero RNDIS_PRINTF("reset\n");
675*10465441SEvalZero break;
676*10465441SEvalZero
677*10465441SEvalZero case REMOTE_NDIS_KEEPALIVE_MSG:
678*10465441SEvalZero ret = _rndis_keepalive_response(func,(rndis_keepalive_msg_t) msg);
679*10465441SEvalZero break;
680*10465441SEvalZero
681*10465441SEvalZero default:
682*10465441SEvalZero RNDIS_PRINTF("msg %X\n", ((rndis_gen_msg_t) msg)->MessageType);
683*10465441SEvalZero ret = -RT_ERROR;
684*10465441SEvalZero break;
685*10465441SEvalZero }
686*10465441SEvalZero
687*10465441SEvalZero if (ret == RT_EOK)
688*10465441SEvalZero _rndis_response_available(func);
689*10465441SEvalZero
690*10465441SEvalZero return ret;
691*10465441SEvalZero }
692*10465441SEvalZero
693*10465441SEvalZero static ufunction_t function = RT_NULL;
send_encapsulated_command_done(udevice_t device,rt_size_t size)694*10465441SEvalZero static rt_err_t send_encapsulated_command_done(udevice_t device, rt_size_t size)
695*10465441SEvalZero {
696*10465441SEvalZero if(function != RT_NULL)
697*10465441SEvalZero {
698*10465441SEvalZero dcd_ep0_send_status(device->dcd);
699*10465441SEvalZero _rndis_msg_parser(function, rndis_message_buffer);
700*10465441SEvalZero function = RT_NULL;
701*10465441SEvalZero }
702*10465441SEvalZero return RT_EOK;
703*10465441SEvalZero }
704*10465441SEvalZero //#error here have bug ep 0x82 send failed
_rndis_send_encapsulated_command(ufunction_t func,ureq_t setup)705*10465441SEvalZero static rt_err_t _rndis_send_encapsulated_command(ufunction_t func, ureq_t setup)
706*10465441SEvalZero {
707*10465441SEvalZero RT_ASSERT(setup->wLength <= sizeof(rndis_message_buffer));
708*10465441SEvalZero function = func;
709*10465441SEvalZero rt_usbd_ep0_read(func->device,rndis_message_buffer,setup->wLength,send_encapsulated_command_done);
710*10465441SEvalZero
711*10465441SEvalZero return RT_EOK;
712*10465441SEvalZero }
713*10465441SEvalZero
_rndis_get_encapsulated_response(ufunction_t func,ureq_t setup)714*10465441SEvalZero static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup)
715*10465441SEvalZero {
716*10465441SEvalZero rndis_gen_msg_t msg;
717*10465441SEvalZero struct rt_rndis_response * response;
718*10465441SEvalZero
719*10465441SEvalZero if(rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
720*10465441SEvalZero {
721*10465441SEvalZero RNDIS_PRINTF("response_list is empty!\r\n");
722*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
723*10465441SEvalZero return RT_EOK;
724*10465441SEvalZero }
725*10465441SEvalZero
726*10465441SEvalZero response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next;
727*10465441SEvalZero
728*10465441SEvalZero msg = (rndis_gen_msg_t)response->buffer;
729*10465441SEvalZero rt_usbd_ep0_write(func->device, (void*)msg, msg->MessageLength);
730*10465441SEvalZero
731*10465441SEvalZero {
732*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
733*10465441SEvalZero rt_list_remove(&response->list);
734*10465441SEvalZero rt_hw_interrupt_enable(level);
735*10465441SEvalZero }
736*10465441SEvalZero
737*10465441SEvalZero rt_free((void *)response->buffer);
738*10465441SEvalZero rt_free(response);
739*10465441SEvalZero
740*10465441SEvalZero if(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
741*10465441SEvalZero {
742*10465441SEvalZero rt_uint32_t * data;
743*10465441SEvalZero
744*10465441SEvalZero RNDIS_PRINTF("auto append next response!\r\n");
745*10465441SEvalZero data = (rt_uint32_t *)((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer;
746*10465441SEvalZero data[0] = RESPONSE_AVAILABLE;
747*10465441SEvalZero data[1] = 0;
748*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request.buffer = ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer;
749*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request.size = 8;
750*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request.req_type = UIO_REQUEST_WRITE;
751*10465441SEvalZero rt_usbd_io_request(func->device, ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd, &((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request);
752*10465441SEvalZero }
753*10465441SEvalZero else
754*10465441SEvalZero {
755*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
756*10465441SEvalZero }
757*10465441SEvalZero
758*10465441SEvalZero return RT_EOK;
759*10465441SEvalZero }
760*10465441SEvalZero
761*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
762*10465441SEvalZero /**
763*10465441SEvalZero * This function will set rndis connect status.
764*10465441SEvalZero *
765*10465441SEvalZero * @param device the usb device object.
766*10465441SEvalZero * @param status the connect status.
767*10465441SEvalZero *
768*10465441SEvalZero * @return RT_EOK on successful.
769*10465441SEvalZero */
_rndis_indicate_status_msg(ufunction_t func,rt_uint32_t status)770*10465441SEvalZero static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status)
771*10465441SEvalZero {
772*10465441SEvalZero rndis_indicate_status_msg_t resp;
773*10465441SEvalZero struct rt_rndis_response * response;
774*10465441SEvalZero
775*10465441SEvalZero response = rt_malloc(sizeof(struct rt_rndis_response));
776*10465441SEvalZero resp = rt_malloc(sizeof(struct rndis_indicate_status_msg));
777*10465441SEvalZero
778*10465441SEvalZero if( (response == RT_NULL) || (resp == RT_NULL) )
779*10465441SEvalZero {
780*10465441SEvalZero RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
781*10465441SEvalZero
782*10465441SEvalZero if(response != RT_NULL)
783*10465441SEvalZero rt_free(response);
784*10465441SEvalZero
785*10465441SEvalZero if(resp != RT_NULL)
786*10465441SEvalZero rt_free(resp);
787*10465441SEvalZero
788*10465441SEvalZero return -RT_ENOMEM;
789*10465441SEvalZero }
790*10465441SEvalZero
791*10465441SEvalZero resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
792*10465441SEvalZero resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */
793*10465441SEvalZero resp->Status = status;
794*10465441SEvalZero resp->StatusBufferLength = 0;
795*10465441SEvalZero resp->StatusBufferOffset = 0;
796*10465441SEvalZero
797*10465441SEvalZero response->buffer = resp;
798*10465441SEvalZero {
799*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
800*10465441SEvalZero rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
801*10465441SEvalZero rt_hw_interrupt_enable(level);
802*10465441SEvalZero }
803*10465441SEvalZero
804*10465441SEvalZero _rndis_response_available(func);
805*10465441SEvalZero
806*10465441SEvalZero return RT_EOK;
807*10465441SEvalZero }
808*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
809*10465441SEvalZero
810*10465441SEvalZero /**
811*10465441SEvalZero * This function will handle rndis interface request.
812*10465441SEvalZero *
813*10465441SEvalZero * @param device the usb device object.
814*10465441SEvalZero * @param setup the setup request.
815*10465441SEvalZero *
816*10465441SEvalZero * @return RT_EOK on successful.
817*10465441SEvalZero */
_interface_handler(ufunction_t func,ureq_t setup)818*10465441SEvalZero static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
819*10465441SEvalZero {
820*10465441SEvalZero RT_ASSERT(func != RT_NULL);
821*10465441SEvalZero RT_ASSERT(setup != RT_NULL);
822*10465441SEvalZero
823*10465441SEvalZero switch(setup->bRequest)
824*10465441SEvalZero {
825*10465441SEvalZero case CDC_SEND_ENCAPSULATED_COMMAND:
826*10465441SEvalZero _rndis_send_encapsulated_command(func, setup);
827*10465441SEvalZero break;
828*10465441SEvalZero
829*10465441SEvalZero case CDC_GET_ENCAPSULATED_RESPONSE:
830*10465441SEvalZero _rndis_get_encapsulated_response(func, setup);
831*10465441SEvalZero break;
832*10465441SEvalZero
833*10465441SEvalZero default:
834*10465441SEvalZero RNDIS_PRINTF("unkown setup->request!\r\n");
835*10465441SEvalZero break;
836*10465441SEvalZero }
837*10465441SEvalZero
838*10465441SEvalZero return RT_EOK;
839*10465441SEvalZero }
840*10465441SEvalZero
841*10465441SEvalZero /**
842*10465441SEvalZero * This function will handle rndis bulk in endpoint request.
843*10465441SEvalZero *
844*10465441SEvalZero * @param device the usb device object.
845*10465441SEvalZero * @param size request size.
846*10465441SEvalZero *
847*10465441SEvalZero * @return RT_EOK.
848*10465441SEvalZero */
849*10465441SEvalZero
_ep_in_handler(ufunction_t func,rt_size_t size)850*10465441SEvalZero static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
851*10465441SEvalZero {
852*10465441SEvalZero rt_sem_release(&((rt_rndis_eth_t)func->user_data)->tx_buffer_free);
853*10465441SEvalZero return RT_EOK;
854*10465441SEvalZero }
855*10465441SEvalZero
856*10465441SEvalZero /**
857*10465441SEvalZero * This function will handle RNDIS bulk out endpoint request.
858*10465441SEvalZero *
859*10465441SEvalZero * @param device the usb device object.
860*10465441SEvalZero * @param size request size.
861*10465441SEvalZero *
862*10465441SEvalZero * @return RT_EOK.
863*10465441SEvalZero */
_ep_out_handler(ufunction_t func,rt_size_t size)864*10465441SEvalZero static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
865*10465441SEvalZero {
866*10465441SEvalZero cdc_eps_t eps;
867*10465441SEvalZero char* data = RT_NULL;
868*10465441SEvalZero
869*10465441SEvalZero eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps;
870*10465441SEvalZero data = (char*)eps->ep_out->buffer;
871*10465441SEvalZero
872*10465441SEvalZero if(((rt_rndis_eth_t)func->user_data)->rx_frist == RT_TRUE)
873*10465441SEvalZero {
874*10465441SEvalZero rndis_packet_msg_t msg = (rndis_packet_msg_t)data;
875*10465441SEvalZero
876*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_length = msg->DataLength;
877*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_offset = 0;
878*10465441SEvalZero
879*10465441SEvalZero if (size >= 44)
880*10465441SEvalZero {
881*10465441SEvalZero data += sizeof(struct rndis_packet_msg);
882*10465441SEvalZero size -= sizeof(struct rndis_packet_msg);
883*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_FALSE;
884*10465441SEvalZero memcpy(&((rt_rndis_eth_t)func->user_data)->rx_buffer[((rt_rndis_eth_t)func->user_data)->rx_offset], data, size);
885*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_offset += size;
886*10465441SEvalZero }
887*10465441SEvalZero }
888*10465441SEvalZero else
889*10465441SEvalZero {
890*10465441SEvalZero memcpy(&((rt_rndis_eth_t)func->user_data)->rx_buffer[((rt_rndis_eth_t)func->user_data)->rx_offset], data, size);
891*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_offset += size;
892*10465441SEvalZero }
893*10465441SEvalZero
894*10465441SEvalZero if(((rt_rndis_eth_t)func->user_data)->rx_offset >= ((rt_rndis_eth_t)func->user_data)->rx_length)
895*10465441SEvalZero {
896*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE;
897*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_TRUE;
898*10465441SEvalZero eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent));
899*10465441SEvalZero }
900*10465441SEvalZero else
901*10465441SEvalZero {
902*10465441SEvalZero eps->ep_out->request.buffer = eps->ep_out->buffer;
903*10465441SEvalZero eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out);
904*10465441SEvalZero eps->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
905*10465441SEvalZero rt_usbd_io_request(func->device, eps->ep_out, &eps->ep_out->request);
906*10465441SEvalZero }
907*10465441SEvalZero
908*10465441SEvalZero return RT_EOK;
909*10465441SEvalZero }
910*10465441SEvalZero
911*10465441SEvalZero /**
912*10465441SEvalZero * This function will handle RNDIS interrupt in endpoint request.
913*10465441SEvalZero *
914*10465441SEvalZero * @param device the usb device object.
915*10465441SEvalZero * @param size request size.
916*10465441SEvalZero *
917*10465441SEvalZero * @return RT_EOK.
918*10465441SEvalZero */
_ep_cmd_handler(ufunction_t func,rt_size_t size)919*10465441SEvalZero static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
920*10465441SEvalZero {
921*10465441SEvalZero // _rndis_response_available(func);
922*10465441SEvalZero return RT_EOK;
923*10465441SEvalZero }
924*10465441SEvalZero
925*10465441SEvalZero /**
926*10465441SEvalZero * This function will run cdc class, it will be called on handle set configuration request.
927*10465441SEvalZero *
928*10465441SEvalZero * @param device the usb device object.
929*10465441SEvalZero *
930*10465441SEvalZero * @return RT_EOK on successful.
931*10465441SEvalZero */
_function_enable(ufunction_t func)932*10465441SEvalZero static rt_err_t _function_enable(ufunction_t func)
933*10465441SEvalZero {
934*10465441SEvalZero cdc_eps_t eps;
935*10465441SEvalZero
936*10465441SEvalZero eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps;
937*10465441SEvalZero eps->ep_in->buffer = ((rt_rndis_eth_t)func->user_data)->tx_pool;
938*10465441SEvalZero eps->ep_out->buffer = ((rt_rndis_eth_t)func->user_data)->rx_pool;
939*10465441SEvalZero eps->ep_cmd->buffer = (rt_uint8_t*)((rt_rndis_eth_t)func->user_data)->cmd_pool;
940*10465441SEvalZero
941*10465441SEvalZero eps->ep_out->request.buffer = eps->ep_out->buffer;
942*10465441SEvalZero eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out);
943*10465441SEvalZero eps->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
944*10465441SEvalZero rt_usbd_io_request(func->device, eps->ep_out, &eps->ep_out->request);
945*10465441SEvalZero
946*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE;
947*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE;
948*10465441SEvalZero
949*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
950*10465441SEvalZero /* stop link up timer. */
951*10465441SEvalZero rt_timer_stop(&((rt_rndis_eth_t)func->user_data)->timer);
952*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
953*10465441SEvalZero
954*10465441SEvalZero /* clean resp chain list. */
955*10465441SEvalZero {
956*10465441SEvalZero struct rt_rndis_response * response;
957*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
958*10465441SEvalZero
959*10465441SEvalZero while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
960*10465441SEvalZero {
961*10465441SEvalZero response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next;
962*10465441SEvalZero
963*10465441SEvalZero rt_list_remove(&response->list);
964*10465441SEvalZero rt_free((void *)response->buffer);
965*10465441SEvalZero rt_free(response);
966*10465441SEvalZero }
967*10465441SEvalZero
968*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
969*10465441SEvalZero rt_hw_interrupt_enable(level);
970*10465441SEvalZero }
971*10465441SEvalZero
972*10465441SEvalZero return RT_EOK;
973*10465441SEvalZero }
974*10465441SEvalZero
975*10465441SEvalZero /**
976*10465441SEvalZero * This function will stop cdc class, it will be called on handle set configuration request.
977*10465441SEvalZero *
978*10465441SEvalZero * @param device the usb device object.
979*10465441SEvalZero *
980*10465441SEvalZero * @return RT_EOK on successful.
981*10465441SEvalZero */
_function_disable(ufunction_t func)982*10465441SEvalZero static rt_err_t _function_disable(ufunction_t func)
983*10465441SEvalZero {
984*10465441SEvalZero RNDIS_PRINTF("plugged out\n");
985*10465441SEvalZero
986*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
987*10465441SEvalZero /* stop link up timer. */
988*10465441SEvalZero rt_timer_stop(&((rt_rndis_eth_t)func->user_data)->timer);
989*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
990*10465441SEvalZero
991*10465441SEvalZero /* clean resp chain list. */
992*10465441SEvalZero {
993*10465441SEvalZero struct rt_rndis_response * response;
994*10465441SEvalZero rt_base_t level = rt_hw_interrupt_disable();
995*10465441SEvalZero
996*10465441SEvalZero while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
997*10465441SEvalZero {
998*10465441SEvalZero response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next;
999*10465441SEvalZero RNDIS_PRINTF("remove resp chain list!\r\n");
1000*10465441SEvalZero
1001*10465441SEvalZero rt_list_remove(&response->list);
1002*10465441SEvalZero rt_free((void *)response->buffer);
1003*10465441SEvalZero rt_free(response);
1004*10465441SEvalZero }
1005*10465441SEvalZero
1006*10465441SEvalZero ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
1007*10465441SEvalZero rt_hw_interrupt_enable(level);
1008*10465441SEvalZero }
1009*10465441SEvalZero
1010*10465441SEvalZero /* link down. */
1011*10465441SEvalZero eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE);
1012*10465441SEvalZero return RT_EOK;
1013*10465441SEvalZero }
1014*10465441SEvalZero
1015*10465441SEvalZero
1016*10465441SEvalZero static struct ufunction_ops ops =
1017*10465441SEvalZero {
1018*10465441SEvalZero _function_enable,
1019*10465441SEvalZero _function_disable,
1020*10465441SEvalZero RT_NULL,
1021*10465441SEvalZero };
1022*10465441SEvalZero
1023*10465441SEvalZero /**
1024*10465441SEvalZero * This function will configure cdc descriptor.
1025*10465441SEvalZero *
1026*10465441SEvalZero * @param comm the communication interface number.
1027*10465441SEvalZero * @param data the data interface number.
1028*10465441SEvalZero *
1029*10465441SEvalZero * @return RT_EOK on successful.
1030*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)1031*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)
1032*10465441SEvalZero {
1033*10465441SEvalZero comm->call_mgmt_desc.data_interface = dintf_nr;
1034*10465441SEvalZero comm->union_desc.master_interface = cintf_nr;
1035*10465441SEvalZero comm->union_desc.slave_interface0 = dintf_nr;
1036*10465441SEvalZero #ifdef RT_USB_DEVICE_COMPOSITE
1037*10465441SEvalZero comm->iad_desc.bFirstInterface = cintf_nr;
1038*10465441SEvalZero #endif
1039*10465441SEvalZero data->ep_out_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
1040*10465441SEvalZero data->ep_in_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
1041*10465441SEvalZero return RT_EOK;
1042*10465441SEvalZero }
1043*10465441SEvalZero
1044*10465441SEvalZero #ifdef RT_USING_LWIP
1045*10465441SEvalZero /* initialize the interface */
rt_rndis_eth_init(rt_device_t dev)1046*10465441SEvalZero static rt_err_t rt_rndis_eth_init(rt_device_t dev)
1047*10465441SEvalZero {
1048*10465441SEvalZero return RT_EOK;
1049*10465441SEvalZero }
1050*10465441SEvalZero
rt_rndis_eth_open(rt_device_t dev,rt_uint16_t oflag)1051*10465441SEvalZero static rt_err_t rt_rndis_eth_open(rt_device_t dev, rt_uint16_t oflag)
1052*10465441SEvalZero {
1053*10465441SEvalZero return RT_EOK;
1054*10465441SEvalZero }
1055*10465441SEvalZero
rt_rndis_eth_close(rt_device_t dev)1056*10465441SEvalZero static rt_err_t rt_rndis_eth_close(rt_device_t dev)
1057*10465441SEvalZero {
1058*10465441SEvalZero return RT_EOK;
1059*10465441SEvalZero }
1060*10465441SEvalZero
rt_rndis_eth_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)1061*10465441SEvalZero static rt_size_t rt_rndis_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
1062*10465441SEvalZero {
1063*10465441SEvalZero rt_set_errno(-RT_ENOSYS);
1064*10465441SEvalZero return 0;
1065*10465441SEvalZero }
1066*10465441SEvalZero
rt_rndis_eth_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)1067*10465441SEvalZero static rt_size_t rt_rndis_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
1068*10465441SEvalZero {
1069*10465441SEvalZero rt_set_errno(-RT_ENOSYS);
1070*10465441SEvalZero return 0;
1071*10465441SEvalZero }
rt_rndis_eth_control(rt_device_t dev,int cmd,void * args)1072*10465441SEvalZero static rt_err_t rt_rndis_eth_control(rt_device_t dev, int cmd, void *args)
1073*10465441SEvalZero {
1074*10465441SEvalZero rt_rndis_eth_t rndis_eth_dev = (rt_rndis_eth_t)dev;
1075*10465441SEvalZero switch(cmd)
1076*10465441SEvalZero {
1077*10465441SEvalZero case NIOCTL_GADDR:
1078*10465441SEvalZero /* get mac address */
1079*10465441SEvalZero if(args) rt_memcpy(args, rndis_eth_dev->dev_addr, MAX_ADDR_LEN);
1080*10465441SEvalZero else return -RT_ERROR;
1081*10465441SEvalZero break;
1082*10465441SEvalZero
1083*10465441SEvalZero default :
1084*10465441SEvalZero break;
1085*10465441SEvalZero }
1086*10465441SEvalZero
1087*10465441SEvalZero return RT_EOK;
1088*10465441SEvalZero }
1089*10465441SEvalZero
1090*10465441SEvalZero /* ethernet device interface */
1091*10465441SEvalZero
1092*10465441SEvalZero
1093*10465441SEvalZero /* reception packet. */
rt_rndis_eth_rx(rt_device_t dev)1094*10465441SEvalZero struct pbuf *rt_rndis_eth_rx(rt_device_t dev)
1095*10465441SEvalZero {
1096*10465441SEvalZero struct pbuf* p = RT_NULL;
1097*10465441SEvalZero rt_uint32_t offset = 0;
1098*10465441SEvalZero rt_rndis_eth_t device = (rt_rndis_eth_t)dev;
1099*10465441SEvalZero if(device->rx_flag == RT_FALSE)
1100*10465441SEvalZero {
1101*10465441SEvalZero return p;
1102*10465441SEvalZero }
1103*10465441SEvalZero
1104*10465441SEvalZero if(device->rx_length != 0)
1105*10465441SEvalZero {
1106*10465441SEvalZero /* allocate buffer */
1107*10465441SEvalZero p = pbuf_alloc(PBUF_LINK, device->rx_length, PBUF_RAM);
1108*10465441SEvalZero if (p != RT_NULL)
1109*10465441SEvalZero {
1110*10465441SEvalZero struct pbuf* q;
1111*10465441SEvalZero
1112*10465441SEvalZero for (q = p; q != RT_NULL; q= q->next)
1113*10465441SEvalZero {
1114*10465441SEvalZero /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */
1115*10465441SEvalZero memcpy(q->payload,
1116*10465441SEvalZero (rt_uint8_t *)((device->rx_buffer) + offset),
1117*10465441SEvalZero q->len);
1118*10465441SEvalZero offset += q->len;
1119*10465441SEvalZero }
1120*10465441SEvalZero }
1121*10465441SEvalZero }
1122*10465441SEvalZero
1123*10465441SEvalZero {
1124*10465441SEvalZero device->rx_flag = RT_FALSE;
1125*10465441SEvalZero device->eps.ep_out->request.buffer = device->eps.ep_out->buffer;
1126*10465441SEvalZero device->eps.ep_out->request.size = EP_MAXPACKET(device->eps.ep_out);
1127*10465441SEvalZero device->eps.ep_out->request.req_type = UIO_REQUEST_READ_BEST;
1128*10465441SEvalZero rt_usbd_io_request(device->func->device, device->eps.ep_out, &device->eps.ep_out->request);
1129*10465441SEvalZero }
1130*10465441SEvalZero
1131*10465441SEvalZero return p;
1132*10465441SEvalZero }
1133*10465441SEvalZero
1134*10465441SEvalZero /* transmit packet. */
rt_rndis_eth_tx(rt_device_t dev,struct pbuf * p)1135*10465441SEvalZero rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p)
1136*10465441SEvalZero {
1137*10465441SEvalZero struct pbuf* q;
1138*10465441SEvalZero char * buffer;
1139*10465441SEvalZero rt_err_t result = RT_EOK;
1140*10465441SEvalZero rt_rndis_eth_t device = (rt_rndis_eth_t)dev;
1141*10465441SEvalZero
1142*10465441SEvalZero if(!device->parent.link_status)
1143*10465441SEvalZero {
1144*10465441SEvalZero RNDIS_PRINTF("linkdown, drop pkg\r\n");
1145*10465441SEvalZero return RT_EOK;
1146*10465441SEvalZero }
1147*10465441SEvalZero
1148*10465441SEvalZero RT_ASSERT(p->tot_len < sizeof(device->tx_buffer));
1149*10465441SEvalZero if(p->tot_len > sizeof(device->tx_buffer))
1150*10465441SEvalZero {
1151*10465441SEvalZero RNDIS_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n",
1152*10465441SEvalZero sizeof(device->tx_buffer), p->tot_len);
1153*10465441SEvalZero p->tot_len = sizeof(device->tx_buffer);
1154*10465441SEvalZero }
1155*10465441SEvalZero
1156*10465441SEvalZero /* wait for buffer free. */
1157*10465441SEvalZero result = rt_sem_take(&device->tx_buffer_free, RT_WAITING_FOREVER);
1158*10465441SEvalZero if(result != RT_EOK)
1159*10465441SEvalZero {
1160*10465441SEvalZero return result;
1161*10465441SEvalZero }
1162*10465441SEvalZero
1163*10465441SEvalZero buffer = (char *)&device->tx_buffer + sizeof(struct rndis_packet_msg);
1164*10465441SEvalZero for (q = p; q != NULL; q = q->next)
1165*10465441SEvalZero {
1166*10465441SEvalZero memcpy(buffer, q->payload, q->len);
1167*10465441SEvalZero buffer += q->len;
1168*10465441SEvalZero }
1169*10465441SEvalZero
1170*10465441SEvalZero /* send */
1171*10465441SEvalZero {
1172*10465441SEvalZero rndis_packet_msg_t msg;
1173*10465441SEvalZero
1174*10465441SEvalZero msg = (rndis_packet_msg_t)&device->tx_buffer;
1175*10465441SEvalZero
1176*10465441SEvalZero msg->MessageType = REMOTE_NDIS_PACKET_MSG;
1177*10465441SEvalZero msg->DataOffset = sizeof(struct rndis_packet_msg) - 8;
1178*10465441SEvalZero msg->DataLength = p->tot_len;
1179*10465441SEvalZero msg->OOBDataLength = 0;
1180*10465441SEvalZero msg->OOBDataOffset = 0;
1181*10465441SEvalZero msg->NumOOBDataElements = 0;
1182*10465441SEvalZero msg->PerPacketInfoOffset = 0;
1183*10465441SEvalZero msg->PerPacketInfoLength = 0;
1184*10465441SEvalZero msg->VcHandle = 0;
1185*10465441SEvalZero msg->Reserved = 0;
1186*10465441SEvalZero msg->MessageLength = sizeof(struct rndis_packet_msg) + p->tot_len;
1187*10465441SEvalZero
1188*10465441SEvalZero if((msg->MessageLength & 0x3F) == 0)
1189*10465441SEvalZero {
1190*10465441SEvalZero /* pad a dummy. */
1191*10465441SEvalZero msg->MessageLength += 1;
1192*10465441SEvalZero }
1193*10465441SEvalZero
1194*10465441SEvalZero device->eps.ep_in->request.buffer = (void *)&device->tx_buffer;
1195*10465441SEvalZero device->eps.ep_in->request.size = msg->MessageLength;
1196*10465441SEvalZero device->eps.ep_in->request.req_type = UIO_REQUEST_WRITE;
1197*10465441SEvalZero rt_usbd_io_request(device->func->device, device->eps.ep_in, &device->eps.ep_in->request);
1198*10465441SEvalZero }
1199*10465441SEvalZero
1200*10465441SEvalZero return result;
1201*10465441SEvalZero }
1202*10465441SEvalZero
1203*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
1204*10465441SEvalZero const static struct rt_device_ops rndis_device_ops =
1205*10465441SEvalZero {
1206*10465441SEvalZero rt_rndis_eth_init,
1207*10465441SEvalZero rt_rndis_eth_open,
1208*10465441SEvalZero rt_rndis_eth_close,
1209*10465441SEvalZero rt_rndis_eth_read,
1210*10465441SEvalZero rt_rndis_eth_write,
1211*10465441SEvalZero rt_rndis_eth_control
1212*10465441SEvalZero };
1213*10465441SEvalZero #endif
1214*10465441SEvalZero
1215*10465441SEvalZero #endif /* RT_USING_LWIP */
1216*10465441SEvalZero
1217*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
1218*10465441SEvalZero /* the delay linkup timer handler. */
timer_timeout(void * parameter)1219*10465441SEvalZero static void timer_timeout(void* parameter)
1220*10465441SEvalZero {
1221*10465441SEvalZero RNDIS_PRINTF("delay link up!\r\n");
1222*10465441SEvalZero _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->parent.parent.user_data,
1223*10465441SEvalZero RNDIS_STATUS_MEDIA_CONNECT);
1224*10465441SEvalZero eth_device_linkchange(&((rt_rndis_eth_t)parameter)->parent, RT_TRUE);
1225*10465441SEvalZero }
1226*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
1227*10465441SEvalZero
1228*10465441SEvalZero /**
1229*10465441SEvalZero * This function will create a cdc rndis class instance.
1230*10465441SEvalZero *
1231*10465441SEvalZero * @param device the usb device object.
1232*10465441SEvalZero *
1233*10465441SEvalZero * @return RT_EOK on successful.
1234*10465441SEvalZero */
rt_usbd_function_rndis_create(udevice_t device)1235*10465441SEvalZero ufunction_t rt_usbd_function_rndis_create(udevice_t device)
1236*10465441SEvalZero {
1237*10465441SEvalZero ufunction_t cdc;
1238*10465441SEvalZero rt_rndis_eth_t _rndis;
1239*10465441SEvalZero cdc_eps_t eps;
1240*10465441SEvalZero uintf_t intf_comm, intf_data;
1241*10465441SEvalZero ualtsetting_t comm_setting, data_setting;
1242*10465441SEvalZero ucdc_data_desc_t data_desc;
1243*10465441SEvalZero ucdc_comm_desc_t comm_desc;
1244*10465441SEvalZero
1245*10465441SEvalZero /* parameter check */
1246*10465441SEvalZero RT_ASSERT(device != RT_NULL);
1247*10465441SEvalZero
1248*10465441SEvalZero /* set usb device string description */
1249*10465441SEvalZero rt_usbd_device_set_string(device, _ustring);
1250*10465441SEvalZero
1251*10465441SEvalZero /* create a cdc class */
1252*10465441SEvalZero cdc = rt_usbd_function_new(device, &_dev_desc, &ops);
1253*10465441SEvalZero rt_usbd_device_set_qualifier(device, &dev_qualifier);
1254*10465441SEvalZero _rndis= rt_malloc(sizeof(struct rt_rndis_eth));
1255*10465441SEvalZero rt_memset(_rndis, 0, sizeof(struct rt_rndis_eth));
1256*10465441SEvalZero cdc->user_data = _rndis;
1257*10465441SEvalZero
1258*10465441SEvalZero _rndis->func = cdc;
1259*10465441SEvalZero /* create a cdc class endpoints collection */
1260*10465441SEvalZero eps = &_rndis->eps;
1261*10465441SEvalZero /* create a cdc communication interface and a cdc data interface */
1262*10465441SEvalZero intf_comm = rt_usbd_interface_new(device, _interface_handler);
1263*10465441SEvalZero intf_data = rt_usbd_interface_new(device, _interface_handler);
1264*10465441SEvalZero
1265*10465441SEvalZero /* create a communication alternate setting and a data alternate setting */
1266*10465441SEvalZero comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_comm_descriptor));
1267*10465441SEvalZero data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
1268*10465441SEvalZero
1269*10465441SEvalZero /* config desc in alternate setting */
1270*10465441SEvalZero rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
1271*10465441SEvalZero (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
1272*10465441SEvalZero rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
1273*10465441SEvalZero /* configure the cdc interface descriptor */
1274*10465441SEvalZero _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num, device->dcd->device_is_hs);
1275*10465441SEvalZero
1276*10465441SEvalZero /* create a command endpoint */
1277*10465441SEvalZero comm_desc = (ucdc_comm_desc_t)comm_setting->desc;
1278*10465441SEvalZero eps->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
1279*10465441SEvalZero /* add the command endpoint to the cdc communication interface */
1280*10465441SEvalZero rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd);
1281*10465441SEvalZero
1282*10465441SEvalZero /* add the communication alternate setting to the communication interface,
1283*10465441SEvalZero then set default setting of the interface */
1284*10465441SEvalZero rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
1285*10465441SEvalZero rt_usbd_set_altsetting(intf_comm, 0);
1286*10465441SEvalZero /* add the communication interface to the cdc class */
1287*10465441SEvalZero rt_usbd_function_add_interface(cdc, intf_comm);
1288*10465441SEvalZero
1289*10465441SEvalZero /* create a bulk in and a bulk out endpoint */
1290*10465441SEvalZero data_desc = (ucdc_data_desc_t)data_setting->desc;
1291*10465441SEvalZero eps->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
1292*10465441SEvalZero eps->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
1293*10465441SEvalZero
1294*10465441SEvalZero /* add the bulk out and bulk in endpoints to the data alternate setting */
1295*10465441SEvalZero rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in);
1296*10465441SEvalZero rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out);
1297*10465441SEvalZero
1298*10465441SEvalZero /* add the data alternate setting to the data interface
1299*10465441SEvalZero then set default setting of the interface */
1300*10465441SEvalZero rt_usbd_interface_add_altsetting(intf_data, data_setting);
1301*10465441SEvalZero rt_usbd_set_altsetting(intf_data, 0);
1302*10465441SEvalZero
1303*10465441SEvalZero /* add the cdc data interface to cdc class */
1304*10465441SEvalZero rt_usbd_function_add_interface(cdc, intf_data);
1305*10465441SEvalZero
1306*10465441SEvalZero rt_usbd_os_comp_id_desc_add_os_func_comp_id_desc(device->os_comp_id_desc, &rndis_func_comp_id_desc);
1307*10465441SEvalZero
1308*10465441SEvalZero
1309*10465441SEvalZero #ifdef RT_USING_LWIP
1310*10465441SEvalZero
1311*10465441SEvalZero rt_list_init(&_rndis->response_list);
1312*10465441SEvalZero _rndis->need_notify = RT_TRUE;
1313*10465441SEvalZero
1314*10465441SEvalZero rt_sem_init(&_rndis->tx_buffer_free, "ue_tx", 1, RT_IPC_FLAG_FIFO);
1315*10465441SEvalZero
1316*10465441SEvalZero #ifdef RNDIS_DELAY_LINK_UP
1317*10465441SEvalZero rt_timer_init(&_rndis->timer,
1318*10465441SEvalZero "RNDIS",
1319*10465441SEvalZero timer_timeout,
1320*10465441SEvalZero _rndis,
1321*10465441SEvalZero RT_TICK_PER_SECOND * 2,
1322*10465441SEvalZero RT_TIMER_FLAG_ONE_SHOT);
1323*10465441SEvalZero #endif /* RNDIS_DELAY_LINK_UP */
1324*10465441SEvalZero
1325*10465441SEvalZero /* OUI 00-00-00, only for test. */
1326*10465441SEvalZero _rndis->dev_addr[0] = 0x34;
1327*10465441SEvalZero _rndis->dev_addr[1] = 0x97;
1328*10465441SEvalZero _rndis->dev_addr[2] = 0xF6;
1329*10465441SEvalZero /* generate random MAC. */
1330*10465441SEvalZero _rndis->dev_addr[3] = 0x94;//*(const rt_uint8_t *)(0x1fff7a10);
1331*10465441SEvalZero _rndis->dev_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x1fff7a14);
1332*10465441SEvalZero _rndis->dev_addr[5] = 0x12;//(const rt_uint8_t *)(0x1fff7a18);
1333*10465441SEvalZero /* OUI 00-00-00, only for test. */
1334*10465441SEvalZero _rndis->host_addr[0] = 0x34;
1335*10465441SEvalZero _rndis->host_addr[1] = 0x97;
1336*10465441SEvalZero _rndis->host_addr[2] = 0xF6;
1337*10465441SEvalZero /* generate random MAC. */
1338*10465441SEvalZero _rndis->host_addr[3] = 0x94;//*(const rt_uint8_t *)(0x0FE081F0);
1339*10465441SEvalZero _rndis->host_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x0FE081F1);
1340*10465441SEvalZero _rndis->host_addr[5] = 0x13;//*(const rt_uint8_t *)(0x0FE081F2);
1341*10465441SEvalZero
1342*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
1343*10465441SEvalZero _rndis->parent.parent.ops = &rndis_device_ops;
1344*10465441SEvalZero #else
1345*10465441SEvalZero _rndis->parent.parent.init = rt_rndis_eth_init;
1346*10465441SEvalZero _rndis->parent.parent.open = rt_rndis_eth_open;
1347*10465441SEvalZero _rndis->parent.parent.close = rt_rndis_eth_close;
1348*10465441SEvalZero _rndis->parent.parent.read = rt_rndis_eth_read;
1349*10465441SEvalZero _rndis->parent.parent.write = rt_rndis_eth_write;
1350*10465441SEvalZero _rndis->parent.parent.control = rt_rndis_eth_control;
1351*10465441SEvalZero #endif
1352*10465441SEvalZero _rndis->parent.parent.user_data = device;
1353*10465441SEvalZero
1354*10465441SEvalZero _rndis->parent.eth_rx = rt_rndis_eth_rx;
1355*10465441SEvalZero _rndis->parent.eth_tx = rt_rndis_eth_tx;
1356*10465441SEvalZero
1357*10465441SEvalZero /* register eth device */
1358*10465441SEvalZero eth_device_init(&((rt_rndis_eth_t)cdc->user_data)->parent, "u0");
1359*10465441SEvalZero
1360*10465441SEvalZero #endif /* RT_USING_LWIP */
1361*10465441SEvalZero
1362*10465441SEvalZero return cdc;
1363*10465441SEvalZero }
1364*10465441SEvalZero
1365*10465441SEvalZero struct udclass rndis_class =
1366*10465441SEvalZero {
1367*10465441SEvalZero .rt_usbd_function_create = rt_usbd_function_rndis_create
1368*10465441SEvalZero };
1369*10465441SEvalZero
rt_usbd_rndis_class_register(void)1370*10465441SEvalZero int rt_usbd_rndis_class_register(void)
1371*10465441SEvalZero {
1372*10465441SEvalZero rt_usbd_class_register(&rndis_class);
1373*10465441SEvalZero return 0;
1374*10465441SEvalZero }
1375*10465441SEvalZero INIT_PREV_EXPORT(rt_usbd_rndis_class_register);