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