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 }