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) 78typedef uint32_t irqstate_t; 79#define UINFO PRINT_INFO 80 81SPIN_LOCK_INIT(g_rndis_spinlock); 82static 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 91static inline void leave_critical_section(irqstate_t flags) 92{ 93 LOS_SpinUnlockRestore(&g_rndis_spinlock, flags); 94} 95 96static 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 117struct 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 160struct 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 168struct 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 176struct 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 190static int rndis_txavail(FAR struct rndis_dev_s *dev); 191static int rndis_transmit(FAR struct rndis_dev_s *priv); 192static int rndis_txpoll(FAR struct rndis_dev_s *priv); 193 194/* usbclass callbacks */ 195 196static 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); 200static int usbclass_bind(FAR struct usbdevclass_driver_s *driver, 201 FAR struct usbdev_s *dev); 202static int usbclass_unbind(FAR struct usbdevclass_driver_s *driver, 203 FAR struct usbdev_s *dev); 204static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver, 205 FAR struct usbdev_s *dev); 206static int usbclass_setconfig(FAR struct rndis_dev_s *priv, uint8_t config); 207static void usbclass_resetconfig(FAR struct rndis_dev_s *priv); 208static FAR struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep, 209 uint16_t len); 210static 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 219const 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 229struct 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 337struct 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 349struct 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 360static 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 392static 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 420static 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 440static 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 452static 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 466static 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 472static 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 516static 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 550static 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 570static 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 590static 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 613static 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 643static 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 663static 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 689static 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 727static 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 756static 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 783static 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 808static 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 835static 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 869static 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 908static 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 937static 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 955static 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 979static 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 1005static 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 1141static 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 1179static 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 1208static 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 1459static 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 1518static 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 1575static 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 1599static 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 1616static 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 1638static 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 1667static 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 1805errout: 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 1818static 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 1922static 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 2067static 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 2109static 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 2202static 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 2292errout: 2293 usbclass_resetconfig(priv); 2294 return ret; 2295} 2296 2297void 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 2347int 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 2389void 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 2411void 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 2435int 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