• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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