1 /*
2 * Copyright (c) 2022, sakumisu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "usbh_core.h"
7 #include "usbh_rndis.h"
8 #include "rndis_protocol.h"
9
10 #undef USB_DBG_TAG
11 #define USB_DBG_TAG "usbh_rndis"
12 #include "usb_log.h"
13
14 #define DEV_FORMAT "/dev/rndis"
15
16 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[512];
17
18 #define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
19 #define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
20
21 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE, CONFIG_USB_ALIGN_SIZE)];
22 static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[USB_ALIGN_UP(CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE, CONFIG_USB_ALIGN_SIZE)];
23 // static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[USB_ALIGN_UP(16, CONFIG_USB_ALIGN_SIZE)];
24
25 static struct usbh_rndis g_rndis_class;
26
usbh_rndis_get_notification(struct usbh_rndis * rndis_class)27 static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
28 {
29 (void)rndis_class;
30 // int ret;
31 // struct usbh_urb *urb = &rndis_class->intin_urb;
32
33 // usbh_int_urb_fill(urb, rndis_class->hport, rndis_class->intin, g_rndis_inttx_buffer, rndis_class->intin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, NULL, NULL);
34 // ret = usbh_submit_urb(urb);
35 // if (ret == 0) {
36 // ret = urb->actual_length;
37 // }
38 // return ret;
39 return 0;
40 }
41
usbh_rndis_init_msg_transfer(struct usbh_rndis * rndis_class)42 static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
43 {
44 struct usb_setup_packet *setup;
45 int ret = 0;
46 rndis_initialize_msg_t *cmd;
47 rndis_initialize_cmplt_t *resp;
48
49 if (!rndis_class || !rndis_class->hport) {
50 return -USB_ERR_INVAL;
51 }
52 setup = rndis_class->hport->setup;
53
54 cmd = (rndis_initialize_msg_t *)g_rndis_buf;
55
56 cmd->MessageType = REMOTE_NDIS_INITIALIZE_MSG;
57 cmd->MessageLength = sizeof(rndis_initialize_msg_t);
58 cmd->RequestId = rndis_class->request_id++;
59 cmd->MajorVersion = 1;
60 cmd->MinorVersion = 0;
61 cmd->MaxTransferSize = 0x4000;
62
63 setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
64 setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
65 setup->wValue = 0;
66 setup->wIndex = 0;
67 setup->wLength = sizeof(rndis_initialize_msg_t);
68
69 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
70 if (ret < 0) {
71 USB_LOG_ERR("init send error, ret: %d\r\n", ret);
72 return ret;
73 }
74
75 usbh_rndis_get_notification(rndis_class);
76
77 resp = (rndis_initialize_cmplt_t *)g_rndis_buf;
78
79 setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
80 setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
81 setup->wValue = 0;
82 setup->wIndex = 0;
83 setup->wLength = sizeof(g_rndis_buf);
84
85 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
86 if (ret < 0) {
87 USB_LOG_ERR("init recv error, ret: %d\r\n", ret);
88 return ret;
89 }
90
91 rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer;
92 rndis_class->max_transfer_size = resp->MaxTransferSize;
93 USB_LOG_INFO("MaxPacketsPerTransfer: %u\r\n", (unsigned int)resp->MaxPacketsPerTransfer);
94 USB_LOG_INFO("MaxTransferSize: %u\r\n", (unsigned int)resp->MaxTransferSize);
95
96 return ret;
97 }
98
usbh_rndis_query_msg_transfer(struct usbh_rndis * rndis_class,uint32_t oid,uint32_t query_len,uint8_t * info,uint32_t * info_len)99 int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len)
100 {
101 struct usb_setup_packet *setup;
102 int ret = 0;
103 rndis_query_msg_t *cmd;
104 rndis_query_cmplt_t *resp;
105
106 if (!rndis_class || !rndis_class->hport) {
107 return -USB_ERR_INVAL;
108 }
109 setup = rndis_class->hport->setup;
110
111 cmd = (rndis_query_msg_t *)g_rndis_buf;
112
113 cmd->MessageType = REMOTE_NDIS_QUERY_MSG;
114 cmd->MessageLength = query_len + sizeof(rndis_query_msg_t);
115 cmd->RequestId = rndis_class->request_id++;
116 cmd->Oid = oid;
117 cmd->InformationBufferLength = query_len;
118 cmd->InformationBufferOffset = 20;
119 cmd->DeviceVcHandle = 0;
120
121 setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
122 setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
123 setup->wValue = 0;
124 setup->wIndex = 0;
125 setup->wLength = query_len + sizeof(rndis_query_msg_t);
126
127 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
128 if (ret < 0) {
129 USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
130 return ret;
131 }
132
133 usbh_rndis_get_notification(rndis_class);
134
135 resp = (rndis_query_cmplt_t *)g_rndis_buf;
136
137 setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
138 setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
139 setup->wValue = 0;
140 setup->wIndex = 0;
141 setup->wLength = sizeof(g_rndis_buf);
142
143 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
144 if (ret < 0) {
145 USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
146 return ret;
147 }
148
149 memcpy(info, ((uint8_t *)resp + sizeof(rndis_query_cmplt_t)), resp->InformationBufferLength);
150 *info_len = resp->InformationBufferLength;
151
152 return ret;
153 }
154
usbh_rndis_set_msg_transfer(struct usbh_rndis * rndis_class,uint32_t oid,uint8_t * info,uint32_t info_len)155 static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len)
156 {
157 struct usb_setup_packet *setup;
158 int ret = 0;
159 rndis_set_msg_t *cmd;
160 rndis_set_cmplt_t *resp;
161
162 if (!rndis_class || !rndis_class->hport) {
163 return -USB_ERR_INVAL;
164 }
165 setup = rndis_class->hport->setup;
166
167 cmd = (rndis_set_msg_t *)g_rndis_buf;
168
169 cmd->MessageType = REMOTE_NDIS_SET_MSG;
170 cmd->MessageLength = info_len + sizeof(rndis_set_msg_t);
171 cmd->RequestId = rndis_class->request_id++;
172 cmd->Oid = oid;
173 cmd->InformationBufferLength = info_len;
174 cmd->InformationBufferOffset = 20;
175 cmd->DeviceVcHandle = 0;
176
177 memcpy(((uint8_t *)cmd + sizeof(rndis_set_msg_t)), info, info_len);
178 setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
179 setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
180 setup->wValue = 0;
181 setup->wIndex = 0;
182 setup->wLength = info_len + sizeof(rndis_set_msg_t);
183
184 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
185 if (ret < 0) {
186 USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
187 return ret;
188 }
189
190 usbh_rndis_get_notification(rndis_class);
191
192 resp = (rndis_set_cmplt_t *)g_rndis_buf;
193
194 setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
195 setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
196 setup->wValue = 0;
197 setup->wIndex = 0;
198 setup->wLength = sizeof(g_rndis_buf);
199
200 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
201 if (ret < 0) {
202 USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
203 return ret;
204 }
205
206 return ret;
207 }
208
usbh_rndis_get_connect_status(struct usbh_rndis * rndis_class)209 int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
210 {
211 int ret;
212 uint8_t data[32];
213 uint32_t data_len;
214
215 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
216 if (ret < 0) {
217 return ret;
218 }
219 if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
220 rndis_class->connect_status = true;
221 } else {
222 rndis_class->connect_status = false;
223 }
224 return 0;
225 }
226
usbh_rndis_keepalive(struct usbh_rndis * rndis_class)227 int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
228 {
229 struct usb_setup_packet *setup;
230 int ret = 0;
231 rndis_keepalive_msg_t *cmd;
232 rndis_keepalive_cmplt_t *resp;
233
234 if (!rndis_class || !rndis_class->hport) {
235 return -USB_ERR_INVAL;
236 }
237 setup = rndis_class->hport->setup;
238
239 cmd = (rndis_keepalive_msg_t *)g_rndis_buf;
240
241 cmd->MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
242 cmd->MessageLength = sizeof(rndis_keepalive_msg_t);
243 cmd->RequestId = rndis_class->request_id++;
244
245 setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
246 setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
247 setup->wValue = 0;
248 setup->wIndex = 0;
249 setup->wLength = sizeof(rndis_keepalive_msg_t);
250
251 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
252 if (ret < 0) {
253 USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
254 return ret;
255 }
256
257 usbh_rndis_get_notification(rndis_class);
258
259 resp = (rndis_keepalive_cmplt_t *)g_rndis_buf;
260
261 setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
262 setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
263 setup->wValue = 0;
264 setup->wIndex = 0;
265 setup->wLength = sizeof(g_rndis_buf);
266
267 ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
268 if (ret < 0) {
269 USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
270 return ret;
271 }
272
273 return ret;
274 }
275
usbh_rndis_connect(struct usbh_hubport * hport,uint8_t intf)276 static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
277 {
278 struct usb_endpoint_descriptor *ep_desc;
279 int ret;
280 uint32_t *oid_support_list;
281 uint32_t oid = 0;
282 uint32_t oid_num = 0;
283 uint32_t data_len;
284 uint8_t tmp_buffer[512];
285 uint8_t data[32];
286
287 struct usbh_rndis *rndis_class = &g_rndis_class;
288
289 memset(rndis_class, 0, sizeof(struct usbh_rndis));
290
291 rndis_class->hport = hport;
292 rndis_class->ctrl_intf = intf;
293 rndis_class->data_intf = intf + 1;
294
295 hport->config.intf[intf].priv = rndis_class;
296 hport->config.intf[intf + 1].priv = NULL;
297
298 // ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
299 // USBH_EP_INIT(rndis_class->intin, ep_desc);
300
301 for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
302 ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
303
304 if (ep_desc->bEndpointAddress & 0x80) {
305 USBH_EP_INIT(rndis_class->bulkin, ep_desc);
306 } else {
307 USBH_EP_INIT(rndis_class->bulkout, ep_desc);
308 }
309 }
310
311 ret = usbh_rndis_init_msg_transfer(rndis_class);
312 if (ret < 0) {
313 return ret;
314 }
315
316 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_SUPPORTED_LIST, 0, tmp_buffer, &data_len);
317 if (ret < 0) {
318 return ret;
319 }
320 oid_num = (data_len / 4);
321 USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num: %u\r\n", (unsigned int)oid_num);
322
323 oid_support_list = (uint32_t *)tmp_buffer;
324
325 for (uint8_t i = 0; i < oid_num; i++) {
326 oid = oid_support_list[i];
327 switch (oid) {
328 case OID_GEN_PHYSICAL_MEDIUM:
329 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_PHYSICAL_MEDIUM, 4, data, &data_len);
330 if (ret < 0) {
331 goto query_errorout;
332 }
333 break;
334 case OID_GEN_MAXIMUM_FRAME_SIZE:
335 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MAXIMUM_FRAME_SIZE, 4, data, &data_len);
336 if (ret < 0) {
337 goto query_errorout;
338 }
339 break;
340 case OID_GEN_LINK_SPEED:
341 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_LINK_SPEED, 4, data, &data_len);
342 if (ret < 0) {
343 goto query_errorout;
344 }
345
346 memcpy(&rndis_class->link_speed, data, 4);
347 break;
348 case OID_GEN_MEDIA_CONNECT_STATUS:
349 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
350 if (ret < 0) {
351 goto query_errorout;
352 }
353 if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
354 rndis_class->connect_status = true;
355 } else {
356 rndis_class->connect_status = false;
357 }
358 break;
359 case OID_802_3_MAXIMUM_LIST_SIZE:
360 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_MAXIMUM_LIST_SIZE, 4, data, &data_len);
361 if (ret < 0) {
362 goto query_errorout;
363 }
364 break;
365 case OID_802_3_CURRENT_ADDRESS:
366 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_CURRENT_ADDRESS, 6, data, &data_len);
367 if (ret < 0) {
368 goto query_errorout;
369 }
370
371 for (uint8_t j = 0; j < 6; j++) {
372 rndis_class->mac[j] = data[j];
373 }
374 break;
375 case OID_802_3_PERMANENT_ADDRESS:
376 ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_PERMANENT_ADDRESS, 6, data, &data_len);
377 if (ret < 0) {
378 goto query_errorout;
379 }
380 break;
381 default:
382 break;
383 }
384 }
385
386 uint32_t packet_filter = 0x0f;
387 ret = usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
388 if (ret < 0) {
389 return ret;
390 }
391
392 uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
393 ret = usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
394 if (ret < 0) {
395 return ret;
396 }
397
398 USB_LOG_INFO("rndis MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
399 rndis_class->mac[0],
400 rndis_class->mac[1],
401 rndis_class->mac[2],
402 rndis_class->mac[3],
403 rndis_class->mac[4],
404 rndis_class->mac[5]);
405
406 strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
407
408 USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
409 usbh_rndis_run(rndis_class);
410 return ret;
411 query_errorout:
412 USB_LOG_ERR("rndis query iod:%08x error\r\n", (unsigned int)oid);
413 return ret;
414 }
415
usbh_rndis_disconnect(struct usbh_hubport * hport,uint8_t intf)416 static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
417 {
418 int ret = 0;
419
420 struct usbh_rndis *rndis_class = (struct usbh_rndis *)hport->config.intf[intf].priv;
421
422 if (rndis_class) {
423 if (rndis_class->bulkin) {
424 usbh_kill_urb(&rndis_class->bulkin_urb);
425 }
426
427 if (rndis_class->bulkout) {
428 usbh_kill_urb(&rndis_class->bulkout_urb);
429 }
430
431 // if (rndis_class->intin) {
432 // usbh_kill_urb(&rndis_class->intin_urb);
433 // }
434
435 if (hport->config.intf[intf].devname[0] != '\0') {
436 usb_osal_thread_schedule_other();
437 USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
438 usbh_rndis_stop(rndis_class);
439 }
440
441 memset(rndis_class, 0, sizeof(struct usbh_rndis));
442 }
443
444 return ret;
445 }
446
usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)447 void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
448 {
449 uint32_t g_rndis_rx_length;
450 int ret;
451 uint32_t pmg_offset;
452 rndis_data_packet_t *pmsg;
453 rndis_data_packet_t temp;
454 #if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
455 uint32_t transfer_size = CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE;
456 #else
457 uint32_t transfer_size = (16 * 1024);
458 #endif
459
460 (void)CONFIG_USB_OSAL_THREAD_GET_ARGV;
461
462 USB_LOG_INFO("Create rndis rx thread\r\n");
463 // clang-format off
464 find_class:
465 // clang-format on
466 g_rndis_class.connect_status = false;
467 if (usbh_find_class_instance("/dev/rndis") == NULL) {
468 goto delete;
469 }
470
471 while (g_rndis_class.connect_status == false) {
472 ret = usbh_rndis_get_connect_status(&g_rndis_class);
473 if (ret < 0) {
474 usb_osal_msleep(100);
475 goto find_class;
476 }
477 usb_osal_msleep(128);
478 }
479
480 g_rndis_rx_length = 0;
481 while (1) {
482 usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, &g_rndis_rx_buffer[g_rndis_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
483 ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
484 if (ret < 0) {
485 break;
486 }
487
488 g_rndis_rx_length += g_rndis_class.bulkin_urb.actual_length;
489
490 /* A transfer is complete because last packet is a short packet.
491 * Short packet is not zero, match g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize).
492 * Short packet cannot be zero.
493 */
494 if (g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize)) {
495 pmg_offset = 0;
496
497 uint32_t total_len = g_rndis_rx_length;
498
499 while (g_rndis_rx_length > 0) {
500 USB_LOG_DBG("rxlen:%u\r\n", (unsigned int)g_rndis_rx_length);
501
502 pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
503
504 /* Not word-aligned case */
505 if (pmg_offset & 0x3) {
506 usb_memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
507 pmsg = &temp;
508 }
509
510 if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
511 uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
512
513 usbh_rndis_eth_input(buf, pmsg->DataLength);
514 pmg_offset += pmsg->MessageLength;
515 g_rndis_rx_length -= pmsg->MessageLength;
516
517 /* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
518 if (g_rndis_rx_length < 4) {
519 g_rndis_rx_length = 0;
520 }
521 } else {
522 USB_LOG_ERR("offset:%u,remain:%u,total:%u\r\n", (unsigned int)pmg_offset, (unsigned int)g_rndis_rx_length, (unsigned int)total_len);
523 g_rndis_rx_length = 0;
524 USB_LOG_ERR("Error rndis packet message\r\n");
525 }
526 }
527 } else {
528 #if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
529 if (g_rndis_rx_length == CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
530 #else
531 if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
532 #endif
533 USB_LOG_ERR("Rx packet is overflow, please reduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
534 while (1) {
535 }
536 }
537 }
538 }
539
540 // clang-format off
541 delete:
542 USB_LOG_INFO("Delete rndis rx thread\r\n");
543 usb_osal_thread_delete(NULL);
544 // clang-format on
545 }
546
547 uint8_t *usbh_rndis_get_eth_txbuf(void)
548 {
549 return (g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
550 }
551
552 int usbh_rndis_eth_output(uint32_t buflen)
553 {
554 rndis_data_packet_t *hdr;
555 uint32_t len;
556
557 if (g_rndis_class.connect_status == false) {
558 return -USB_ERR_NOTCONN;
559 }
560
561 hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
562 memset(hdr, 0, sizeof(rndis_data_packet_t));
563
564 hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
565 hdr->MessageLength = sizeof(rndis_data_packet_t) + buflen;
566 hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
567 hdr->DataLength = buflen;
568
569 len = hdr->MessageLength;
570 /* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
571 if (!(len % g_rndis_class.bulkout->wMaxPacketSize)) {
572 len += 1;
573 }
574
575 USB_LOG_DBG("txlen:%d\r\n", len);
576
577 usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
578 return usbh_submit_urb(&g_rndis_class.bulkout_urb);
579 }
580
581 __WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
582 {
583 (void)rndis_class;
584 }
585
586 __WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
587 {
588 (void)rndis_class;
589 }
590
591 static const struct usbh_class_driver rndis_class_driver = {
592 .driver_name = "rndis",
593 .connect = usbh_rndis_connect,
594 .disconnect = usbh_rndis_disconnect
595 };
596
597 CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
598 .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
599 .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS,
600 .bInterfaceSubClass = 0x01,
601 .bInterfaceProtocol = 0x03,
602 .id_table = NULL,
603 .class_driver = &rndis_class_driver
604 };
605