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