1 /****************************************************************************
2 * drivers/usbdev/rndis.c
3 *
4 * Copyright (C) 2011-2017 Gregory Nutt. All rights reserved.
5 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
6 * Authors: Sakari Kapanen <sakari.m.kapanen@gmail.com>,
7 * Petteri Aimonen <jpa@git.mail.kapsi.fi>
8 *
9 * References:
10 * [MS-RNDIS]:
11 * Remote Network Driver Interface Specification (RNDIS) Protocol
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 * 3. Neither the name NuttX nor the names of its contributors may be
24 * used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 ****************************************************************************/
41 /****************************************************************************
42 * Notice of Export Control Law
43 * ===============================================
44 * Huawei LiteOS may be subject to applicable export control laws and regulations,
45 * which might include those applicable to Huawei LiteOS of U.S. and the country in
46 * which you are located.
47 * Import, export and usage of Huawei LiteOS in any manner by you shall be in
48 * compliance with such applicable export control laws and regulations.
49 ****************************************************************************/
50
51 /****************************************************************************
52 * Included Files
53 ****************************************************************************/
54
55 #include <errno.h>
56 #include <string.h>
57 #include <stdlib.h>
58 #include <stdio.h>
59 #include <securec.h>
60
61 #include <lwip/netifapi.h>
62 #include "rndis_std.h"
63 #include "gadget/rndis.h"
64 #include "gadget/f_ether.h"
65 #include "gadget/composite.h"
66
67 /****************************************************************************
68 * Pre-processor definitions
69 ****************************************************************************/
70
71 #ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER
72 #define FRNDIS_MAX_PACKET_SIZE 0x0400
73 #else
74 #define FRNDIS_MAX_PACKET_SIZE 0x0200
75 #endif
76
77 #define WORK_AVAILABLE(work) ((work)->work_status == 0)
78 typedef uint32_t irqstate_t;
79 #define UINFO PRINT_INFO
80
81 SPIN_LOCK_INIT(g_rndis_spinlock);
enter_critical_section(void)82 static inline irqstate_t enter_critical_section(void)
83 {
84 irqstate_t flags;
85
86 LOS_SpinLockSave(&g_rndis_spinlock, &flags);
87
88 return flags;
89 }
90
leave_critical_section(irqstate_t flags)91 static inline void leave_critical_section(irqstate_t flags)
92 {
93 LOS_SpinUnlockRestore(&g_rndis_spinlock, flags);
94 }
95
96 static pthread_mutex_t rndis_mtx = PTHREAD_MUTEX_INITIALIZER;
97 #define NET_LOCK() (void)pthread_mutex_lock(&rndis_mtx)
98 #define NET_UNLOCK() (void)pthread_mutex_unlock(&rndis_mtx)
99
100 #define LINK_STATUS_EVENT_MASK (1)
101
102 #define CONFIG_NET_ETH_MTU (2048)
103 #define CONFIG_RNDIS_BULKIN_REQLEN (CONFIG_NET_ETH_MTU + RNDIS_PACKET_HDR_SIZE)
104 #define CONFIG_RNDIS_BULKOUT_REQLEN CONFIG_RNDIS_BULKIN_REQLEN
105
106 #define RNDIS_CONFIGID (1)
107 #define RNDIS_CONFIGIDNONE (0)
108
109 #define RNDIS_BUFFER_SIZE CONFIG_NET_ETH_MTU
110
111 /****************************************************************************
112 * Private Types
113 ****************************************************************************/
114
115 /* This structure describes the internal state of the driver */
116
117 struct rndis_dev_s
118 {
119 struct los_eth_driver netdev; /* Network driver structure */
120 FAR struct usbdev_s *usbdev; /* usbdev driver pointer */
121 FAR struct usbdev_ep_s *epintin; /* Interrupt IN endpoint structure */
122 FAR struct usbdev_ep_s *epbulkin; /* Bulk IN endpoint structure */
123 FAR struct usbdev_ep_s *epbulkout; /* Bulk OUT endpoint structure */
124 FAR struct usbdev_req_s *ctrlreq; /* Pointer to preallocated control request */
125 FAR struct usbdev_req_s *epintin_req; /* Pointer to preallocated interrupt in endpoint request */
126 FAR struct usbdev_req_s *rdreq; /* Pointer to Preallocated control endpoint read request */
127 struct list_head reqlist; /* List of free write request containers */
128
129 void *resp_buf; /* Used to store response messages */
130
131 bool epintin_enable; /* Interrupt endpoint enable flag */
132 bool epbulkin_enable; /* IN endpoint enable flag */
133 bool epbulkout_enable; /* OUT endpoint enable flag */
134 struct workqueue_struct *wq; /* Workqueue for TX and RX */
135 struct work_struct rxwork; /* Worker for dispatching RX packets */
136 struct work_struct pollwork; /* TX poll worker */
137
138 uint8_t config; /* USB Configuration number */
139 FAR struct usbdev_req_s *net_req; /* Pointer to request whose buffer is assigned to network */
140 FAR struct usbdev_req_s *rx_req; /* Pointer request container that holds RX buffer */
141 size_t current_rx_received; /* Number of bytes of current RX datagram received over USB */
142 size_t current_rx_datagram_size; /* Total number of bytes of the current RX datagram */
143 size_t current_rx_datagram_offset; /* Offset of current RX datagram */
144 size_t current_rx_msglen; /* Length of the entire message to be received */
145 bool rdreq_submitted; /* Indicates if the read request is submitted */
146 bool rx_blocked; /* Indicates if we can receive packets on bulk in endpoint */
147 bool ctrlreq_has_encap_response; /* Indicates if ctrlreq buffer holds a response */
148 bool connected; /* Connection status indicator */
149 uint32_t rndis_packet_filter; /* RNDIS packet filter value */
150 uint32_t rndis_host_tx_count; /* TX packet counter */
151 uint32_t rndis_host_rx_count; /* RX packet counter */
152 uint8_t host_mac_address[6]; /* Host side MAC address */
153 EVENT_CB_S link_status_event; /* Network connection event */
154 pthread_t task_id; /* Network connection status processing task */
155 atomic_t tx_transferring; /* Tx transmission flag */
156 };
157
158 /* The internal version of the class driver */
159
160 struct rndis_driver_s
161 {
162 struct usbdevclass_driver_s drvr;
163 FAR struct rndis_dev_s *dev;
164 };
165
166 /* This is what is allocated */
167
168 struct rndis_alloc_s
169 {
170 struct rndis_dev_s dev;
171 struct rndis_driver_s drvr;
172 };
173
174 /* RNDIS object ID - value pair structure */
175
176 struct rndis_oid_value_s
177 {
178 uint32_t objid;
179 uint32_t length;
180 uint32_t value;
181 FAR const void *data; /* Data pointer overrides value if non-NULL. */
182 };
183
184 /****************************************************************************
185 * Private Function Prototypes
186 ****************************************************************************/
187
188 /* Netdev driver callbacks */
189
190 static int rndis_txavail(FAR struct rndis_dev_s *dev);
191 static int rndis_transmit(FAR struct rndis_dev_s *priv);
192 static int rndis_txpoll(FAR struct rndis_dev_s *priv);
193
194 /* usbclass callbacks */
195
196 static int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
197 FAR struct usbdev_s *dev,
198 FAR const struct usb_device_request *ctrl,
199 FAR uint8_t *dataout, size_t outlen);
200 static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
201 FAR struct usbdev_s *dev);
202 static int usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
203 FAR struct usbdev_s *dev);
204 static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
205 FAR struct usbdev_s *dev);
206 static int usbclass_setconfig(FAR struct rndis_dev_s *priv, uint8_t config);
207 static void usbclass_resetconfig(FAR struct rndis_dev_s *priv);
208 static FAR struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep,
209 uint16_t len);
210 static void usbclass_freereq(FAR struct usbdev_ep_s *ep,
211 FAR struct usbdev_req_s *req);
212
213 /****************************************************************************
214 * Private Data
215 ****************************************************************************/
216
217 /* USB driver operations */
218
219 const struct usbdevclass_driverops_s g_eth_driverops =
220 {
221 usbclass_bind,
222 usbclass_unbind,
223 usbclass_setup,
224 usbclass_disconnect,
225 NULL,
226 NULL
227 };
228
229 struct rndis_hs_function_descriptor g_rndis_hs_func_desc =
230 {
231 {
232 .bLength = sizeof(struct usb_interface_assoc_descriptor),
233 .bDescriptorType = 0x0b,
234 .bInterfaceCount = 0x02,
235 .bFunctionClass = 0x02,
236 .bFunctionSubClass = 0x06,
237 .bFunctionProtocol = 0,
238 .iFunction = 6,
239 },
240 {
241 .bLength = sizeof(struct usb_interface_descriptor),
242 .bDescriptorType = UDESC_INTERFACE,
243 .bAlternateSetting = 0,
244 .bNumEndpoints = 1, /* Endpoints Num */
245 .bInterfaceClass = UDCLASS_COMM,
246 .bInterfaceSubClass = UICLASS_CDC,
247 .bInterfaceProtocol = UIPROTO_DATA_VENDOR,
248 .iInterface = 0x04
249 },
250 {
251 .bLength = sizeof(struct usb_cdc_header_desc),
252 .bDescriptorType = 0x24,
253 .bDescriptorSubType = 0,
254 HSETW(.bcdCDC, 0x0110),
255 },
256 {
257 .bLength = sizeof(struct usb_cdc_call_mgmt_descriptor),
258 .bDescriptorType = 0x24,
259 .bDescriptorSubType = 0x01,
260 .bmCapabilities = 0,
261 .bDataInterface = 0x01, /* data-interfac */
262 },
263 {
264 .bLength = sizeof(struct usb_cdc_acm_descriptor),
265 .bDescriptorType = 0x24,
266 .bDescriptorSubType = 0x02,
267 .bmCapabilities = 0,
268 },
269 {
270 .bLength = sizeof(struct usb_cdc_union_desc),
271 .bDescriptorType = 0x24,
272 .bDescriptorSubType = 0x06,
273 },
274 {
275 .bLength = sizeof(struct usb_endpoint_descriptor),
276 .bDescriptorType = UDESC_ENDPOINT,
277 .bEndpointAddress = UE_DIR_IN,
278 .bmAttributes = UE_INTERRUPT,
279 HSETW(.wMaxPacketSize, 0x0008),
280 .bInterval = 9,
281 },
282 #ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER
283 {
284 .bLength = 6,
285 .bDescriptorType = 0x30,
286 .bMaxBurst = 0,
287 .bmAttributes = 0,
288 HSETW(.wBytesPerInterval, 0x0008),
289 },
290 #endif
291 {
292 .bLength = sizeof(struct usb_interface_descriptor),
293 .bDescriptorType = UDESC_INTERFACE,
294 .bAlternateSetting = 0,
295 .bNumEndpoints = 2, /* Endpoints Num */
296 .bInterfaceClass = UICLASS_CDC_DATA,
297 .bInterfaceSubClass = 0, /* interface subclass */
298 .bInterfaceProtocol = 0, /* interface protocol */
299 .iInterface = 5,
300 },
301 {
302 .bLength = sizeof(struct usb_endpoint_descriptor),
303 .bDescriptorType = UDESC_ENDPOINT,
304 .bEndpointAddress = UE_DIR_IN,
305 .bmAttributes = UE_BULK,
306 HSETW(.wMaxPacketSize, FRNDIS_MAX_PACKET_SIZE),
307 .bInterval = 0,
308 },
309 #ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER
310 {
311 .bLength = 6,
312 .bDescriptorType = 0x30,
313 .bMaxBurst = 0,
314 .bmAttributes = 0,
315 .wBytesPerInterval = {0x00}
316 },
317 #endif
318 {
319 .bLength = sizeof(struct usb_endpoint_descriptor),
320 .bDescriptorType = UDESC_ENDPOINT,
321 .bEndpointAddress = UE_DIR_OUT,
322 .bmAttributes = UE_BULK,
323 HSETW(.wMaxPacketSize, FRNDIS_MAX_PACKET_SIZE),
324 .bInterval = 0,
325 },
326 #ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER
327 {
328 .bLength = 6,
329 .bDescriptorType = 0x30,
330 .bMaxBurst = 0,
331 .bmAttributes = 0,
332 .wBytesPerInterval = {0x00}
333 },
334 #endif
335 };
336
337 struct usb_config_descriptor g_rndis_hs_config_desc =
338 {
339 .bLength = USB_CONFIG_DESC_SIZE,
340 .bDescriptorType = UDESC_CONFIG,
341 HSETW(.wTotalLength, USB_CONFIG_DESC_SIZE + sizeof(g_rndis_hs_func_desc)),
342 .bNumInterface = 2,
343 .bConfigurationValue = 1,
344 .iConfiguration = 0,
345 .bmAttributes = UC_SELF_POWERED | UC_BUS_POWERED,
346 .bMaxPower = 1, /* max power */
347 };
348
349 struct rndis_hs_descriptor g_rndis_hs_desc =
350 {
351 .rndis_config = &g_rndis_hs_config_desc,
352 .rndis_func = &g_rndis_hs_func_desc
353 };
354
355 /* These lists give dummy responses to be returned to PC. The values are
356 * chosen so that Windows is happy - other operating systems don't really care
357 * much.
358 */
359
360 static const uint32_t g_rndis_supported_oids[] =
361 {
362 RNDIS_OID_GEN_SUPPORTED_LIST,
363 RNDIS_OID_GEN_HARDWARE_STATUS,
364 RNDIS_OID_GEN_MEDIA_SUPPORTED,
365 RNDIS_OID_GEN_MEDIA_IN_USE,
366 RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
367 RNDIS_OID_GEN_LINK_SPEED,
368 RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE,
369 RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE,
370 RNDIS_OID_GEN_VENDOR_ID,
371 RNDIS_OID_GEN_VENDOR_DESCRIPTION,
372 RNDIS_OID_GEN_VENDOR_DRIVER_VERSION,
373 RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
374 RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE,
375 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
376 RNDIS_OID_GEN_PHYSICAL_MEDIUM,
377 RNDIS_OID_GEN_XMIT_OK,
378 RNDIS_OID_GEN_RCV_OK,
379 RNDIS_OID_GEN_XMIT_ERROR,
380 RNDIS_OID_GEN_RCV_ERROR,
381 RNDIS_OID_GEN_RCV_NO_BUFFER,
382 RNDIS_OID_802_3_PERMANENT_ADDRESS,
383 RNDIS_OID_802_3_CURRENT_ADDRESS,
384 RNDIS_OID_802_3_MULTICAST_LIST,
385 RNDIS_OID_802_3_MAC_OPTIONS,
386 RNDIS_OID_802_3_MAXIMUM_LIST_SIZE,
387 RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT,
388 RNDIS_OID_802_3_XMIT_ONE_COLLISION,
389 RNDIS_OID_802_3_XMIT_MORE_COLLISION,
390 };
391
392 static const struct rndis_oid_value_s g_rndis_oid_values[] =
393 {
394 {RNDIS_OID_GEN_SUPPORTED_LIST, sizeof(g_rndis_supported_oids), 0, g_rndis_supported_oids},
395 {RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE, 4, CONFIG_NET_ETH_MTU, NULL},
396 #ifdef CONFIG_USBDEV_DUALSPEED
397 {RNDIS_OID_GEN_LINK_SPEED, 4, 100000, NULL},
398 #else
399 {RNDIS_OID_GEN_LINK_SPEED, 4, 2000000, NULL},
400 #endif
401 {RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE, 4, CONFIG_NET_ETH_MTU, NULL},
402 {RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE, 4, CONFIG_NET_ETH_MTU, NULL},
403 {RNDIS_OID_GEN_VENDOR_ID, 4, 0x00FFFFFF, NULL},
404 {RNDIS_OID_GEN_VENDOR_DESCRIPTION, 6, 0, "RNDIS"},
405 {RNDIS_OID_GEN_CURRENT_PACKET_FILTER, 4, 0, NULL},
406 {RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE, 4, 2048, NULL},
407 {RNDIS_OID_GEN_XMIT_OK, 4, 0, NULL},
408 {RNDIS_OID_GEN_RCV_OK, 4, 0, NULL},
409 {RNDIS_OID_802_3_PERMANENT_ADDRESS, 6, 0, NULL},
410 {RNDIS_OID_802_3_CURRENT_ADDRESS, 6, 0, NULL},
411 {RNDIS_OID_802_3_MULTICAST_LIST, 4, 0xE0000000, NULL},
412 {RNDIS_OID_802_3_MAXIMUM_LIST_SIZE, 4, 1, NULL},
413 {0x0, 4, 0, NULL}, /* Default fallback */
414 };
415
416 /****************************************************************************
417 * Private Data
418 ****************************************************************************/
419
link_status_check_func(struct rndis_dev_s * dev)420 static void link_status_check_func(struct rndis_dev_s *dev)
421 {
422 int link_status;
423 struct netif *netif = &dev->netdev.ac_if;
424
425 link_status = dev->connected;
426 if (netif_is_up(netif) && !link_status)
427 {
428 (void)netifapi_netif_set_link_down(netif);
429 (void)netifapi_netif_set_down(netif);
430 dprintf("set usb rndis network link down!\n");
431 }
432 else if (!netif_is_up(netif) && link_status)
433 {
434 (void)netifapi_netif_set_link_up(netif);
435 (void)netifapi_netif_set_up(netif);
436 dprintf("set usb rndis network link up!\n");
437 }
438 }
439
link_status_check_thread(UINTPTR para)440 static void link_status_check_thread(UINTPTR para)
441 {
442 struct rndis_dev_s *dev = (struct rndis_dev_s *)para;
443
444 for (;;)
445 {
446 (void)LOS_EventRead(&dev->link_status_event, LINK_STATUS_EVENT_MASK, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
447
448 link_status_check_func(dev);
449 }
450 }
451
link_status_check_init(struct rndis_dev_s * dev)452 static void link_status_check_init(struct rndis_dev_s *dev)
453 {
454 #define LINK_STATUS_TASK_PRI 10
455 uint32_t ret;
456
457 (void)LOS_EventInit(&dev->link_status_event);
458 ret = usb_os_task_creat(&dev->task_id, (TSK_ENTRY_FUNC)link_status_check_thread, LINK_STATUS_TASK_PRI, "USB_Status_Task", (UINTPTR)(dev));
459 if (ret)
460 {
461 (void)LOS_EventDestroy(&dev->link_status_event);
462 return;
463 }
464 }
465
link_status_check_deinit(struct rndis_dev_s * dev)466 static void link_status_check_deinit(struct rndis_dev_s *dev)
467 {
468 (void)usb_os_task_delete(dev->task_id);
469 (void)LOS_EventDestroy(&dev->link_status_event);
470 }
471
link_status_change(struct rndis_dev_s * dev)472 static void link_status_change(struct rndis_dev_s *dev)
473 {
474 (void)LOS_EventWrite(&dev->link_status_event, LINK_STATUS_EVENT_MASK);
475 }
476
477 /****************************************************************************
478 * Buffering of data is implemented in the following manner:
479 *
480 * RNDIS driver holds a number of preallocated bulk IN endpoint write
481 * requests along with buffers large enough to hold an Ethernet packet and
482 * the corresponding RNDIS header.
483 *
484 * One of these is always reserved for packet reception - when data arrives
485 * on the bulk OUT endpoint, it is copied to the reserved request buffer.
486 * When the reception of an Ethernet packet is complete, a worker to process
487 * the packet is scheduled and bulk OUT endpoint is set to NAK.
488 *
489 * The processing worker passes the buffer to the network. When the network is
490 * done processing the packet, the buffer might contain data to be sent.
491 * If so, the corresponding write request is queued on the bulk IN endpoint.
492 * The NAK state on bulk OUT endpoint is cleared to allow new packets to
493 * arrive. If there's no data to send, the request is returned to the list of
494 * free requests.
495 *
496 * When a bulk IN write operation is complete, the request is added to the
497 * list of free requests.
498 *
499 ****************************************************************************/
500
501 /****************************************************************************
502 * Name: rndis_submit_rdreq
503 *
504 * Description:
505 * Submits the bulk OUT read request. Takes care not to submit the request
506 * when the RX packet buffer is already in use.
507 *
508 * Input Parameters:
509 * priv: pointer to RNDIS device driver structure
510 *
511 * Returned Value:
512 * The return value of the EP_SUBMIT operation
513 *
514 ****************************************************************************/
515
rndis_submit_rdreq(FAR struct rndis_dev_s * priv)516 static int rndis_submit_rdreq(FAR struct rndis_dev_s *priv)
517 {
518 int ret = OK;
519
520 if (!priv->rdreq_submitted && !priv->rx_blocked)
521 {
522 priv->rdreq->len = CONFIG_RNDIS_BULKOUT_REQLEN;
523 priv->epbulkout->handle_req = priv->rdreq;
524
525 ret = EP_SUBMIT(priv->epbulkout, priv->rdreq);
526 if (ret != OK)
527 {
528 usb_err("%s %d, len:%u\n", __FUNCTION__, __LINE__, priv->rdreq->len);
529 }
530 else
531 {
532 priv->rdreq_submitted = true;
533 }
534 }
535
536 return ret;
537 }
538
539 /****************************************************************************
540 * Name: rndis_cancel_rdreq
541 *
542 * Description:
543 * Cancels the bulk OUT endpoint read request.
544 *
545 * Input Parameters:
546 * priv: pointer to RNDIS device driver structure
547 *
548 ****************************************************************************/
549
rndis_cancel_rdreq(FAR struct rndis_dev_s * priv)550 static void rndis_cancel_rdreq(FAR struct rndis_dev_s *priv)
551 {
552 if (priv->rdreq_submitted)
553 {
554 EP_CANCEL(priv->epbulkout, priv->rdreq);
555 priv->rdreq_submitted = false;
556 }
557 }
558
559 /****************************************************************************
560 * Name: rndis_block_rx
561 *
562 * Description:
563 * Blocks reception of further bulk OUT endpoint data.
564 *
565 * Input Parameters:
566 * priv: pointer to RNDIS device driver structure
567 *
568 ****************************************************************************/
569
rndis_block_rx(FAR struct rndis_dev_s * priv)570 static void rndis_block_rx(FAR struct rndis_dev_s *priv)
571 {
572 priv->rx_blocked = true;
573 rndis_cancel_rdreq(priv);
574 }
575
576 /****************************************************************************
577 * Name: rndis_unblock_rx
578 *
579 * Description:
580 * Unblocks reception of bulk OUT endpoint data.
581 *
582 * Input Parameters:
583 * priv: pointer to RNDIS device driver structure
584 *
585 * Assumptions:
586 * Called from critical section
587 *
588 ****************************************************************************/
589
rndis_unblock_rx(FAR struct rndis_dev_s * priv)590 static void rndis_unblock_rx(FAR struct rndis_dev_s *priv)
591 {
592 priv->rx_blocked = false;
593 }
594
595 /****************************************************************************
596 * Name: rndis_allocwrreq
597 *
598 * Description:
599 * Allocates a bulk IN endpoint request from the list of free request
600 * buffers.
601 *
602 * Input Parameters:
603 * priv: pointer to RNDIS device driver structure
604 *
605 * Returned Value:
606 * NULL if allocation failed; pointer to allocated request if succeeded
607 *
608 * Assumptions:
609 * Called from critical section
610 *
611 ****************************************************************************/
612
rndis_allocwrreq(FAR struct rndis_dev_s * priv)613 static FAR struct usbdev_req_s *rndis_allocwrreq(FAR struct rndis_dev_s *priv)
614 {
615 struct usbdev_req_s *req;
616
617 req = usbclass_allocreq(priv->epbulkin, CONFIG_RNDIS_BULKIN_REQLEN);
618 if (req == NULL)
619 {
620 return NULL;
621 }
622
623 return req;
624 }
625
626 /****************************************************************************
627 * Name: rndis_hasfreereqs
628 *
629 * Description:
630 * Checks if there are free requests usable for TX data.
631 *
632 * Input Parameters:
633 * priv: pointer to RNDIS device driver structure
634 *
635 * Returned Value:
636 * true if requests available; false if no requests available
637 *
638 * Assumptions:
639 * Called from critical section
640 *
641 ****************************************************************************/
642
rndis_hasfreereqs(FAR struct rndis_dev_s * priv)643 static bool rndis_hasfreereqs(FAR struct rndis_dev_s *priv)
644 {
645 return list_empty(&priv->reqlist) ? true : false;
646 }
647
648 /****************************************************************************
649 * Name: rndis_freewrreq
650 *
651 * Description:
652 * Returns a bulk IN endpoint write requests to the list of free requests.
653 *
654 * Input Parameters:
655 * priv: pointer to RNDIS device driver structure
656 * req: pointer to the request
657 *
658 * Assumptions:
659 * Called with interrupts disabled.
660 *
661 ****************************************************************************/
662
rndis_freewrreq(FAR struct rndis_dev_s * priv,FAR struct usbdev_req_s * req)663 static void rndis_freewrreq(FAR struct rndis_dev_s *priv,
664 FAR struct usbdev_req_s *req)
665 {
666 DEBUGASSERT(req != NULL);
667
668 usbclass_freereq(priv->epbulkin, req);
669 rndis_submit_rdreq(priv);
670 }
671
672 /****************************************************************************
673 * Name: rndis_allocnetreq
674 *
675 * Description:
676 * Allocates a request buffer to be used on the network.
677 *
678 * Input Parameters:
679 * priv: pointer to RNDIS device driver structure
680 *
681 * Returned Value:
682 * true if succeeded; false if failed
683 *
684 * Assumptions:
685 * Caller holds the network lock
686 *
687 ****************************************************************************/
688
rndis_allocnetreq(FAR struct rndis_dev_s * priv)689 static bool rndis_allocnetreq(FAR struct rndis_dev_s *priv)
690 {
691 irqstate_t flags = enter_critical_section();
692
693 if (rndis_hasfreereqs(priv))
694 {
695 leave_critical_section(flags);
696 return false;
697 }
698
699 if (atomic_read(&priv->tx_transferring))
700 {
701 leave_critical_section(flags);
702 return false;
703 }
704
705 priv->net_req = list_first_entry(&priv->reqlist, struct usbdev_req_s, list);
706 list_del_init(&priv->net_req->list);
707
708 atomic_set(&priv->tx_transferring, 1);
709 leave_critical_section(flags);
710 return priv->net_req != NULL;
711 }
712
713 /****************************************************************************
714 * Name: rndis_sendnetreq
715 *
716 * Description:
717 * Submits the request buffer held by the network.
718 *
719 * Input Parameters:
720 * priv: pointer to RNDIS device driver structure
721 *
722 * Assumptions:
723 * Caller holds the network lock
724 *
725 ****************************************************************************/
726
rndis_sendnetreq(FAR struct rndis_dev_s * priv)727 static void rndis_sendnetreq(FAR struct rndis_dev_s *priv)
728 {
729 irqstate_t flags = enter_critical_section();
730
731 DEBUGASSERT(priv->net_req != NULL);
732
733 priv->net_req->priv = priv->net_req;
734 priv->epbulkin->handle_req = priv->net_req;
735 EP_SUBMIT(priv->epbulkin, priv->net_req);
736
737 priv->net_req = NULL;
738
739 leave_critical_section(flags);
740 }
741
742 /****************************************************************************
743 * Name: rndis_freenetreq
744 *
745 * Description:
746 * Frees the request buffer held by the network.
747 *
748 * Input Parameters:
749 * priv: pointer to RNDIS device driver structure
750 *
751 * Assumptions:
752 * Caller holds the network lock
753 *
754 ****************************************************************************/
755
rndis_freenetreq(FAR struct rndis_dev_s * priv)756 static void rndis_freenetreq(FAR struct rndis_dev_s *priv)
757 {
758 irqstate_t flags = enter_critical_section();
759
760 rndis_freewrreq(priv, priv->net_req);
761 priv->net_req = NULL;
762
763 leave_critical_section(flags);
764 }
765
766 /****************************************************************************
767 * Name: rndis_allocrxreq
768 *
769 * Description:
770 * Allocates a buffer for packet reception if there already isn't one.
771 *
772 * Input Parameters:
773 * priv: pointer to RNDIS device driver structure
774 *
775 * Returned Value:
776 * true if succeeded; false if failed
777 *
778 * Assumptions:
779 * Called from critical section
780 *
781 ****************************************************************************/
782
rndis_allocrxreq(FAR struct rndis_dev_s * priv)783 static bool rndis_allocrxreq(FAR struct rndis_dev_s *priv)
784 {
785 if (priv->rx_req != NULL)
786 {
787 return true;
788 }
789
790 priv->rx_req = rndis_allocwrreq(priv);
791 return priv->rx_req != NULL;
792 }
793
794 /****************************************************************************
795 * Name: rndis_giverxreq
796 *
797 * Description:
798 * Passes the RX packet buffer to the network
799 *
800 * Input Parameters:
801 * priv: pointer to RNDIS device driver structure
802 *
803 * Assumptions:
804 * Caller holds the network lock
805 *
806 ****************************************************************************/
807
rndis_giverxreq(FAR struct rndis_dev_s * priv)808 static void rndis_giverxreq(FAR struct rndis_dev_s *priv)
809 {
810 DEBUGASSERT(priv->rx_req != NULL);
811 DEBUGASSERT(priv->net_req == NULL);
812
813 priv->net_req = priv->rx_req;
814 priv->rx_req = NULL;
815 }
816
817 /****************************************************************************
818 * Name: rndis_fillrequest
819 *
820 * Description:
821 * Fills the RNDIS header to the request buffer
822 *
823 * Input Parameters:
824 * priv: pointer to RNDIS device driver structure
825 * req: the request whose buffer we should fill
826 *
827 * Returned Value:
828 * The total length of the request data
829 *
830 * Assumptions:
831 * Caller holds the network lock
832 *
833 ****************************************************************************/
834
rndis_fillrequest(FAR struct rndis_dev_s * priv,FAR struct usbdev_req_s * req)835 static uint16_t rndis_fillrequest(FAR struct rndis_dev_s *priv,
836 FAR struct usbdev_req_s *req)
837 {
838 size_t datalen = req->len - RNDIS_PACKET_HDR_SIZE;
839
840 if (datalen > 0)
841 {
842 /* Send the required headers */
843
844 FAR struct rndis_packet_msg *msg = (FAR struct rndis_packet_msg *)req->buf;
845 (void)memset_s(msg, RNDIS_PACKET_HDR_SIZE, 0, RNDIS_PACKET_HDR_SIZE);
846
847 msg->msgtype = RNDIS_PACKET_MSG;
848 msg->msglen = RNDIS_PACKET_HDR_SIZE + datalen;
849 msg->dataoffset = RNDIS_PACKET_HDR_SIZE - 8;
850 msg->datalen = datalen;
851
852 req->flags = USBDEV_REQFLAGS_NULLPKT;
853 }
854
855 return req->len;
856 }
857
858 /****************************************************************************
859 * Name: rndis_rxdispatch
860 *
861 * Description:
862 * Processes the received Ethernet packet. Called from work queue.
863 *
864 * Input Parameters:
865 * arg: pointer to RNDIS device driver structure
866 *
867 ****************************************************************************/
868
rndis_rxdispatch(FAR struct work_struct * arg)869 static void rndis_rxdispatch(FAR struct work_struct *arg)
870 {
871 FAR struct rndis_dev_s *priv = (FAR struct rndis_dev_s *)arg->data;
872 irqstate_t flags;
873
874 NET_LOCK();
875 flags = enter_critical_section();
876 rndis_giverxreq(priv);
877 leave_critical_section(flags);
878
879 if (priv->net_req == NULL)
880 {
881 return;
882 }
883
884 eth_rx(&priv->netdev, priv->net_req);
885
886 priv->current_rx_datagram_size = 0;
887 rndis_unblock_rx(priv);
888
889 rndis_freenetreq(priv);
890 NET_UNLOCK();
891 }
892
893 /****************************************************************************
894 * Name: rndis_txpoll
895 *
896 * Description:
897 * Sends the packet that is stored in the network packet buffer. Called
898 * from work queue by e.g. txavail and txpoll callbacks.
899 *
900 * Input Parameters:
901 * dev: pointer to network driver structure
902 *
903 * Assumptions:
904 * Caller holds the network lock
905 *
906 ****************************************************************************/
907
rndis_txpoll(FAR struct rndis_dev_s * priv)908 static int rndis_txpoll(FAR struct rndis_dev_s *priv)
909 {
910 int ret = OK;
911
912 if (!priv->connected)
913 {
914 return -EBUSY;
915 }
916
917 if (priv->net_req->len > 0)
918 {
919 ret = rndis_transmit(priv);
920 }
921
922 /* If zero is returned, the polling will continue until all connections have
923 * been examined.
924 */
925
926 return ret;
927 }
928
929 /****************************************************************************
930 * Name: rndis_transmit
931 *
932 * Description:
933 * Start hardware transmission.
934 *
935 ****************************************************************************/
936
rndis_transmit(FAR struct rndis_dev_s * priv)937 static int rndis_transmit(FAR struct rndis_dev_s *priv)
938 {
939 /* Queue the packet */
940
941 rndis_fillrequest(priv, priv->net_req);
942 rndis_sendnetreq(priv);
943
944 return OK;
945 }
946
947 /****************************************************************************
948 * Name: rndis_txavail_work
949 *
950 * Description:
951 * txavail worker function
952 *
953 ****************************************************************************/
954
rndis_txavail_work(FAR struct work_struct * arg)955 static void rndis_txavail_work(FAR struct work_struct *arg)
956 {
957 FAR struct rndis_dev_s *priv = (FAR struct rndis_dev_s *)arg->data;
958
959 NET_LOCK();
960
961 if (rndis_allocnetreq(priv))
962 {
963 rndis_txpoll(priv);
964 }
965
966 NET_UNLOCK();
967 }
968
969 /****************************************************************************
970 * Name: rndis_txavail
971 *
972 * Description:
973 * Network txavail callback that's called when there are buffers available
974 * for sending data. May be called from an interrupt, so we must queue a
975 * worker to do the actual processing.
976 *
977 ****************************************************************************/
978
rndis_txavail(FAR struct rndis_dev_s * priv)979 static int rndis_txavail(FAR struct rndis_dev_s *priv)
980 {
981 bool ret;
982
983 if (WORK_AVAILABLE(&priv->pollwork))
984 {
985 ret = queue_work(priv->wq, &priv->pollwork);
986 if (ret == false) {
987 usb_err("queue work failed!\n");
988 }
989 }
990
991 return OK;
992 }
993
994 /************************************************************************************
995 * Name: rndis_recvpacket
996 *
997 * Description:
998 * Handles a USB packet arriving on the data bulk out endpoint.
999 *
1000 * Assumptions:
1001 * Called from the USB interrupt handler with interrupts disabled.
1002 *
1003 ************************************************************************************/
1004
rndis_recvpacket(FAR struct rndis_dev_s * priv,FAR uint8_t * reqbuf,uint16_t reqlen)1005 static inline int rndis_recvpacket(FAR struct rndis_dev_s *priv,
1006 FAR uint8_t *reqbuf, uint16_t reqlen)
1007 {
1008 int ret;
1009
1010 if (!rndis_allocrxreq(priv))
1011 {
1012 return -ENOMEM;
1013 }
1014
1015 if (!priv->connected)
1016 {
1017 return -EBUSY;
1018 }
1019
1020 if (!priv->current_rx_datagram_size)
1021 {
1022 if (reqlen < 16)
1023 {
1024 /* Packet too small to contain a message header */
1025 }
1026 else
1027 {
1028 /* The packet contains a RNDIS packet message header */
1029
1030 FAR struct rndis_packet_msg *msg = (FAR struct rndis_packet_msg *)reqbuf;
1031 if (msg->msgtype == RNDIS_PACKET_MSG)
1032 {
1033 priv->current_rx_received = reqlen;
1034 priv->current_rx_datagram_size = msg->datalen;
1035 priv->current_rx_msglen = msg->msglen;
1036
1037 /* According to RNDIS-over-USB send, if the message length is a
1038 * multiple of endpoint max packet size, the host must send an
1039 * additional single-byte zero packet. Take that in account here.
1040 */
1041
1042 if ((priv->current_rx_msglen % priv->epbulkout->maxpacket) == 0)
1043 {
1044 priv->current_rx_msglen += 1;
1045 }
1046
1047 /* Data offset is defined as an offset from the beginning of the
1048 * offset field itself
1049 */
1050
1051 priv->current_rx_datagram_offset = msg->dataoffset + 8;
1052 if (priv->current_rx_datagram_offset < reqlen)
1053 {
1054 ret = memcpy_s(&priv->rx_req->buf[RNDIS_PACKET_HDR_SIZE],
1055 CONFIG_RNDIS_BULKIN_REQLEN - RNDIS_PACKET_HDR_SIZE,
1056 &reqbuf[priv->current_rx_datagram_offset],
1057 reqlen - priv->current_rx_datagram_offset);
1058 if (ret != EOK)
1059 {
1060 usb_err("memcpy failed!\n");
1061 return -ENOMEM;
1062 }
1063 }
1064 }
1065 else
1066 {
1067 usb_err("Unknown RNDIS message type %u\n", msg->msgtype);
1068 }
1069 }
1070 }
1071 else
1072 {
1073 if (priv->current_rx_received >= priv->current_rx_datagram_offset &&
1074 priv->current_rx_received <= priv->current_rx_datagram_size +
1075 priv->current_rx_datagram_offset)
1076 {
1077 size_t index = priv->current_rx_received - priv->current_rx_datagram_offset;
1078 size_t copysize = min(reqlen, priv->current_rx_datagram_size - index);
1079
1080 /* Check if the received packet exceeds request buffer */
1081
1082 if ((RNDIS_PACKET_HDR_SIZE + index + copysize) <= CONFIG_NET_ETH_MTU)
1083 {
1084 ret = memcpy_s(&priv->rx_req->buf[RNDIS_PACKET_HDR_SIZE + index],
1085 CONFIG_RNDIS_BULKIN_REQLEN - RNDIS_PACKET_HDR_SIZE - index,
1086 reqbuf, copysize);
1087 if (ret != EOK)
1088 {
1089 usb_err("memcpy failed!\n");
1090 return -ENOMEM;
1091 }
1092 }
1093 else
1094 {
1095 usb_err("The packet exceeds request buffer (reqlen=%u) \n", reqlen);
1096 }
1097 }
1098 priv->current_rx_received += reqlen;
1099 }
1100
1101 if (priv->current_rx_received >= priv->current_rx_msglen)
1102 {
1103 /* Check for a usable packet length (4 added for the CRC) */
1104
1105 if (priv->current_rx_datagram_size > (CONFIG_NET_ETH_MTU + 4) ||
1106 priv->current_rx_datagram_size <= (sizeof(struct eth_hdr) + 4))
1107 {
1108 priv->current_rx_datagram_size = 0;
1109 }
1110 else
1111 {
1112 priv->rx_req->xfrd = priv->current_rx_received;
1113
1114 ret = queue_work(priv->wq, &priv->rxwork);
1115 DEBUGASSERT(ret == 0);
1116 UNUSED(ret);
1117
1118 rndis_block_rx(priv);
1119 priv->rndis_host_tx_count++;
1120 return -EBUSY;
1121 }
1122 }
1123
1124 return OK;
1125 }
1126
1127 /****************************************************************************
1128 * Name: rndis_prepare_response
1129 *
1130 * Description:
1131 * Passes the RX packet buffer to the network
1132 *
1133 * Input Parameters:
1134 * priv: pointer to RNDIS device driver structure
1135 *
1136 * Assumptions:
1137 * Called from critical section
1138 *
1139 ****************************************************************************/
1140
rndis_prepare_response(FAR struct rndis_dev_s * priv,size_t size,FAR struct rndis_command_header * request_hdr)1141 static bool rndis_prepare_response(FAR struct rndis_dev_s *priv, size_t size,
1142 FAR struct rndis_command_header *request_hdr)
1143 {
1144 FAR struct rndis_response_header *hdr;
1145 priv->resp_buf = malloc(size);
1146 if (!priv->resp_buf)
1147 {
1148 usb_err("malloc fail!\n");
1149 return false;
1150 }
1151
1152 hdr = (FAR struct rndis_response_header *)priv->resp_buf;
1153
1154 hdr->msgtype = request_hdr->msgtype | RNDIS_MSG_COMPLETE;
1155 hdr->msglen = size;
1156 hdr->reqid = request_hdr->reqid;
1157 hdr->status = RNDIS_STATUS_SUCCESS;
1158
1159 priv->ctrlreq_has_encap_response = true;
1160
1161 return true;
1162 }
1163
1164 /****************************************************************************
1165 * Name: rndis_send_encapsulated_response
1166 *
1167 * Description:
1168 * Give a notification to the host that there is an encapsulated response
1169 * available.
1170 *
1171 * Input Parameters:
1172 * priv: pointer to RNDIS device driver structure
1173 *
1174 * Assumptions:
1175 * Called from critical section
1176 *
1177 ****************************************************************************/
1178
rndis_send_encapsulated_response(FAR struct rndis_dev_s * priv)1179 static int rndis_send_encapsulated_response(FAR struct rndis_dev_s *priv)
1180 {
1181 FAR struct rndis_notification *notif =
1182 (FAR struct rndis_notification *)priv->epintin_req->buf;
1183
1184 notif->notification = RNDIS_NOTIFICATION_RESPONSE_AVAILABLE;
1185 notif->reserved = 0;
1186 priv->epintin_req->len = sizeof(struct rndis_notification);
1187 priv->epintin->handle_req = priv->epintin_req;
1188
1189 EP_SUBMIT(priv->epintin, priv->epintin_req);
1190
1191 return OK;
1192 }
1193
1194 /****************************************************************************
1195 * Name: rndis_handle_control_message
1196 *
1197 * Description:
1198 * Handle a RNDIS control message.
1199 *
1200 * Input Parameters:
1201 * ctrlreq: pointer to RNDIS control request
1202 *
1203 * Assumptions:
1204 * Called from critical section
1205 *
1206 ****************************************************************************/
1207
rndis_handle_control_message(struct usbdev_ep_s * ep,struct usbdev_req_s * ctrlreq)1208 static void rndis_handle_control_message(struct usbdev_ep_s *ep, struct usbdev_req_s *ctrlreq)
1209 {
1210 FAR struct rndis_dev_s *priv = (struct rndis_dev_s *)ctrlreq->priv;
1211 FAR struct rndis_command_header *cmd_hdr =
1212 (FAR struct rndis_command_header *)ctrlreq->buf;
1213 int ret;
1214 bool resp_flag;
1215
1216 (void)ep;
1217
1218 switch (cmd_hdr->msgtype)
1219 {
1220 case RNDIS_INITIALIZE_MSG:
1221 {
1222 UINFO("rndis initialize msg!\n");
1223 FAR struct rndis_initialize_cmplt *resp;
1224
1225 resp_flag = rndis_prepare_response(priv, sizeof(struct rndis_initialize_cmplt), cmd_hdr);
1226 if (!resp_flag)
1227 {
1228 return;
1229 }
1230
1231 resp = (FAR struct rndis_initialize_cmplt *)priv->resp_buf;
1232
1233 resp->major = RNDIS_MAJOR_VERSION;
1234 resp->minor = RNDIS_MINOR_VERSION;
1235 resp->devflags = RNDIS_DEVICEFLAGS;
1236 resp->medium = RNDIS_MEDIUM_802_3;
1237 resp->pktperxfer = 1;
1238 resp->xfrsize = (4 + 44 + 22) + RNDIS_BUFFER_SIZE;
1239 resp->pktalign = 2;
1240
1241 rndis_send_encapsulated_response(priv);
1242 }
1243 break;
1244
1245 case RNDIS_HALT_MSG:
1246 {
1247 UINFO("rndis halt msg disconnect!\n");
1248 priv->connected = false;
1249 }
1250 break;
1251
1252 case RNDIS_QUERY_MSG:
1253 {
1254 int i;
1255 size_t max_reply_size = sizeof(struct rndis_query_cmplt) +
1256 sizeof(g_rndis_supported_oids);
1257 FAR struct rndis_query_msg req;
1258 ret = memcpy_s(&req, sizeof(struct rndis_query_msg), ctrlreq->buf, sizeof(struct rndis_query_msg));
1259 if (ret != EOK)
1260 {
1261 usb_err("memcpy failed!\n");
1262 return;
1263 }
1264
1265 resp_flag = rndis_prepare_response(priv, max_reply_size, cmd_hdr);
1266 if (!resp_flag)
1267 {
1268 return;
1269 }
1270
1271 FAR struct rndis_query_cmplt *resp =
1272 (FAR struct rndis_query_cmplt *)priv->resp_buf;
1273
1274 resp->hdr.msglen = sizeof(struct rndis_query_cmplt);
1275 resp->bufoffset = 0;
1276 resp->buflen = 0;
1277 resp->hdr.status = RNDIS_STATUS_NOT_SUPPORTED;
1278
1279 for (i = 0;
1280 i < sizeof(g_rndis_oid_values)/sizeof(g_rndis_oid_values[0]);
1281 i++)
1282 {
1283 bool match = (g_rndis_oid_values[i].objid == req.objid);
1284
1285 if (!match && g_rndis_oid_values[i].objid == 0)
1286 {
1287 int j;
1288
1289 /* Check whether to apply the fallback entry */
1290
1291 for (j = 0; j < sizeof(g_rndis_supported_oids)/sizeof(uint32_t); j++)
1292 {
1293 if (g_rndis_supported_oids[j] == req.objid)
1294 {
1295 match = true;
1296 break;
1297 }
1298 }
1299 }
1300
1301 if (match)
1302 {
1303 resp->hdr.status = RNDIS_STATUS_SUCCESS;
1304 resp->bufoffset = 16;
1305 resp->buflen = g_rndis_oid_values[i].length;
1306
1307 if (req.objid == RNDIS_OID_GEN_CURRENT_PACKET_FILTER)
1308 {
1309 resp->buffer[0] = priv->rndis_packet_filter;
1310 }
1311 else if (req.objid == RNDIS_OID_GEN_XMIT_OK)
1312 {
1313 resp->buffer[0] = priv->rndis_host_tx_count;
1314 }
1315 else if (req.objid == RNDIS_OID_GEN_RCV_OK)
1316 {
1317 resp->buffer[0] = priv->rndis_host_rx_count;
1318 }
1319 else if (req.objid == RNDIS_OID_802_3_CURRENT_ADDRESS ||
1320 req.objid == RNDIS_OID_802_3_PERMANENT_ADDRESS)
1321 {
1322 ret = memcpy_s(resp->buffer, USB_COMP_EP0_BUFSIZ - sizeof(struct rndis_query_cmplt),
1323 priv->host_mac_address, 6);
1324 if (ret != EOK)
1325 {
1326 usb_err("memcpy failed!\n");
1327 return;
1328 }
1329 }
1330 else if (g_rndis_oid_values[i].data)
1331 {
1332 ret = memcpy_s(resp->buffer, USB_COMP_EP0_BUFSIZ - sizeof(struct rndis_query_cmplt),
1333 g_rndis_oid_values[i].data, resp->buflen);
1334 if (ret != EOK)
1335 {
1336 usb_err("memcpy failed!\n");
1337 return;
1338 }
1339 }
1340 else
1341 {
1342 ret = memcpy_s(resp->buffer, USB_COMP_EP0_BUFSIZ - sizeof(struct rndis_query_cmplt),
1343 &g_rndis_oid_values[i].value, resp->buflen);
1344 if (ret != EOK)
1345 {
1346 usb_err("memcpy failed!\n");
1347 return;
1348 }
1349 }
1350 break;
1351 }
1352 }
1353
1354 resp->hdr.msglen += resp->buflen;
1355
1356 rndis_send_encapsulated_response(priv);
1357 }
1358 break;
1359
1360 case RNDIS_SET_MSG:
1361 {
1362 FAR struct rndis_set_msg *req;
1363 FAR struct rndis_response_header *resp;
1364
1365 req = malloc(USB_DWC_MAX_PACKET_SIZE);
1366 if (!req)
1367 {
1368 usb_err("malloc fail!\n");
1369 return;
1370 }
1371 (void)memcpy_s(req, USB_DWC_MAX_PACKET_SIZE, ctrlreq->buf, USB_DWC_MAX_PACKET_SIZE);
1372
1373 resp_flag = rndis_prepare_response(priv, sizeof(struct rndis_response_header),
1374 cmd_hdr);
1375 if (!resp_flag)
1376 {
1377 free(req);
1378 return;
1379 }
1380
1381 resp = (FAR struct rndis_response_header *)priv->resp_buf;
1382
1383 if (req->objid == RNDIS_OID_GEN_CURRENT_PACKET_FILTER)
1384 {
1385 priv->rndis_packet_filter = req->buffer[0];
1386
1387 if (req->buffer[0] == 0)
1388 {
1389 UINFO("rndis set msg disconnect!\n");
1390 priv->connected = false;
1391 }
1392 else
1393 {
1394 UINFO("RNDIS is now connected\n");
1395 priv->connected = true;
1396 link_status_change(priv);
1397 }
1398 }
1399 else if (req->objid == RNDIS_OID_802_3_MULTICAST_LIST)
1400 {
1401 UINFO("RNDIS multicast list ignored\n");
1402 }
1403 else
1404 {
1405 resp->status = RNDIS_STATUS_NOT_SUPPORTED;
1406 }
1407
1408 rndis_send_encapsulated_response(priv);
1409 free(req);
1410 }
1411 break;
1412
1413 case RNDIS_RESET_MSG:
1414 {
1415 FAR struct rndis_reset_cmplt *resp;
1416
1417 resp_flag = rndis_prepare_response(priv, sizeof(struct rndis_reset_cmplt),
1418 cmd_hdr);
1419 if (!resp_flag)
1420 {
1421 return;
1422 }
1423
1424 resp = (FAR struct rndis_reset_cmplt *)priv->resp_buf;
1425 resp->addreset = 0;
1426 priv->connected = false;
1427 UINFO("rndis reset msg disconnect!\n");
1428 rndis_send_encapsulated_response(priv);
1429 }
1430 break;
1431
1432 case RNDIS_KEEPALIVE_MSG:
1433 {
1434 UINFO("rndis keepalive msg!\n");
1435 resp_flag = rndis_prepare_response(priv, sizeof(struct rndis_response_header),
1436 cmd_hdr);
1437 if (!resp_flag)
1438 {
1439 return;
1440 }
1441
1442 rndis_send_encapsulated_response(priv);
1443 }
1444 break;
1445
1446 default:
1447 usb_err("Unsupported RNDIS control message: %u\n", cmd_hdr->msgtype);
1448 }
1449 }
1450
1451 /****************************************************************************
1452 * Name: rndis_rdcomplete
1453 *
1454 * Description:
1455 * Handle completion of read request on the bulk OUT endpoint.
1456 *
1457 ****************************************************************************/
1458
rndis_rdcomplete(FAR struct usbdev_ep_s * ep,FAR struct usbdev_req_s * req)1459 static void rndis_rdcomplete(FAR struct usbdev_ep_s *ep,
1460 FAR struct usbdev_req_s *req)
1461 {
1462 FAR struct rndis_dev_s *priv;
1463 irqstate_t flags;
1464 int ret;
1465
1466 /* Sanity check */
1467
1468 #ifdef CONFIG_DEBUG_FEATURES
1469 if (!ep || !ep->priv || !req)
1470 {
1471 return;
1472 }
1473 #endif
1474
1475 /* Extract references to private data */
1476
1477 priv = (FAR struct rndis_dev_s *)ep->priv;
1478
1479 /* Process the received data unless this is some unusual condition */
1480
1481 ret = OK;
1482
1483 flags = enter_critical_section();
1484 priv->rdreq_submitted = false;
1485
1486 switch (req->result)
1487 {
1488 case 0: /* Normal completion */
1489 ret = rndis_recvpacket(priv, req->buf, (uint16_t)req->xfrd);
1490 DEBUGASSERT(ret != -ENOMEM);
1491 break;
1492
1493 case -ESHUTDOWN: /* Disconnection */
1494 leave_critical_section(flags);
1495 return;
1496
1497 default: /* Some other error occurred */
1498 break;
1499 };
1500
1501 if (ret == OK)
1502 {
1503 rndis_submit_rdreq(priv);
1504 }
1505
1506 leave_critical_section(flags);
1507 }
1508
1509 /****************************************************************************
1510 * Name: rndis_wrcomplete
1511 *
1512 * Description:
1513 * Handle completion of write request. This function probably executes
1514 * in the context of an interrupt handler.
1515 *
1516 ****************************************************************************/
1517
rndis_wrcomplete(FAR struct usbdev_ep_s * ep,FAR struct usbdev_req_s * req)1518 static void rndis_wrcomplete(FAR struct usbdev_ep_s *ep,
1519 FAR struct usbdev_req_s *req)
1520 {
1521 FAR struct rndis_dev_s *priv;
1522 FAR struct usbdev_req_s *req_wr;
1523 irqstate_t flags;
1524
1525 /* Sanity check */
1526
1527 #ifdef CONFIG_DEBUG_FEATURES
1528 if (!ep || !ep->priv || !req || !req->priv)
1529 {
1530 return;
1531 }
1532 #endif
1533
1534 /* Extract references to our private data */
1535
1536 priv = (FAR struct rndis_dev_s *)ep->priv;
1537 req_wr = (FAR struct usbdev_req_s *)req->priv;
1538
1539 /* Return the write request to the free list */
1540
1541 flags = enter_critical_section();
1542
1543 switch (req_wr->result)
1544 {
1545 case OK: /* Normal completion */
1546 atomic_set(&priv->tx_transferring, 0);
1547 priv->rndis_host_rx_count++;
1548 break;
1549
1550 case -ESHUTDOWN: /* Disconnection */
1551 break;
1552
1553 default: /* Some other error occurred */
1554 break;
1555 }
1556
1557 rndis_freewrreq(priv, req_wr);
1558 priv->epbulkin->handle_req = NULL;
1559 if (!rndis_hasfreereqs(priv))
1560 {
1561 (void)rndis_txavail(priv);
1562 }
1563
1564 leave_critical_section(flags);
1565 }
1566
1567 /****************************************************************************
1568 * Name: usbclass_ep0incomplete
1569 *
1570 * Description:
1571 * Handle completion of EP0 control operations
1572 *
1573 ****************************************************************************/
1574
usbclass_ep0incomplete(FAR struct usbdev_ep_s * ep,FAR struct usbdev_req_s * req)1575 static void usbclass_ep0incomplete(FAR struct usbdev_ep_s *ep,
1576 FAR struct usbdev_req_s *req)
1577 {
1578 (void)ep;
1579
1580 if (req->result)
1581 {
1582 usb_err("result:%d, xfrd:%u, len:%u\n", req->result, req->xfrd, req->len);
1583 }
1584 else if (req->len > 0)
1585 {
1586 struct rndis_dev_s *priv = (FAR struct rndis_dev_s *)req->priv;
1587 priv->ctrlreq_has_encap_response = false;
1588 }
1589 }
1590
1591 /****************************************************************************
1592 * Name: usbclass_ep0incomplete
1593 *
1594 * Description:
1595 * Handle completion of interrupt IN endpoint operations
1596 *
1597 ****************************************************************************/
1598
usbclass_epintin_complete(FAR struct usbdev_ep_s * ep,FAR struct usbdev_req_s * req)1599 static void usbclass_epintin_complete(FAR struct usbdev_ep_s *ep,
1600 FAR struct usbdev_req_s *req)
1601 {
1602 if (req->result || req->xfrd != req->len)
1603 {
1604 usb_err("result:%d, xfrd:%u, len:%u\n", req->result, req->xfrd, req->len);
1605 }
1606 }
1607
1608 /****************************************************************************
1609 * Name: usbclass_freereq
1610 *
1611 * Description:
1612 * Free a request instance along with its buffer
1613 *
1614 ****************************************************************************/
1615
usbclass_freereq(FAR struct usbdev_ep_s * ep,FAR struct usbdev_req_s * req)1616 static void usbclass_freereq(FAR struct usbdev_ep_s *ep,
1617 FAR struct usbdev_req_s *req)
1618 {
1619 if (ep != NULL && req != NULL)
1620 {
1621 if (req->buf != NULL)
1622 {
1623 EP_FREEBUFFER(ep, req->buf);
1624 }
1625
1626 EP_FREEREQ(ep, req);
1627 }
1628 }
1629
1630 /****************************************************************************
1631 * Name: usbclass_allocreq
1632 *
1633 * Description:
1634 * Allocate a request instance along with its buffer
1635 *
1636 ****************************************************************************/
1637
usbclass_allocreq(FAR struct usbdev_ep_s * ep,uint16_t len)1638 static FAR struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep,
1639 uint16_t len)
1640 {
1641 FAR struct usbdev_req_s *req;
1642
1643 req = EP_ALLOCREQ(ep);
1644 if (req != NULL)
1645 {
1646 req->len = len;
1647 req->buf = EP_ALLOCBUFFER(ep, len);
1648
1649 if (req->buf == NULL)
1650 {
1651 EP_FREEREQ(ep, req);
1652 req = NULL;
1653 }
1654 }
1655
1656 return req;
1657 }
1658
1659 /****************************************************************************
1660 * Name: usbclass_bind
1661 *
1662 * Description:
1663 * Invoked when the driver is bound to a USB device driver
1664 *
1665 ****************************************************************************/
1666
usbclass_bind(FAR struct usbdevclass_driver_s * driver,FAR struct usbdev_s * dev)1667 static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
1668 FAR struct usbdev_s *dev)
1669 {
1670 FAR struct rndis_dev_s *priv = ((FAR struct rndis_driver_s *)driver)->dev;
1671 struct composite_devobj_s *devobj;
1672 struct usbdev_devinfo_s *devinfo;
1673 struct composite_dev_s *cdev;
1674 uint16_t reqlen;
1675 int ret;
1676
1677 /* Bind the structures */
1678
1679 priv->usbdev = dev;
1680
1681 cdev = dev->ep0->priv;
1682 if (cdev == NULL)
1683 {
1684 usb_err("rndis eth bind failed!\n");
1685 return -1;
1686 }
1687
1688 devobj = usbclass_devobj_get(cdev, DEV_ETHERNET);
1689 if (devobj == NULL)
1690 {
1691 return -1;
1692 }
1693 devinfo = &devobj->compdesc.devinfo;
1694
1695 /* Preallocate control request */
1696
1697 priv->ctrlreq = cdev->ctrlreq;
1698 if (priv->ctrlreq == NULL)
1699 {
1700 ret = -ENOMEM;
1701 goto errout;
1702 }
1703
1704 /* Pre-allocate all endpoints... the endpoints will not be functional
1705 * until the SET CONFIGURATION request is processed in usbclass_setconfig.
1706 * This is done here because there may be calls to kmm_malloc and the SET
1707 * CONFIGURATION processing probably occurrs within interrupt handling
1708 * logic where kmm_malloc calls will fail.
1709 */
1710
1711 priv->epintin = DEV_ALLOCEP(dev, g_rndis_hs_func_desc.nepd.bEndpointAddress,
1712 (struct usb_endpoint_descriptor *)&g_rndis_hs_func_desc.nepd);
1713 if (!priv->epintin)
1714 {
1715 ret = -ENODEV;
1716 goto errout;
1717 }
1718 RNDIS_MKEPINTIN(devinfo) = priv->epintin->eplog;
1719 priv->epintin->priv = priv;
1720 priv->epintin_enable = false;
1721
1722 priv->epintin_req = usbclass_allocreq(priv->epintin, sizeof(struct rndis_notification));
1723 if (priv->epintin_req == NULL)
1724 {
1725 ret = -ENOMEM;
1726 goto errout;
1727 }
1728
1729 priv->epintin_req->callback = usbclass_epintin_complete;
1730
1731 priv->epbulkin = DEV_ALLOCEP(dev, g_rndis_hs_func_desc.iepd.bEndpointAddress,
1732 (struct usb_endpoint_descriptor *)&g_rndis_hs_func_desc.iepd);
1733 if (!priv->epbulkin)
1734 {
1735 ret = -ENODEV;
1736 goto errout;
1737 }
1738 RNDIS_MKEPBULKIN(devinfo) = priv->epbulkin->eplog;
1739 priv->epbulkin->handle_req = NULL;
1740 priv->epbulkin->priv = priv;
1741 priv->epbulkin_enable = false;
1742
1743 priv->epbulkout = DEV_ALLOCEP(dev, g_rndis_hs_func_desc.oepd.bEndpointAddress,
1744 (struct usb_endpoint_descriptor *)&g_rndis_hs_func_desc.oepd);
1745 if (!priv->epbulkout)
1746 {
1747 ret = -ENODEV;
1748 goto errout;
1749 }
1750 RNDIS_MKEPBULKOUT(devinfo) = priv->epbulkout->eplog;
1751 priv->epbulkout->priv = priv;
1752 priv->epbulkout_enable = false;
1753
1754 /* Pre-allocate read requests. The buffer size is one full packet. */
1755
1756 reqlen = 64;
1757 if (CONFIG_RNDIS_BULKOUT_REQLEN > reqlen)
1758 {
1759 reqlen = CONFIG_RNDIS_BULKOUT_REQLEN;
1760 }
1761
1762 priv->rdreq = usbclass_allocreq(priv->epbulkout, reqlen);
1763 if (priv->rdreq == NULL)
1764 {
1765 ret = -ENOMEM;
1766 goto errout;
1767 }
1768
1769 priv->rdreq->callback = rndis_rdcomplete;
1770
1771 g_rndis_hs_func_desc.ifcad.bFirstInterface = (uint8_t)devinfo->ifnobase;
1772 g_rndis_hs_func_desc.ifcd.bInterfaceNumber = (uint8_t)devinfo->ifnobase;
1773 g_rndis_hs_func_desc.cdc_union_desc.bMasterInterface0 = (uint8_t)devinfo->ifnobase;
1774
1775 g_rndis_hs_func_desc.ifdd.bInterfaceNumber = (uint8_t)(devinfo->ifnobase + 1);
1776 g_rndis_hs_func_desc.cdc_union_desc.bSlaveInterface0 = (uint8_t)(devinfo->ifnobase + 1);
1777
1778 /* Report if we are selfpowered */
1779
1780 #ifdef CONFIG_USBDEV_SELFPOWERED
1781 DEV_SETSELFPOWERED(dev);
1782 #endif
1783
1784 INIT_WORK(&priv->rxwork, rndis_rxdispatch);
1785 priv->rxwork.data = (atomic_long_t)priv;
1786 INIT_WORK(&priv->pollwork, rndis_txavail_work);
1787 priv->pollwork.data = (atomic_long_t)priv;
1788 priv->wq = create_workqueue("rndis workqueue");
1789 if (!priv->wq)
1790 {
1791 ret = -EFAULT;
1792 goto errout;
1793 }
1794
1795 priv->connected = false;
1796 netdev_register(&priv->netdev);
1797
1798 link_status_check_init(priv);
1799
1800 /* And pull-up the data line for the soft connect function */
1801
1802 DEV_CONNECT(dev);
1803 return OK;
1804
1805 errout:
1806 (void)usbclass_unbind(driver, dev);
1807 return ret;
1808 }
1809
1810 /****************************************************************************
1811 * Name: usbclass_unbind
1812 *
1813 * Description:
1814 * Invoked when the driver is unbound from a USB device driver
1815 *
1816 ****************************************************************************/
1817
usbclass_unbind(FAR struct usbdevclass_driver_s * driver,FAR struct usbdev_s * dev)1818 static int usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
1819 FAR struct usbdev_s *dev)
1820 {
1821 FAR struct rndis_dev_s *priv;
1822
1823 #ifdef CONFIG_DEBUG_FEATURES
1824 if (!driver || !dev || !dev->ep0)
1825 {
1826 return -1;
1827 }
1828 #endif
1829
1830 /* Extract reference to private data */
1831
1832 priv = ((FAR struct rndis_driver_s *)driver)->dev;
1833
1834 #ifdef CONFIG_DEBUG_FEATURES
1835 if (!priv)
1836 {
1837 return -1;
1838 }
1839 #endif
1840
1841 /* Make sure that we are not already unbound */
1842
1843 if (priv != NULL)
1844 {
1845 destroy_workqueue(priv->wq);
1846 priv->wq = NULL;
1847
1848 /* Make sure that the endpoints have been unconfigured. If
1849 * we were terminated gracefully, then the configuration should
1850 * already have been reset. If not, then calling usbclass_resetconfig
1851 * should cause the endpoints to immediately terminate all
1852 * transfers and return the requests to us (with result == -ESHUTDOWN)
1853 */
1854
1855 usbclass_resetconfig(priv);
1856 mdelay(50);
1857
1858 netdev_unregister(&priv->netdev);
1859
1860 link_status_check_deinit(priv);
1861
1862 /* Free the bulk IN endpoint */
1863
1864 if (priv->epbulkin)
1865 {
1866 DEV_FREEEP(dev, priv->epbulkin);
1867 priv->epbulkin = NULL;
1868 }
1869
1870 /* Free the pre-allocated control request */
1871
1872 if (priv->ctrlreq != NULL)
1873 {
1874 priv->ctrlreq = NULL;
1875 }
1876
1877 if (priv->epintin_req != NULL)
1878 {
1879 usbclass_freereq(priv->epintin, priv->epintin_req);
1880 priv->epintin_req = NULL;
1881 }
1882
1883 /* Free the interrupt IN endpoint */
1884
1885 if (priv->epintin)
1886 {
1887 DEV_FREEEP(dev, priv->epintin);
1888 priv->epintin = NULL;
1889 }
1890
1891 /* Free pre-allocated read requests (which should all have
1892 * been returned to the free list at this time -- we don't check)
1893 */
1894
1895 if (priv->rdreq)
1896 {
1897 usbclass_freereq(priv->epbulkout, priv->rdreq);
1898 priv->rdreq = NULL;
1899 }
1900
1901 /* Free the bulk OUT endpoint */
1902
1903 if (priv->epbulkout)
1904 {
1905 DEV_FREEEP(dev, priv->epbulkout);
1906 priv->epbulkout = NULL;
1907 }
1908 }
1909
1910 return 0;
1911 }
1912
1913 /****************************************************************************
1914 * Name: usbclass_setup
1915 *
1916 * Description:
1917 * Invoked for ep0 control requests. This function probably executes
1918 * in the context of an interrupt handler.
1919 *
1920 ****************************************************************************/
1921
usbclass_setup(FAR struct usbdevclass_driver_s * driver,FAR struct usbdev_s * dev,FAR const struct usb_device_request * ctrl,FAR uint8_t * dataout,size_t outlen)1922 static int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
1923 FAR struct usbdev_s *dev,
1924 FAR const struct usb_device_request *ctrl,
1925 FAR uint8_t *dataout, size_t outlen)
1926 {
1927 FAR struct rndis_dev_s *priv;
1928 FAR struct usbdev_req_s *ctrlreq;
1929 uint16_t value;
1930 uint16_t len;
1931 int ret = -EOPNOTSUPP;
1932
1933 (void)dataout;
1934 (void)outlen;
1935
1936 #ifdef CONFIG_DEBUG_FEATURES
1937 if (!driver || !dev || !dev->ep0 || !ctrl)
1938 {
1939 return -EIO;
1940 }
1941 #endif
1942
1943 /* Extract reference to private data */
1944
1945 priv = ((FAR struct rndis_driver_s *)driver)->dev;
1946
1947 #ifdef CONFIG_DEBUG_FEATURES
1948 if (!priv || !priv->ctrlreq || !priv->resp_buf)
1949 {
1950 return -ENODEV;
1951 }
1952 #endif
1953 ctrlreq = priv->ctrlreq;
1954
1955 /* Extract the little-endian 16-bit values to host order */
1956
1957 value = UGETW(ctrl->wValue);
1958 len = UGETW(ctrl->wLength);
1959
1960 switch (ctrl->bmRequestType & USB_TYPE_MASK)
1961 {
1962 /***********************************************************************
1963 * Standard Requests
1964 ***********************************************************************/
1965
1966 case USB_TYPE_STANDARD:
1967 {
1968 switch (ctrl->bRequest)
1969 {
1970 case USB_REQ_SET_CONFIGURATION:
1971 case USB_REQ_SET_INTERFACE:
1972 {
1973 if (ctrl->bmRequestType == 0)
1974 {
1975 return usbclass_setconfig(priv, value);
1976 }
1977 }
1978 break;
1979
1980 default:
1981 usb_err("Request is not supported!\n");
1982 break;
1983 }
1984 }
1985 break;
1986
1987 /* Class requests */
1988
1989 case USB_TYPE_CLASS:
1990 {
1991 if ((ctrl->bmRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE)
1992 {
1993 if (ctrl->bRequest == RNDIS_SEND_ENCAPSULATED_COMMAND)
1994 {
1995 ctrlreq->callback = rndis_handle_control_message;
1996 ctrlreq->priv = priv;
1997 ret = len;
1998 }
1999 else if (ctrl->bRequest == RNDIS_GET_ENCAPSULATED_RESPONSE)
2000 {
2001 if (!priv->ctrlreq_has_encap_response)
2002 {
2003 ret = 1;
2004 ctrlreq->buf[0] = 0;
2005 }
2006 else
2007 {
2008 FAR struct rndis_response_header *hdr =
2009 (FAR struct rndis_response_header *)priv->resp_buf;
2010
2011 /* Msglen represents the length of the message
2012 * to be sent to the USB host.
2013 */
2014
2015 ret = memcpy_s(ctrlreq->buf, hdr->msglen, priv->resp_buf, hdr->msglen);
2016 if (ret != EOK)
2017 {
2018 usb_err("memcpy failed!\n");
2019 free(priv->resp_buf);
2020 priv->resp_buf = NULL;
2021 return ret;
2022 }
2023 ret = hdr->msglen;
2024 ctrlreq->callback = usbclass_ep0incomplete;
2025 ctrlreq->priv = priv;
2026 free(priv->resp_buf);
2027 priv->resp_buf = NULL;
2028 }
2029 }
2030 }
2031 }
2032 break;
2033
2034 default:
2035 break;
2036 }
2037
2038 /* Respond to the setup command if data was returned. On an error return
2039 * value (ret < 0), the USB driver will stall.
2040 */
2041
2042 if (ret >= 0)
2043 {
2044 ctrlreq->len = min(len, (uint32_t)ret);
2045 ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
2046 ret = EP_SUBMIT(dev->ep0, ctrlreq);
2047 if (ret < 0)
2048 {
2049 ctrlreq->result = OK;
2050 usbclass_ep0incomplete(dev->ep0, ctrlreq);
2051 }
2052 }
2053
2054 return ret;
2055 }
2056
2057 /****************************************************************************
2058 * Name: usbclass_disconnect
2059 *
2060 * Description:
2061 * Invoked after all transfers have been stopped, when the host is
2062 * disconnected. This function is probably called from the context of an
2063 * interrupt handler.
2064 *
2065 ****************************************************************************/
2066
usbclass_disconnect(FAR struct usbdevclass_driver_s * driver,FAR struct usbdev_s * dev)2067 static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
2068 FAR struct usbdev_s *dev)
2069 {
2070 FAR struct rndis_dev_s *priv;
2071
2072 #ifdef CONFIG_DEBUG_FEATURES
2073 if (!driver || !dev || !dev->ep0)
2074 {
2075 return;
2076 }
2077 #endif
2078
2079 /* Extract reference to private data */
2080
2081 priv = ((FAR struct rndis_driver_s *)driver)->dev;
2082
2083 #ifdef CONFIG_DEBUG_FEATURES
2084 if (!priv)
2085 {
2086 return;
2087 }
2088 #endif
2089
2090 /* Reset the configuration */
2091
2092 usbclass_resetconfig(priv);
2093
2094 /* Perform the soft connect function so that we will we can be
2095 * re-enumerated.
2096 */
2097
2098 DEV_CONNECT(dev);
2099 }
2100
2101 /****************************************************************************
2102 * Name: usbclass_resetconfig
2103 *
2104 * Description:
2105 * Mark the device as not configured and disable all endpoints.
2106 *
2107 ****************************************************************************/
2108
usbclass_resetconfig(FAR struct rndis_dev_s * priv)2109 static void usbclass_resetconfig(FAR struct rndis_dev_s *priv)
2110 {
2111 struct usbdev_req_s *req;
2112 irqstate_t flags;
2113
2114 link_status_change(priv);
2115
2116 /* Disable endpoints. This should force completion of all pending
2117 * transfers.
2118 */
2119
2120 if (priv->epintin_enable == true)
2121 {
2122 EP_DISABLE(priv->epintin);
2123 priv->epintin_enable = false;
2124 }
2125 if (priv->epbulkin_enable == true)
2126 {
2127 EP_DISABLE(priv->epbulkin);
2128 priv->epbulkin_enable = false;
2129 }
2130 if (priv->epbulkout_enable == true)
2131 {
2132 EP_DISABLE(priv->epbulkout);
2133 priv->epbulkout_enable = false;
2134 }
2135
2136 flags = enter_critical_section();
2137
2138 /* Are we configured? */
2139
2140 if (priv->config != RNDIS_CONFIGIDNONE)
2141 {
2142 /* Yes.. but not anymore */
2143
2144 priv->config = RNDIS_CONFIGIDNONE;
2145
2146 priv->connected = false;
2147
2148 if (priv->resp_buf != NULL)
2149 {
2150 free(priv->resp_buf);
2151 priv->resp_buf = NULL;
2152 }
2153
2154 /* Free write requests that are not in use (which should be all
2155 * of them
2156 */
2157
2158 req = priv->epbulkin->handle_req;
2159 if (req != NULL)
2160 {
2161 usbclass_freereq(priv->epbulkin, req);
2162 priv->epbulkin->handle_req = NULL;
2163 }
2164
2165 if (priv->net_req)
2166 {
2167 usbclass_freereq(priv->epbulkout, priv->net_req);
2168 priv->net_req = NULL;
2169 }
2170
2171 if (priv->rx_req)
2172 {
2173 usbclass_freereq(priv->epbulkout, priv->rx_req);
2174 priv->rx_req = NULL;
2175 }
2176
2177 while (!list_empty(&priv->reqlist))
2178 {
2179 req = list_first_entry(&priv->reqlist, struct usbdev_req_s, list);
2180 list_del_init(&req->list);
2181
2182 if (req->priv != NULL)
2183 {
2184 req->priv = NULL;
2185 }
2186 usbclass_freereq(priv->epbulkin, req);
2187 }
2188 atomic_set(&priv->tx_transferring, 0);
2189 }
2190 leave_critical_section(flags);
2191 }
2192
2193 /****************************************************************************
2194 * Name: usbclass_setconfig
2195 *
2196 * Description:
2197 * Set the device configuration by allocating and configuring endpoints and
2198 * by allocating and queue read and write requests.
2199 *
2200 ****************************************************************************/
2201
usbclass_setconfig(FAR struct rndis_dev_s * priv,uint8_t config)2202 static int usbclass_setconfig(FAR struct rndis_dev_s *priv, uint8_t config)
2203 {
2204 struct usbdev_s *dev;
2205 int ret;
2206
2207 #ifdef CONFIG_DEBUG_FEATURES
2208 if (priv == NULL)
2209 {
2210 return -EIO;
2211 }
2212 #endif
2213
2214 if (config == priv->config)
2215 {
2216 /* Already configured -- Do nothing */
2217
2218 return 0;
2219 }
2220
2221 /* Discard the previous configuration data */
2222
2223 usbclass_resetconfig(priv);
2224
2225 /* Was this a request to simply discard the current configuration? */
2226
2227 if (config == RNDIS_CONFIGIDNONE)
2228 {
2229 return 0;
2230 }
2231
2232 /* We only accept one configuration */
2233
2234 if (config != RNDIS_CONFIGID)
2235 {
2236 return -EINVAL;
2237 }
2238 dev = priv->usbdev;
2239
2240 /* Configure the IN interrupt endpoint */
2241
2242 ret = EP_CONFIGURE(priv->epintin, &g_rndis_hs_func_desc.nepd, false);
2243 if (ret < 0)
2244 {
2245 goto errout;
2246 }
2247
2248 priv->epintin->priv = priv;
2249 priv->epintin_enable = true;
2250
2251 /* Configure the IN bulk endpoint */
2252
2253 usbd_configep_byspeed(dev, &g_rndis_hs_func_desc.iepd);
2254 ret = EP_CONFIGURE(priv->epbulkin, &g_rndis_hs_func_desc.iepd, false);
2255 if (ret < 0)
2256 {
2257 goto errout;
2258 }
2259
2260 priv->epbulkin->priv = priv;
2261 priv->epbulkin_enable = true;
2262
2263 /* Configure the OUT bulk endpoint */
2264
2265 usbd_configep_byspeed(dev, &g_rndis_hs_func_desc.oepd);
2266 ret = EP_CONFIGURE(priv->epbulkout, &g_rndis_hs_func_desc.oepd, true);
2267 if (ret < 0)
2268 {
2269 goto errout;
2270 }
2271
2272 priv->epbulkout->priv = priv;
2273 priv->epbulkout_enable = true;
2274
2275 /* Queue read requests in the bulk OUT endpoint */
2276
2277 priv->rdreq->callback = rndis_rdcomplete;
2278
2279 ret = rndis_submit_rdreq(priv);
2280 if (ret != OK)
2281 {
2282 goto errout;
2283 }
2284
2285 /* We are successfully configured */
2286
2287 priv->config = config;
2288
2289 link_status_change(priv);
2290 return OK;
2291
2292 errout:
2293 usbclass_resetconfig(priv);
2294 return ret;
2295 }
2296
rndis_tx(struct los_eth_driver * sc,const struct eth_drv_sg * sg_list,int sg_len,uint32_t total_len,UINTPTR key)2297 void rndis_tx(struct los_eth_driver *sc, const struct eth_drv_sg *sg_list,
2298 int sg_len, uint32_t total_len, UINTPTR key)
2299 {
2300 struct rndis_dev_s *dev = (struct rndis_dev_s *)sc->driver_context;
2301 struct usbdev_req_s *req;
2302 irqstate_t flags;
2303 uint8_t *d_buf;
2304 uint32_t len = 0;
2305 int ret;
2306 int i;
2307
2308 (void)key;
2309
2310 req = usbclass_allocreq(dev->epbulkin, (uint16_t)(total_len + RNDIS_PACKET_HDR_SIZE));
2311 if (req == NULL)
2312 {
2313 usb_err("alloc req failed!\n");
2314 return;
2315 }
2316 req->priv = req;
2317 req->callback = rndis_wrcomplete;
2318 req->len = total_len + RNDIS_PACKET_HDR_SIZE;
2319
2320 d_buf = &req->buf[RNDIS_PACKET_HDR_SIZE];
2321 for (i = 0; i < sg_len; i++)
2322 {
2323 ret = memcpy_s((void *)(d_buf + len), total_len - len, (const void *)(sg_list[i].buf), sg_list[i].len);
2324 if (ret != EOK)
2325 {
2326 usb_err("memcpy fail, ret = %d\n", ret);
2327 return;
2328 }
2329 len += sg_list[i].len;
2330 }
2331
2332 flags = enter_critical_section();
2333
2334 if (dev->connected == false)
2335 {
2336 leave_critical_section(flags);
2337 usbclass_freereq(dev->epbulkin, req);
2338 return;
2339 }
2340
2341 list_add_tail(&req->list, &dev->reqlist);
2342
2343 (void)rndis_txavail(dev);
2344 leave_critical_section(flags);
2345 }
2346
rndis_classobject(int minor,struct usbdev_devinfo_s * devinfo,struct usbdevclass_driver_s ** devclass_drvr)2347 int rndis_classobject(int minor, struct usbdev_devinfo_s *devinfo,
2348 struct usbdevclass_driver_s **devclass_drvr)
2349 {
2350 FAR struct rndis_alloc_s *alloc;
2351 FAR struct rndis_dev_s *priv;
2352 FAR struct rndis_driver_s *drvr;
2353
2354 (void)minor;
2355 (void)devinfo;
2356
2357 /* Allocate the structures needed */
2358
2359 alloc = (FAR struct rndis_alloc_s *)malloc(sizeof(struct rndis_alloc_s));
2360 if (!alloc)
2361 {
2362 return -ENOMEM;
2363 }
2364
2365 /* Convenience pointers into the allocated blob */
2366
2367 priv = &alloc->dev;
2368 drvr = &alloc->drvr;
2369
2370 /* Initialize the USB ethernet driver structure */
2371
2372 (void)memset_s(priv, sizeof(struct rndis_dev_s), 0, sizeof(struct rndis_dev_s));
2373 INIT_LIST_HEAD(&priv->reqlist);
2374 eth_random_addr(priv->host_mac_address);
2375
2376 (void)memset_s(&priv->netdev, sizeof(struct los_eth_driver), 0, sizeof(struct los_eth_driver));
2377 priv->netdev.driver_context = priv;
2378
2379 /* Initialize the USB class driver structure */
2380
2381 drvr->drvr.speed = USB_SPEED_HIGH;
2382 drvr->drvr.ops = &g_eth_driverops;
2383 drvr->dev = priv;
2384 *devclass_drvr = &drvr->drvr;
2385
2386 return 0;
2387 }
2388
rndis_uninitialize(struct usbdevclass_driver_s * devclass_drvr)2389 void rndis_uninitialize(struct usbdevclass_driver_s *devclass_drvr)
2390 {
2391 struct rndis_driver_s *drvr = (struct rndis_driver_s *)devclass_drvr;
2392 struct rndis_dev_s *priv;
2393 struct rndis_alloc_s *alloc;
2394
2395 if (drvr == NULL)
2396 {
2397 return;
2398 }
2399
2400 priv = drvr->dev;
2401 if (priv == NULL)
2402 {
2403 return;
2404 }
2405
2406 alloc = container_of(drvr, struct rndis_alloc_s, drvr);
2407
2408 free(alloc);
2409 }
2410
usbdev_rndis_initialize_sub(struct composite_devdesc_s * dev,int ifnobase,int minor)2411 void usbdev_rndis_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor)
2412 {
2413 /* Ask the ETH driver to fill in the constants we didn't
2414 * know here.
2415 */
2416
2417 rndis_get_composite_devdesc(dev);
2418
2419 /* Overwrite and correct some values... */
2420 /* The callback functions for the ETH class */
2421
2422 dev->classobject = rndis_classobject;
2423 dev->uninitialize = rndis_uninitialize;
2424
2425 /* Interfaces */
2426
2427 dev->devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */
2428 dev->minor = minor; /* The minor interface number */
2429
2430 /* Strings */
2431
2432 dev->devinfo.strbase = 0; /* Offset to String Numbers */
2433 }
2434
usbdev_rndis_initialize(struct module * mod,int n,void * arg)2435 int usbdev_rndis_initialize(struct module *mod, int n, void *arg)
2436 {
2437 struct composite_softc *com_s = (struct composite_softc *)arg;
2438 struct composite_devdesc_s dev;
2439 int ret;
2440
2441 (void)mod;
2442 (void)n;
2443
2444 if (com_s == NULL)
2445 {
2446 PRINTK(" ** Rndis device initialized failed! **\n");
2447 return -1;
2448 }
2449 usbdev_rndis_initialize_sub(&dev, 0, DEV_ETHERNET);
2450
2451 ret = composite_initialize(com_s, 1, &dev);
2452 if (ret < 0)
2453 {
2454 PRINTK(" ** Rndis device initialized failed! **\n");
2455 return -1;
2456 }
2457 PRINTK(" ** Rndis device initialized successfully! **\n");
2458 return 0;
2459 }
2460