• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_rndis.h"
8 #include "rndis_protocol.h"
9 
10 #define RNDIS_OUT_EP_IDX 0
11 #define RNDIS_IN_EP_IDX  1
12 #define RNDIS_INT_EP_IDX 2
13 
14 /* Describe EndPoints configuration */
15 static struct usbd_endpoint rndis_ep_data[3];
16 
17 #define RNDIS_INQUIRY_PUT(src, len)   (memcpy(infomation_buffer, src, len))
18 #define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
19 
20 #ifdef CONFIG_USB_HS
21 #define RNDIS_MAX_PACKET_SIZE 512
22 #else
23 #define RNDIS_MAX_PACKET_SIZE 64
24 #endif
25 
26 #ifndef CONFIG_USB_HS
27 #define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */
28 #else
29 #define RNDIS_LINK_SPEED 480000000 /* Link baudrate (480Mbit/s for USB-HS) */
30 #endif
31 
32 /* Device data structure */
33 struct usbd_rndis_priv {
34     uint32_t drv_version;
35     uint32_t link_status;
36     uint32_t speed;
37     uint32_t net_filter;
38     usb_eth_stat_t eth_state;
39     rndis_state_t init_state;
40     uint8_t mac[6];
41 } g_usbd_rndis;
42 
43 #if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
44 #undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
45 #define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
46 #endif
47 
48 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
49 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
50 
51 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
52 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
53 
54 volatile uint8_t *g_rndis_rx_data_buffer;
55 volatile uint32_t g_rndis_rx_data_length;
56 volatile uint32_t g_rndis_tx_data_length;
57 
58 /* RNDIS options list */
59 const uint32_t oid_supported_list[] = {
60     /* General OIDs */
61     OID_GEN_SUPPORTED_LIST,
62     OID_GEN_HARDWARE_STATUS,
63     OID_GEN_MEDIA_SUPPORTED,
64     OID_GEN_MEDIA_IN_USE,
65     OID_GEN_MAXIMUM_FRAME_SIZE,
66     OID_GEN_LINK_SPEED,
67     OID_GEN_TRANSMIT_BLOCK_SIZE,
68     OID_GEN_RECEIVE_BLOCK_SIZE,
69     OID_GEN_VENDOR_ID,
70     OID_GEN_VENDOR_DESCRIPTION,
71     OID_GEN_VENDOR_DRIVER_VERSION,
72     OID_GEN_CURRENT_PACKET_FILTER,
73     OID_GEN_MAXIMUM_TOTAL_SIZE,
74     OID_GEN_MEDIA_CONNECT_STATUS,
75 
76     OID_GEN_PHYSICAL_MEDIUM,
77 
78     /* General Statistic OIDs */
79     OID_GEN_XMIT_OK,
80     OID_GEN_RCV_OK,
81     OID_GEN_XMIT_ERROR,
82     OID_GEN_RCV_ERROR,
83     OID_GEN_RCV_NO_BUFFER,
84 
85     /* Please configure us */
86     OID_GEN_RNDIS_CONFIG_PARAMETER,
87 
88     /* 802.3 OIDs */
89     OID_802_3_PERMANENT_ADDRESS,
90     OID_802_3_CURRENT_ADDRESS,
91     OID_802_3_MULTICAST_LIST,
92     OID_802_3_MAXIMUM_LIST_SIZE,
93 
94     /* 802.3 Statistic OIDs */
95     OID_802_3_RCV_ERROR_ALIGNMENT,
96     OID_802_3_XMIT_ONE_COLLISION,
97     OID_802_3_XMIT_MORE_COLLISIONS,
98 
99     OID_802_3_MAC_OPTIONS,
100 };
101 
102 static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
103 
rndis_notify_rsp(void)104 static void rndis_notify_rsp(void)
105 {
106     memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
107     NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
108     usbd_ep_start_write(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
109 }
110 
rndis_class_interface_request_handler(struct usb_setup_packet * setup,uint8_t ** data,uint32_t * len)111 static int rndis_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
112 {
113     switch (setup->bRequest) {
114         case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
115             rndis_encapsulated_cmd_handler(*data, setup->wLength);
116             break;
117         case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
118             *data = rndis_encapsulated_resp_buffer;
119             *len = ((rndis_generic_msg_t *)rndis_encapsulated_resp_buffer)->MessageLength;
120             break;
121 
122         default:
123             return -1;
124     }
125 
126     return 0;
127 }
128 
129 static int rndis_init_cmd_handler(uint8_t *data, uint32_t len);
130 static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len);
131 static int rndis_query_cmd_handler(uint8_t *data, uint32_t len);
132 static int rndis_set_cmd_handler(uint8_t *data, uint32_t len);
133 static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len);
134 static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len);
135 
rndis_encapsulated_cmd_handler(uint8_t * data,uint32_t len)136 static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len)
137 {
138     switch (((rndis_generic_msg_t *)data)->MessageType) {
139         case REMOTE_NDIS_INITIALIZE_MSG:
140             return rndis_init_cmd_handler(data, len);
141         case REMOTE_NDIS_HALT_MSG:
142             return rndis_halt_cmd_handler(data, len);
143         case REMOTE_NDIS_QUERY_MSG:
144             return rndis_query_cmd_handler(data, len);
145         case REMOTE_NDIS_SET_MSG:
146             return rndis_set_cmd_handler(data, len);
147         case REMOTE_NDIS_RESET_MSG:
148             return rndis_reset_cmd_handler(data, len);
149         case REMOTE_NDIS_KEEPALIVE_MSG:
150             return rndis_keepalive_cmd_handler(data, len);
151 
152         default:
153             break;
154     }
155     return -1;
156 }
157 
rndis_init_cmd_handler(uint8_t * data,uint32_t len)158 static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
159 {
160     rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
161     rndis_initialize_cmplt_t *resp;
162 
163     resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
164     resp->RequestId = cmd->RequestId;
165     resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
166     resp->MessageLength = sizeof(rndis_initialize_cmplt_t);
167     resp->MajorVersion = RNDIS_MAJOR_VERSION;
168     resp->MinorVersion = RNDIS_MINOR_VERSION;
169     resp->Status = RNDIS_STATUS_SUCCESS;
170     resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
171     resp->Medium = RNDIS_MEDIUM_802_3;
172     resp->MaxPacketsPerTransfer = 1;
173     resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + sizeof(rndis_data_packet_t);
174     resp->PacketAlignmentFactor = 0;
175     resp->AfListOffset = 0;
176     resp->AfListSize = 0;
177 
178     g_usbd_rndis.init_state = rndis_initialized;
179 
180     rndis_notify_rsp();
181     return 0;
182 }
183 
rndis_halt_cmd_handler(uint8_t * data,uint32_t len)184 static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
185 {
186     rndis_halt_msg_t *resp;
187 
188     resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
189     resp->MessageLength = 0;
190 
191     g_usbd_rndis.init_state = rndis_uninitialized;
192 
193     return 0;
194 }
195 
rndis_query_cmd_handler(uint8_t * data,uint32_t len)196 static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
197 {
198     rndis_query_msg_t *cmd = (rndis_query_msg_t *)data;
199     rndis_query_cmplt_t *resp;
200     uint8_t *infomation_buffer;
201     uint32_t infomation_len = 0;
202 
203     resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
204     resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
205     resp->RequestId = cmd->RequestId;
206     resp->InformationBufferOffset = sizeof(rndis_query_cmplt_t) - sizeof(rndis_generic_msg_t);
207     resp->Status = RNDIS_STATUS_SUCCESS;
208 
209     infomation_buffer = (uint8_t *)resp + sizeof(rndis_query_cmplt_t);
210 
211     switch (cmd->Oid) {
212         case OID_GEN_SUPPORTED_LIST:
213             RNDIS_INQUIRY_PUT(oid_supported_list, sizeof(oid_supported_list));
214             infomation_len = sizeof(oid_supported_list);
215             break;
216         case OID_GEN_HARDWARE_STATUS:
217             RNDIS_INQUIRY_PUT_LE32(NDIS_HW_STS_READY);
218             infomation_len = 4;
219             break;
220         case OID_GEN_MEDIA_SUPPORTED:
221         case OID_GEN_MEDIA_IN_USE:
222             RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
223             infomation_len = 4;
224             break;
225         case OID_GEN_MAXIMUM_FRAME_SIZE:
226         case OID_GEN_TRANSMIT_BLOCK_SIZE:
227         case OID_GEN_RECEIVE_BLOCK_SIZE:
228             RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE);
229             infomation_len = 4;
230             break;
231         case OID_GEN_VENDOR_ID:
232             RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_VENDOR_ID);
233             infomation_len = 4;
234             break;
235         case OID_GEN_VENDOR_DRIVER_VERSION:
236             RNDIS_INQUIRY_PUT_LE32(0x0001);
237             infomation_len = 4;
238             break;
239         case OID_GEN_VENDOR_DESCRIPTION:
240             RNDIS_INQUIRY_PUT(CONFIG_USBDEV_RNDIS_VENDOR_DESC, strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC));
241             infomation_len = (strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC) + 1);
242             break;
243         case OID_802_3_CURRENT_ADDRESS:
244         case OID_802_3_PERMANENT_ADDRESS:
245             RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
246             infomation_len = 6;
247             break;
248         case OID_GEN_PHYSICAL_MEDIUM:
249             RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
250             infomation_len = 4;
251             break;
252         case OID_GEN_LINK_SPEED:
253             RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
254             infomation_len = 4;
255             break;
256         case OID_GEN_CURRENT_PACKET_FILTER:
257             RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
258             infomation_len = 4;
259             break;
260         case OID_GEN_MAXIMUM_TOTAL_SIZE:
261             RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE);
262             infomation_len = 4;
263             break;
264         case OID_GEN_MEDIA_CONNECT_STATUS:
265             RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
266             infomation_len = 4;
267             break;
268         case OID_GEN_RNDIS_CONFIG_PARAMETER:
269             RNDIS_INQUIRY_PUT_LE32(0);
270             infomation_len = 4;
271             break;
272         case OID_802_3_MAXIMUM_LIST_SIZE:
273             RNDIS_INQUIRY_PUT_LE32(1); /* one address */
274             infomation_len = 4;
275             break;
276         case OID_802_3_MULTICAST_LIST:
277             //RNDIS_INQUIRY_PUT_LE32(0xE0000000); /* 224.0.0.0 */
278             resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
279             RNDIS_INQUIRY_PUT_LE32(0);
280             infomation_len = 4;
281             break;
282         case OID_802_3_MAC_OPTIONS:
283             // infomation_len = 0;
284             resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
285             RNDIS_INQUIRY_PUT_LE32(0);
286             infomation_len = 4;
287             break;
288         case OID_GEN_MAC_OPTIONS:
289             RNDIS_INQUIRY_PUT_LE32(0);
290             infomation_len = 4;
291             break;
292         case OID_802_3_RCV_ERROR_ALIGNMENT:
293             RNDIS_INQUIRY_PUT_LE32(0);
294             infomation_len = 4;
295             break;
296         case OID_802_3_XMIT_ONE_COLLISION:
297             RNDIS_INQUIRY_PUT_LE32(0);
298             infomation_len = 4;
299             break;
300         case OID_802_3_XMIT_MORE_COLLISIONS:
301             RNDIS_INQUIRY_PUT_LE32(0);
302             infomation_len = 4;
303             break;
304         case OID_GEN_XMIT_OK:
305             RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
306             infomation_len = 4;
307             break;
308         case OID_GEN_RCV_OK:
309             RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
310             infomation_len = 4;
311             break;
312         case OID_GEN_RCV_ERROR:
313             RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
314             infomation_len = 4;
315             break;
316         case OID_GEN_XMIT_ERROR:
317             RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
318             infomation_len = 4;
319             break;
320         case OID_GEN_RCV_NO_BUFFER:
321             RNDIS_INQUIRY_PUT_LE32(0);
322             infomation_len = 4;
323             break;
324         default:
325             resp->Status = RNDIS_STATUS_FAILURE;
326             infomation_len = 0;
327             USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
328             break;
329     }
330 
331     resp->MessageLength = sizeof(rndis_query_cmplt_t) + infomation_len;
332     resp->InformationBufferLength = infomation_len;
333 
334     rndis_notify_rsp();
335     return 0;
336 }
337 
rndis_set_cmd_handler(uint8_t * data,uint32_t len)338 static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
339 {
340     rndis_set_msg_t *cmd = (rndis_set_msg_t *)data;
341     rndis_set_cmplt_t *resp;
342     rndis_config_parameter_t *param;
343 
344     resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
345     resp->RequestId = cmd->RequestId;
346     resp->MessageType = REMOTE_NDIS_SET_CMPLT;
347     resp->MessageLength = sizeof(rndis_set_cmplt_t);
348     resp->Status = RNDIS_STATUS_SUCCESS;
349 
350     switch (cmd->Oid) {
351         case OID_GEN_RNDIS_CONFIG_PARAMETER:
352             param = (rndis_config_parameter_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
353             USB_LOG_WRN("RNDIS cfg param: NameOfs=%d, NameLen=%d, ValueOfs=%d, ValueLen=%d\r\n",
354                         param->ParameterNameOffset, param->ParameterNameLength,
355                         param->ParameterValueOffset, param->ParameterValueLength);
356             break;
357         case OID_GEN_CURRENT_PACKET_FILTER:
358             if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
359                 USB_LOG_WRN("PACKET_FILTER!\r\n");
360                 resp->Status = RNDIS_STATUS_INVALID_DATA;
361             } else {
362                 uint32_t *filter;
363                 /* Parameter starts at offset buf_offset of the req_id field */
364                 filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
365 
366                 //g_usbd_rndis.net_filter = param->ParameterNameOffset;
367                 g_usbd_rndis.net_filter = *(uint32_t *)filter;
368                 if (g_usbd_rndis.net_filter) {
369                     g_usbd_rndis.init_state = rndis_data_initialized;
370                 } else {
371                     g_usbd_rndis.init_state = rndis_initialized;
372                 }
373             }
374             break;
375         case OID_GEN_CURRENT_LOOKAHEAD:
376             break;
377         case OID_GEN_PROTOCOL_OPTIONS:
378             break;
379         case OID_802_3_MULTICAST_LIST:
380             break;
381         case OID_PNP_ADD_WAKE_UP_PATTERN:
382         case OID_PNP_REMOVE_WAKE_UP_PATTERN:
383         case OID_PNP_ENABLE_WAKE_UP:
384         default:
385             resp->Status = RNDIS_STATUS_FAILURE;
386             USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
387             break;
388     }
389 
390     rndis_notify_rsp();
391 
392     return 0;
393 }
394 
rndis_reset_cmd_handler(uint8_t * data,uint32_t len)395 static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
396 {
397     // rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
398     rndis_reset_cmplt_t *resp;
399 
400     resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
401     resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
402     resp->MessageLength = sizeof(rndis_reset_cmplt_t);
403     resp->Status = RNDIS_STATUS_SUCCESS;
404     resp->AddressingReset = 1;
405 
406     g_usbd_rndis.init_state = rndis_uninitialized;
407 
408     rndis_notify_rsp();
409 
410     return 0;
411 }
412 
rndis_keepalive_cmd_handler(uint8_t * data,uint32_t len)413 static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
414 {
415     rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
416     rndis_keepalive_cmplt_t *resp;
417 
418     resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
419     resp->RequestId = cmd->RequestId;
420     resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
421     resp->MessageLength = sizeof(rndis_keepalive_cmplt_t);
422     resp->Status = RNDIS_STATUS_SUCCESS;
423 
424     rndis_notify_rsp();
425 
426     return 0;
427 }
428 
rndis_notify_handler(uint8_t event,void * arg)429 static void rndis_notify_handler(uint8_t event, void *arg)
430 {
431     switch (event) {
432         case USBD_EVENT_RESET:
433             g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
434             break;
435         case USBD_EVENT_CONFIGURED:
436             g_rndis_rx_data_length = 0;
437             g_rndis_tx_data_length = 0;
438             g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
439             usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
440             break;
441 
442         default:
443             break;
444     }
445 }
446 
rndis_bulk_out(uint8_t ep,uint32_t nbytes)447 void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
448 {
449     rndis_data_packet_t *hdr;
450 
451     hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
452     g_rndis_rx_data_buffer = g_rndis_rx_buffer;
453     if ((hdr->MessageType != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
454         usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
455         return;
456     }
457 
458     /* Point to the payload and update the message length */
459     g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
460     g_rndis_rx_data_length = hdr->DataLength;
461 
462     usbd_rndis_data_recv_done();
463 }
464 
rndis_bulk_in(uint8_t ep,uint32_t nbytes)465 void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
466 {
467     if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
468         /* send zlp */
469         usbd_ep_start_write(ep, NULL, 0);
470     } else {
471         g_rndis_tx_data_length = 0;
472     }
473 }
474 
rndis_int_in(uint8_t ep,uint32_t nbytes)475 void rndis_int_in(uint8_t ep, uint32_t nbytes)
476 {
477     //USB_LOG_DBG("len:%d\r\n", nbytes);
478 }
479 
480 #ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
481 #include <lwip/pbuf.h>
482 
usbd_rndis_eth_rx(void)483 struct pbuf *usbd_rndis_eth_rx(void)
484 {
485     struct pbuf *p;
486 
487     if (g_rndis_rx_data_length == 0) {
488         return NULL;
489     }
490     p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
491     if (p == NULL) {
492         return NULL;
493     }
494     memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
495     p->len = g_rndis_rx_data_length;
496 
497     USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
498     g_rndis_rx_data_length = 0;
499     usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
500 
501     return p;
502 }
503 
usbd_rndis_eth_tx(struct pbuf * p)504 int usbd_rndis_eth_tx(struct pbuf *p)
505 {
506     struct pbuf *q;
507     uint8_t *buffer;
508     rndis_data_packet_t *hdr;
509 
510     if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
511         return 0;
512     }
513 
514     if (g_rndis_tx_data_length > 0) {
515         return -EBUSY;
516     }
517 
518     if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
519         p->tot_len = sizeof(g_rndis_tx_buffer);
520     }
521 
522     buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
523     for (q = p; q != NULL; q = q->next) {
524         memcpy(buffer, q->payload, q->len);
525         buffer += q->len;
526     }
527 
528     hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
529 
530     memset(hdr, 0, sizeof(rndis_data_packet_t));
531     hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
532     hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
533     hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
534     hdr->DataLength = p->tot_len;
535 
536     g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
537 
538     USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
539     return usbd_ep_start_write(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
540 }
541 #endif
usbd_rndis_init_intf(struct usbd_interface * intf,const uint8_t out_ep,const uint8_t in_ep,const uint8_t int_ep,uint8_t mac[6])542 struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
543                                             const uint8_t out_ep,
544                                             const uint8_t in_ep,
545                                             const uint8_t int_ep, uint8_t mac[6])
546 {
547     memcpy(g_usbd_rndis.mac, mac, 6);
548 
549     g_usbd_rndis.drv_version = 0x0001;
550     g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
551     g_usbd_rndis.speed = RNDIS_LINK_SPEED;
552 
553     rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
554     rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
555     rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr = in_ep;
556     rndis_ep_data[RNDIS_IN_EP_IDX].ep_cb = rndis_bulk_in;
557     rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
558     rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
559 
560     usbd_add_endpoint(&rndis_ep_data[RNDIS_OUT_EP_IDX]);
561     usbd_add_endpoint(&rndis_ep_data[RNDIS_IN_EP_IDX]);
562     usbd_add_endpoint(&rndis_ep_data[RNDIS_INT_EP_IDX]);
563 
564     intf->class_interface_handler = rndis_class_interface_request_handler;
565     intf->class_endpoint_handler = NULL;
566     intf->vendor_handler = NULL;
567     intf->notify_handler = rndis_notify_handler;
568 
569     return intf;
570 }
571