summaryrefslogtreecommitdiff
path: root/components/drivers/usb/usbdevice/class
diff options
context:
space:
mode:
authoruestczyh222 <[email protected]>2017-11-24 22:57:22 +0800
committeruestczyh222 <[email protected]>2017-11-25 17:31:48 +0800
commitf4fb71616772aa8ee309d7421fbce7090e5514ce (patch)
tree3f7441881ab48e82e53987dfa2fd2190eba4ce5c /components/drivers/usb/usbdevice/class
parent345bea8b1d8c866d4de20d4d86ccf923324725f6 (diff)
[Components][USB][Class and
Core]修复了协议栈在ep0请求大于端点描述最大包时无法正确读取的bug 增加了rndis class LWIP on USB
Diffstat (limited to 'components/drivers/usb/usbdevice/class')
-rw-r--r--components/drivers/usb/usbdevice/class/ndis.h229
-rw-r--r--components/drivers/usb/usbdevice/class/rndis.c1325
-rw-r--r--components/drivers/usb/usbdevice/class/rndis.h222
3 files changed, 1776 insertions, 0 deletions
diff --git a/components/drivers/usb/usbdevice/class/ndis.h b/components/drivers/usb/usbdevice/class/ndis.h
new file mode 100644
index 0000000000..8ad16637c2
--- /dev/null
+++ b/components/drivers/usb/usbdevice/class/ndis.h
@@ -0,0 +1,229 @@
+/*
+ * ndis.h
+ *
+ * Modified by Colin O'Flynn <[email protected]>
+ * ntddndis.h modified by Benedikt Spranger <[email protected]>
+ *
+ * Thanks to the cygwin development team,
+ * espacially to Casper S. Hornstrup <[email protected]>
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef __NDIS_H__
+#define __NDIS_H__
+
+#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
+#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
+#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
+
+/* from drivers/net/sk98lin/h/skgepnmi.h */
+#define OID_PNP_CAPABILITIES 0xFD010100
+#define OID_PNP_SET_POWER 0xFD010101
+#define OID_PNP_QUERY_POWER 0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
+#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
+
+enum NDIS_DEVICE_POWER_STATE
+{
+ NdisDeviceStateUnspecified = 0,
+ NdisDeviceStateD0,
+ NdisDeviceStateD1,
+ NdisDeviceStateD2,
+ NdisDeviceStateD3,
+ NdisDeviceStateMaximum
+};
+
+struct NDIS_PM_WAKE_UP_CAPABILITIES
+{
+ enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
+ enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
+ enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp;
+};
+
+/* NDIS_PNP_CAPABILITIES.Flags constants */
+#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
+#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
+#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004
+
+/* Required Object IDs (OIDs) */
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_SUPPORTED_GUIDS 0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
+#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
+#define OID_GEN_MACHINE_NAME 0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
+#define OID_GEN_VLAN_ID 0x0001021C
+
+/* Optional OIDs */
+#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
+#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
+
+/* Required statistics OIDs */
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+
+/* Optional statistics OIDs */
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+#define OID_GEN_NETCARD_LOAD 0x00020211
+#define OID_GEN_DEVICE_PROFILE 0x00020212
+#define OID_GEN_INIT_TIME_MS 0x00020213
+#define OID_GEN_RESET_COUNTS 0x00020214
+#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215
+#define OID_GEN_FRIENDLY_NAME 0x00020216
+#define OID_GEN_MINIPORT_INFO 0x00020217
+#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218
+
+/* IEEE 802.3 (Ethernet) OIDs */
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+
+/* Wireless LAN OIDs */
+#define OID_802_11_BSSID 0x0D010101 /* Q S */
+#define OID_802_11_SSID 0x0D010102 /* Q S */
+#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */
+#define OID_802_11_RSSI 0x0D010206 /* Q I */
+#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */
+#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */
+#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */
+#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */
+#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */
+#define OID_802_11_ADD_WEP 0x0D010113 /* S */
+#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */
+#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */
+#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */
+#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */
+#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */
+
+/* OID_GEN_MINIPORT_INFO constants */
+#define NDIS_MINIPORT_BUS_MASTER 0x00000001
+#define NDIS_MINIPORT_WDM_DRIVER 0x00000002
+#define NDIS_MINIPORT_SG_LIST 0x00000004
+#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008
+#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010
+#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020
+#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040
+#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080
+#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100
+#define NDIS_MINIPORT_IS_NDIS_5 0x00000200
+#define NDIS_MINIPORT_IS_CO 0x00000400
+#define NDIS_MINIPORT_DESERIALIZE 0x00000800
+#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000
+#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000
+#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000
+#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000
+#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000
+#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000
+#define NDIS_MINIPORT_HIDDEN 0x00040000
+#define NDIS_MINIPORT_SWENUM 0x00080000
+#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000
+#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000
+#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000
+#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000
+#define NDIS_MINIPORT_64BITS_DMA 0x01000000
+
+#define NDIS_MEDIUM_802_3 0x00000000
+#define NDIS_MEDIUM_802_5 0x00000001
+#define NDIS_MEDIUM_FDDI 0x00000002
+#define NDIS_MEDIUM_WAN 0x00000003
+#define NDIS_MEDIUM_LOCAL_TALK 0x00000004
+#define NDIS_MEDIUM_DIX 0x00000005
+#define NDIS_MEDIUM_ARCENT_RAW 0x00000006
+#define NDIS_MEDIUM_ARCENT_878_2 0x00000007
+#define NDIS_MEDIUM_ATM 0x00000008
+#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009
+#define NDIS_MEDIUM_IRDA 0x0000000A
+#define NDIS_MEDIUM_BPC 0x0000000B
+#define NDIS_MEDIUM_CO_WAN 0x0000000C
+#define NDIS_MEDIUM_1394 0x0000000D
+
+#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
+#define NDIS_PACKET_TYPE_SMT 0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
+#define NDIS_PACKET_TYPE_GROUP 0x00000100
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
+
+#define NDIS_MEDIA_STATE_CONNECTED 0x00000000
+#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+
+#endif /* __NDIS_H__ */
diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c
new file mode 100644
index 0000000000..a7f36dccb6
--- /dev/null
+++ b/components/drivers/usb/usbdevice/class/rndis.c
@@ -0,0 +1,1325 @@
+/*
+ * File : rndis.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006-2013, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-12-24 heyuanjie87 first version
+ * 2013-04-13 aozima update ethernet driver.
+ * 2013-04-26 aozima align the desc to 4byte.
+ * 2013-05-08 aozima pad a dummy when send MAX_PKT_SIZE.
+ * 2013-05-09 aozima add delay linkup feature.
+ * 2013-07-09 aozima support respone chain list.
+ * 2013-07-18 aozima re-initial respone chain list when RNDIS restart.
+ * 2017-11-25 ZYH fix it and add OS descriptor
+ */
+
+#include <rtdevice.h>
+#include "cdc.h"
+#include "rndis.h"
+#include "ndis.h"
+
+//#define RNDIS_DEBUG
+//#define RNDIS_DELAY_LINK_UP
+
+#ifdef RNDIS_DEBUG
+#define RNDIS_PRINTF rt_kprintf("[RNDIS] "); rt_kprintf
+#else
+#define RNDIS_PRINTF(...)
+#endif /* RNDIS_DEBUG */
+
+/* RT-Thread LWIP ethernet interface */
+#include <netif/ethernetif.h>
+
+
+struct rt_rndis_response
+{
+ struct rt_list_node list;
+ const void * buffer;
+};
+
+#define MAX_ADDR_LEN 6
+struct rt_rndis_eth
+{
+ /* inherit from ethernet device */
+ struct eth_device parent;
+ struct ufunction *func;
+ /* interface address info */
+ rt_uint8_t host_addr[MAX_ADDR_LEN];
+ rt_uint8_t dev_addr[MAX_ADDR_LEN];
+
+#ifdef RNDIS_DELAY_LINK_UP
+ struct rt_timer timer;
+#endif /* RNDIS_DELAY_LINK_UP */
+
+ ALIGN(4)
+ rt_uint8_t rx_pool[64];
+ ALIGN(4)
+ rt_uint8_t tx_pool[64];
+
+ rt_uint32_t cmd_pool[2];
+ ALIGN(4)
+ char rx_buffer[sizeof(struct rndis_packet_msg) + USB_ETH_MTU + 14];
+ rt_size_t rx_offset;
+ rt_size_t rx_length;
+ rt_bool_t rx_flag;
+ rt_bool_t rx_frist;
+
+ ALIGN(4)
+ char tx_buffer[sizeof(struct rndis_packet_msg) + USB_ETH_MTU + 14];
+ struct rt_semaphore tx_buffer_free;
+
+ struct rt_list_node response_list;
+ rt_bool_t need_notify;
+ struct cdc_eps eps;
+};
+typedef struct rt_rndis_eth * rt_rndis_eth_t;
+static rt_uint32_t oid_packet_filter = 0x0000000;
+
+ALIGN(4)
+static struct udevice_descriptor _dev_desc =
+{
+ USB_DESC_LENGTH_DEVICE, /* bLength */
+ USB_DESC_TYPE_DEVICE, /* type */
+ USB_BCD_VERSION, /* bcdUSB */
+ 0xEF, /* bDeviceClass */
+ 0x04, /* bDeviceSubClass */
+ 0x01, /* bDeviceProtocol */
+ USB_CDC_BUFSIZE, /* bMaxPacketSize0 */
+ _VENDOR_ID, /* idVendor */
+ _PRODUCT_ID, /* idProduct */
+ USB_BCD_DEVICE, /* bcdDevice */
+ USB_STRING_MANU_INDEX, /* iManufacturer */
+ USB_STRING_PRODUCT_INDEX, /* iProduct */
+ USB_STRING_SERIAL_INDEX, /* iSerialNumber */
+ USB_DYNAMIC /* bNumConfigurations */
+};
+
+/* communcation interface descriptor */
+ALIGN(4)
+const static struct ucdc_comm_descriptor _comm_desc =
+{
+#ifdef RT_USB_DEVICE_COMPOSITE
+ /* Interface Association Descriptor */
+ USB_DESC_LENGTH_IAD,
+ USB_DESC_TYPE_IAD,
+ USB_DYNAMIC,
+ 0x02,
+ USB_CDC_CLASS_COMM,
+ USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTOCOL_VENDOR,
+ 0x00,
+#endif
+ /* Interface Descriptor */
+ USB_DESC_LENGTH_INTERFACE,
+ USB_DESC_TYPE_INTERFACE,
+ USB_DYNAMIC,
+ 0x00,
+ 0x01,
+ USB_CDC_CLASS_COMM,
+ USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTOCOL_VENDOR,
+ 0x00,
+ /* Header Functional Descriptor */
+ 0x05,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_HEADER,
+ 0x0110,
+ /* Call Management Functional Descriptor */
+ 0x05,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_CALL_MGMT,
+ 0x00,
+ USB_DYNAMIC,
+ /* Abstract Control Management Functional Descriptor */
+ 0x04,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_ACM,
+ 0x02,
+ /* Union Functional Descriptor */
+ 0x05,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_UNION,
+ USB_DYNAMIC,
+ USB_DYNAMIC,
+ /* Endpoint Descriptor */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DIR_IN | USB_DYNAMIC,
+ USB_EP_ATTR_INT,
+ 0x08,
+ 0x0A,
+};
+
+/* data interface descriptor */
+ALIGN(4)
+const static struct ucdc_data_descriptor _data_desc =
+{
+ /* interface descriptor */
+ USB_DESC_LENGTH_INTERFACE,
+ USB_DESC_TYPE_INTERFACE,
+ USB_DYNAMIC,
+ 0x00,
+ 0x02,
+ USB_CDC_CLASS_DATA,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* endpoint, bulk out */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DIR_OUT | USB_DYNAMIC,
+ USB_EP_ATTR_BULK,
+ USB_CDC_BUFSIZE,
+ 0x00,
+ /* endpoint, bulk in */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DYNAMIC | USB_DIR_IN,
+ USB_EP_ATTR_BULK,
+ USB_CDC_BUFSIZE,
+ 0x00,
+};
+
+ALIGN(4)
+const static char* _ustring[] =
+{
+ "Language", /* LANGID */
+ "RT-Thread Team.", /* MANU */
+ "RT-Thread RNDIS device", /* PRODUCT */
+ "1.1.0", /* SERIAL */
+ "Configuration", /* CONFIG */
+ "Interface", /* INTERFACE */
+ USB_STRING_OS
+};
+
+struct usb_os_function_comp_id_descriptor rndis_func_comp_id_desc =
+{
+ .bFirstInterfaceNumber = USB_DYNAMIC,
+ .reserved1 = 0x01,
+ .compatibleID = {'R', 'N', 'D', 'I', 'S', 0x00, 0x00, 0x00},
+ .subCompatibleID = {'5', '1', '6', '2', '0', '0', '1', 0x00},
+ .reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+ALIGN(4)
+static struct usb_qualifier_descriptor dev_qualifier =
+{
+ sizeof(dev_qualifier),
+ USB_DESC_TYPE_DEVICEQUALIFIER,
+ 0x0200,
+ USB_CLASS_CDC,
+ 0x00,
+ 64,
+ 0x01,
+ 0,
+};
+
+/* supported OIDs */
+ALIGN(4)
+const static rt_uint32_t oid_supported_list[] =
+{
+ /* General OIDs */
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_VENDOR_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MEDIA_CONNECT_STATUS,
+
+ OID_GEN_PHYSICAL_MEDIUM,
+
+ /* General Statistic OIDs */
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+
+ /* Please configure us */
+ OID_GEN_RNDIS_CONFIG_PARAMETER,
+
+ /* 802.3 OIDs */
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+
+ /* 802.3 Statistic OIDs */
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+
+ OID_802_3_MAC_OPTIONS,
+};
+
+static rt_uint8_t rndis_message_buffer[RNDIS_MESSAGE_BUFFER_SIZE];
+
+static void _rndis_response_available(ufunction_t func)
+{
+ rt_rndis_eth_t device = (rt_rndis_eth_t)func->user_data;
+ rt_uint32_t * data;
+ if(device->need_notify == RT_TRUE)
+ {
+ device->need_notify = RT_FALSE;
+ data = (rt_uint32_t *)device->eps.ep_cmd->buffer;
+ data[0] = RESPONSE_AVAILABLE;
+ data[1] = 0;
+ device->eps.ep_cmd->request.buffer = device->eps.ep_cmd->buffer;
+ device->eps.ep_cmd->request.size = 8;
+ device->eps.ep_cmd->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, device->eps.ep_cmd, &device->eps.ep_cmd->request);
+ }
+}
+
+static rt_err_t _rndis_init_response(ufunction_t func, rndis_init_msg_t msg)
+{
+ rndis_init_cmplt_t resp;
+ struct rt_rndis_response * response;
+
+ response = rt_malloc(sizeof(struct rt_rndis_response));
+ resp = rt_malloc(sizeof(struct rndis_init_cmplt));
+
+ if( (response == RT_NULL) || (resp == RT_NULL) )
+ {
+ RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
+
+ if(response != RT_NULL)
+ rt_free(response);
+
+ if(resp != RT_NULL)
+ rt_free(resp);
+
+ return -RT_ENOMEM;
+ }
+
+ resp->RequestId = msg->RequestId;
+ resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
+ resp->MessageLength = sizeof(struct rndis_init_cmplt);
+ resp->MajorVersion = RNDIS_MAJOR_VERSION;
+ resp->MinorVersion = RNDIS_MAJOR_VERSION;
+ resp->Status = RNDIS_STATUS_SUCCESS;
+ resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
+ resp->Medium = RNDIS_MEDIUM_802_3;
+ resp->MaxPacketsPerTransfer = 1;
+ resp->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header,
+ RNDIS messages */
+ resp->PacketAlignmentFactor = 3;
+ resp->AfListOffset = 0;
+ resp->AfListSize = 0;
+
+ response->buffer = resp;
+
+ {
+ rt_base_t level = rt_hw_interrupt_disable();
+ rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
+ rt_hw_interrupt_enable(level);
+ }
+
+
+ return RT_EOK;
+}
+
+static rndis_query_cmplt_t _create_resp(rt_size_t size)
+{
+ rndis_query_cmplt_t resp;
+
+ resp = rt_malloc(sizeof(struct rndis_query_cmplt) + size);
+
+ if(resp == RT_NULL)
+ {
+ RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
+ return RT_NULL;
+ }
+
+ resp->InformationBufferLength = size;
+
+ return resp;
+}
+
+static void _copy_resp(rndis_query_cmplt_t resp, const void * buffer)
+{
+ char * resp_buffer = (char *)resp + sizeof(struct rndis_query_cmplt);
+ memcpy(resp_buffer, buffer, resp->InformationBufferLength);
+}
+
+static void _set_resp(rndis_query_cmplt_t resp, rt_uint32_t value)
+{
+ rt_uint32_t * response = (rt_uint32_t *)((char *)resp + sizeof(struct rndis_query_cmplt));
+ *response = value;
+}
+
+static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg)
+{
+ rndis_query_cmplt_t resp = RT_NULL;
+ struct rt_rndis_response * response;
+ rt_err_t ret = RT_EOK;
+
+ switch (msg->Oid)
+ {
+ /*
+ * general OIDs
+ */
+ case OID_GEN_SUPPORTED_LIST:
+ resp = _create_resp(sizeof(oid_supported_list));
+ if(resp == RT_NULL) break;
+ _copy_resp(resp, oid_supported_list);
+ break;
+
+ case OID_GEN_PHYSICAL_MEDIUM:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, NDIS_MEDIUM_802_3);
+ break;
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, USB_ETH_MTU);
+ break;
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, USB_ETH_MTU + RNDIS_MESSAGE_BUFFER_SIZE);
+ break;
+
+ case OID_GEN_LINK_SPEED:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, (10UL * 1000 * 1000) / 100);
+ break;
+
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ /* link_status */
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+
+#ifdef RNDIS_DELAY_LINK_UP
+ if(((rt_rndis_eth_t)func->user_data)->parent.link_status)
+ {
+ _set_resp(resp, NDIS_MEDIA_STATE_CONNECTED);
+ }
+ else
+ {
+ _set_resp(resp, NDIS_MEDIA_STATE_DISCONNECTED);
+ }
+#else
+ _set_resp(resp, NDIS_MEDIA_STATE_CONNECTED);
+#endif /* RNDIS_DELAY_LINK_UP */
+ break;
+
+ case OID_GEN_VENDOR_ID:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 0x12345678); /* only for test */
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+ {
+ const char vendor_desc[] = "RT-Thread RNDIS";
+
+ resp = _create_resp(sizeof(vendor_desc));
+ if(resp == RT_NULL) break;
+ _copy_resp(resp, vendor_desc);
+ }
+ break;
+
+ case OID_GEN_VENDOR_DRIVER_VERSION:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 0x0000200);
+ break;
+
+ /* statistics OIDs */
+ case OID_GEN_XMIT_OK:
+ case OID_GEN_RCV_OK:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 1);
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+ case OID_GEN_RCV_ERROR:
+ case OID_GEN_RCV_NO_BUFFER:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 0);
+ break;
+
+ /*
+ * ieee802.3 OIDs
+ */
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 1);
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ resp = _create_resp(sizeof(((rt_rndis_eth_t)func->user_data)->host_addr));
+ if(resp == RT_NULL) break;
+ _copy_resp(resp, ((rt_rndis_eth_t)func->user_data)->host_addr);
+ break;
+
+ case OID_802_3_MULTICAST_LIST:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 0xE000000);
+ break;
+
+ case OID_802_3_MAC_OPTIONS:
+ resp = _create_resp(4);
+ if(resp == RT_NULL) break;
+ _set_resp(resp, 0);
+ break;
+
+ default:
+ RNDIS_PRINTF("OID %X\n", msg->Oid);
+ ret = -RT_ERROR;
+ break;
+ }
+
+ response = rt_malloc(sizeof(struct rt_rndis_response));
+ if( (response == RT_NULL) || (resp == RT_NULL) )
+ {
+ RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
+
+ if(response != RT_NULL)
+ rt_free(response);
+
+ if(resp != RT_NULL)
+ rt_free(resp);
+
+ return -RT_ENOMEM;
+ }
+
+ resp->RequestId = msg->RequestId;
+ resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
+ resp->InformationBufferOffset = 16;
+
+ resp->Status = RNDIS_STATUS_SUCCESS;
+ resp->MessageLength = sizeof(struct rndis_query_cmplt) + resp->InformationBufferLength;
+
+ response->buffer = resp;
+
+ {
+ rt_base_t level = rt_hw_interrupt_disable();
+ rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
+ rt_hw_interrupt_enable(level);
+ }
+
+ return ret;
+}
+
+static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg)
+{
+ rndis_set_cmplt_t resp;
+ struct rt_rndis_response * response;
+
+ response = rt_malloc(sizeof(struct rt_rndis_response));
+ resp = rt_malloc(sizeof(struct rndis_set_cmplt));
+
+ if( (response == RT_NULL) || (resp == RT_NULL) )
+ {
+ RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
+
+ if(response != RT_NULL)
+ rt_free(response);
+
+ if(resp != RT_NULL)
+ rt_free(resp);
+
+ return -RT_ENOMEM;
+ }
+
+ resp->RequestId = msg->RequestId;
+ resp->MessageType = REMOTE_NDIS_SET_CMPLT;
+ resp->MessageLength = sizeof(struct rndis_set_cmplt);
+
+ switch (msg->Oid)
+ {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ oid_packet_filter = *((rt_uint32_t *)((rt_uint8_t *)&(msg->RequestId) + \
+ msg->InformationBufferOffset));
+ oid_packet_filter = oid_packet_filter;
+ RNDIS_PRINTF("OID_GEN_CURRENT_PACKET_FILTER\r\n");
+
+#ifdef RNDIS_DELAY_LINK_UP
+ /* link up. */
+ rt_timer_start(&((rt_rndis_eth_t)func->user_data)->timer);
+#else
+ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_TRUE);
+#endif /* RNDIS_DELAY_LINK_UP */
+ break;
+
+ case OID_802_3_MULTICAST_LIST:
+ break;
+
+ default:
+ resp->Status = RNDIS_STATUS_FAILURE;
+ return RT_EOK;
+ }
+
+ resp->Status = RNDIS_STATUS_SUCCESS;
+
+ response->buffer = resp;
+
+ {
+ rt_base_t level = rt_hw_interrupt_disable();
+ rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
+ rt_hw_interrupt_enable(level);
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg)
+{
+ rndis_keepalive_cmplt_t resp;
+ struct rt_rndis_response * response;
+
+ response = rt_malloc(sizeof(struct rt_rndis_response));
+ resp = rt_malloc(sizeof(struct rndis_keepalive_cmplt));
+
+ if( (response == RT_NULL) || (resp == RT_NULL) )
+ {
+ RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
+
+ if(response != RT_NULL)
+ rt_free(response);
+
+ if(resp != RT_NULL)
+ rt_free(resp);
+
+ return -RT_ENOMEM;
+ }
+
+ resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
+ resp->MessageLength = sizeof(struct rndis_keepalive_cmplt);
+ resp->Status = RNDIS_STATUS_SUCCESS;
+
+ response->buffer = resp;
+
+ {
+ rt_base_t level = rt_hw_interrupt_disable();
+ rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
+ rt_hw_interrupt_enable(level);
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t _rndis_msg_parser(ufunction_t func, rt_uint8_t *msg)
+{
+ rt_err_t ret = -RT_ERROR;
+
+ switch (((rndis_gen_msg_t) msg)->MessageType)
+ {
+ case REMOTE_NDIS_INITIALIZE_MSG:
+ ret = _rndis_init_response(func, (rndis_init_msg_t) msg);
+ break;
+
+ case REMOTE_NDIS_HALT_MSG:
+ RNDIS_PRINTF("halt\n");
+ /* link down. */
+ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE);
+ break;
+
+ case REMOTE_NDIS_QUERY_MSG:
+ ret = _rndis_query_response(func,(rndis_query_msg_t) msg);
+ break;
+
+ case REMOTE_NDIS_SET_MSG:
+ ret = _rndis_set_response(func,(rndis_set_msg_t) msg);
+ RNDIS_PRINTF("set\n");
+ break;
+
+ case REMOTE_NDIS_RESET_MSG:
+ RNDIS_PRINTF("reset\n");
+ break;
+
+ case REMOTE_NDIS_KEEPALIVE_MSG:
+ ret = _rndis_keepalive_response(func,(rndis_keepalive_msg_t) msg);
+ break;
+
+ default:
+ RNDIS_PRINTF("msg %X\n", ((rndis_gen_msg_t) msg)->MessageType);
+ ret = -RT_ERROR;
+ break;
+ }
+
+ if (ret == RT_EOK)
+ _rndis_response_available(func);
+
+ return ret;
+}
+
+static ufunction_t function = RT_NULL;
+static rt_err_t send_encapsulated_command_done(udevice_t device, rt_size_t size)
+{
+ if(function != RT_NULL)
+ {
+ dcd_ep0_send_status(device->dcd);
+ _rndis_msg_parser(function, rndis_message_buffer);
+ function = RT_NULL;
+ }
+ return RT_EOK;
+}
+//#error here have bug ep 0x82 send failed
+static rt_err_t _rndis_send_encapsulated_command(ufunction_t func, ureq_t setup)
+{
+ RT_ASSERT(setup->wLength <= sizeof(rndis_message_buffer));
+ function = func;
+ rt_usbd_ep0_read(func->device,rndis_message_buffer,setup->wLength,send_encapsulated_command_done);
+
+ return RT_EOK;
+}
+
+static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup)
+{
+ rndis_gen_msg_t msg;
+ struct rt_rndis_response * response;
+
+ if(rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
+ {
+ RNDIS_PRINTF("response_list is empty!\r\n");
+ ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
+ return RT_EOK;
+ }
+
+ response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next;
+
+ msg = (rndis_gen_msg_t)response->buffer;
+ rt_usbd_ep0_write(func->device, (void*)msg, msg->MessageLength);
+
+ {
+ rt_base_t level = rt_hw_interrupt_disable();
+ rt_list_remove(&response->list);
+ rt_hw_interrupt_enable(level);
+ }
+
+ rt_free((void *)response->buffer);
+ rt_free(response);
+
+ if(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
+ {
+ rt_uint32_t * data;
+
+ RNDIS_PRINTF("auto append next response!\r\n");
+ data = (rt_uint32_t *)((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer;
+ data[0] = RESPONSE_AVAILABLE;
+ data[1] = 0;
+ ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request.buffer = ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer;
+ ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request.size = 8;
+ ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, ((rt_rndis_eth_t)func->user_data)->eps.ep_cmd, &((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->request);
+ }
+ else
+ {
+ ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
+ }
+
+ return RT_EOK;
+}
+
+#ifdef RNDIS_DELAY_LINK_UP
+/**
+ * This function will set rndis connect status.
+ *
+ * @param device the usb device object.
+ * @param status the connect status.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status)
+{
+ rndis_indicate_status_msg_t resp;
+ struct rt_rndis_response * response;
+
+ response = rt_malloc(sizeof(struct rt_rndis_response));
+ resp = rt_malloc(sizeof(struct rndis_indicate_status_msg));
+
+ if( (response == RT_NULL) || (resp == RT_NULL) )
+ {
+ RNDIS_PRINTF("%d: no memory!\r\n", __LINE__);
+
+ if(response != RT_NULL)
+ rt_free(response);
+
+ if(resp != RT_NULL)
+ rt_free(resp);
+
+ return -RT_ENOMEM;
+ }
+
+ resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
+ resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */
+ resp->Status = status;
+ resp->StatusBufferLength = 0;
+ resp->StatusBufferOffset = 0;
+
+ response->buffer = resp;
+ {
+ rt_base_t level = rt_hw_interrupt_disable();
+ rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list);
+ rt_hw_interrupt_enable(level);
+ }
+
+ _rndis_response_available(func);
+
+ return RT_EOK;
+}
+#endif /* RNDIS_DELAY_LINK_UP */
+
+/**
+ * This function will handle rndis interface request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
+{
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ switch(setup->bRequest)
+ {
+ case CDC_SEND_ENCAPSULATED_COMMAND:
+ _rndis_send_encapsulated_command(func, setup);
+ break;
+
+ case CDC_GET_ENCAPSULATED_RESPONSE:
+ _rndis_get_encapsulated_response(func, setup);
+ break;
+
+ default:
+ RNDIS_PRINTF("unkown setup->request!\r\n");
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle rndis bulk in endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+
+static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
+{
+ rt_sem_release(&((rt_rndis_eth_t)func->user_data)->tx_buffer_free);
+ return RT_EOK;
+}
+
+/**
+ * This function will handle RNDIS bulk out endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
+{
+ cdc_eps_t eps;
+ char* data = RT_NULL;
+
+ eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps;
+ data = (char*)eps->ep_out->buffer;
+
+ if(((rt_rndis_eth_t)func->user_data)->rx_frist == RT_TRUE)
+ {
+ rndis_packet_msg_t msg = (rndis_packet_msg_t)data;
+
+ ((rt_rndis_eth_t)func->user_data)->rx_length = msg->DataLength;
+ ((rt_rndis_eth_t)func->user_data)->rx_offset = 0;
+
+ if (size >= 44)
+ {
+ data += sizeof(struct rndis_packet_msg);
+ size -= sizeof(struct rndis_packet_msg);
+ ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_FALSE;
+ memcpy(&((rt_rndis_eth_t)func->user_data)->rx_buffer[((rt_rndis_eth_t)func->user_data)->rx_offset], data, size);
+ ((rt_rndis_eth_t)func->user_data)->rx_offset += size;
+ }
+ }
+ else
+ {
+ memcpy(&((rt_rndis_eth_t)func->user_data)->rx_buffer[((rt_rndis_eth_t)func->user_data)->rx_offset], data, size);
+ ((rt_rndis_eth_t)func->user_data)->rx_offset += size;
+ }
+
+ if(((rt_rndis_eth_t)func->user_data)->rx_offset >= ((rt_rndis_eth_t)func->user_data)->rx_length)
+ {
+ ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE;
+ ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_TRUE;
+ eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent));
+ }
+ else
+ {
+ eps->ep_out->request.buffer = eps->ep_out->buffer;
+ eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out);
+ eps->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, eps->ep_out, &eps->ep_out->request);
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle RNDIS interrupt in endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
+{
+// _rndis_response_available(func);
+ return RT_EOK;
+}
+
+/**
+ * This function will run cdc class, it will be called on handle set configuration request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _function_enable(ufunction_t func)
+{
+ cdc_eps_t eps;
+
+ eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps;
+ eps->ep_in->buffer = ((rt_rndis_eth_t)func->user_data)->tx_pool;
+ eps->ep_out->buffer = ((rt_rndis_eth_t)func->user_data)->rx_pool;
+ eps->ep_cmd->buffer = (rt_uint8_t*)((rt_rndis_eth_t)func->user_data)->cmd_pool;
+
+ eps->ep_out->request.buffer = eps->ep_out->buffer;
+ eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out);
+ eps->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, eps->ep_out, &eps->ep_out->request);
+
+ ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE;
+ ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE;
+
+#ifdef RNDIS_DELAY_LINK_UP
+ /* stop link up timer. */
+ rt_timer_stop(&((rt_rndis_eth_t)func->user_data)->timer);
+#endif /* RNDIS_DELAY_LINK_UP */
+
+ /* clean resp chain list. */
+ {
+ struct rt_rndis_response * response;
+ rt_base_t level = rt_hw_interrupt_disable();
+
+ while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
+ {
+ response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next;
+
+ rt_list_remove(&response->list);
+ rt_free((void *)response->buffer);
+ rt_free(response);
+ }
+
+ ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
+ rt_hw_interrupt_enable(level);
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will stop cdc class, it will be called on handle set configuration request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _function_disable(ufunction_t func)
+{
+ RNDIS_PRINTF("plugged out\n");
+
+#ifdef RNDIS_DELAY_LINK_UP
+ /* stop link up timer. */
+ rt_timer_stop(&((rt_rndis_eth_t)func->user_data)->timer);
+#endif /* RNDIS_DELAY_LINK_UP */
+
+ /* clean resp chain list. */
+ {
+ struct rt_rndis_response * response;
+ rt_base_t level = rt_hw_interrupt_disable();
+
+ while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list))
+ {
+ response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next;
+ RNDIS_PRINTF("remove resp chain list!\r\n");
+
+ rt_list_remove(&response->list);
+ rt_free((void *)response->buffer);
+ rt_free(response);
+ }
+
+ ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE;
+ rt_hw_interrupt_enable(level);
+ }
+
+ /* link down. */
+ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE);
+ return RT_EOK;
+}
+
+
+static struct ufunction_ops ops =
+{
+ _function_enable,
+ _function_disable,
+ RT_NULL,
+};
+
+/**
+ * This function will configure cdc descriptor.
+ *
+ * @param comm the communication interface number.
+ * @param data the data interface number.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
+{
+ comm->call_mgmt_desc.data_interface = dintf_nr;
+ comm->union_desc.master_interface = cintf_nr;
+ comm->union_desc.slave_interface0 = dintf_nr;
+#ifdef RT_USB_DEVICE_COMPOSITE
+ comm->iad_desc.bFirstInterface = cintf_nr;
+#endif
+
+ return RT_EOK;
+}
+
+#ifdef RT_USING_LWIP
+/* initialize the interface */
+static rt_err_t rt_rndis_eth_init(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_err_t rt_rndis_eth_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ return RT_EOK;
+}
+
+static rt_err_t rt_rndis_eth_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_size_t rt_rndis_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_size_t rt_rndis_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+static rt_err_t rt_rndis_eth_control(rt_device_t dev, int cmd, void *args)
+{
+ rt_rndis_eth_t rndis_eth_dev = (rt_rndis_eth_t)dev;
+ switch(cmd)
+ {
+ case NIOCTL_GADDR:
+ /* get mac address */
+ if(args) rt_memcpy(args, rndis_eth_dev->dev_addr, MAX_ADDR_LEN);
+ else return -RT_ERROR;
+ break;
+
+ default :
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/* ethernet device interface */
+
+
+/* reception packet. */
+struct pbuf *rt_rndis_eth_rx(rt_device_t dev)
+{
+ struct pbuf* p = RT_NULL;
+ rt_uint32_t offset = 0;
+ rt_rndis_eth_t device = (rt_rndis_eth_t)dev;
+ if(device->rx_flag == RT_FALSE)
+ {
+ return p;
+ }
+
+ if(device->rx_length != 0)
+ {
+ /* allocate buffer */
+ p = pbuf_alloc(PBUF_LINK, device->rx_length, PBUF_RAM);
+ if (p != RT_NULL)
+ {
+ struct pbuf* q;
+
+ for (q = p; q != RT_NULL; q= q->next)
+ {
+ /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */
+ memcpy(q->payload,
+ (rt_uint8_t *)((device->rx_buffer) + offset),
+ q->len);
+ offset += q->len;
+ }
+ }
+ }
+
+ {
+ device->rx_flag = RT_FALSE;
+ device->eps.ep_out->request.buffer = device->eps.ep_out->buffer;
+ device->eps.ep_out->request.size = EP_MAXPACKET(device->eps.ep_out);
+ device->eps.ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(device->func->device, device->eps.ep_out, &device->eps.ep_out->request);
+ }
+
+ return p;
+}
+
+/* transmit packet. */
+rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p)
+{
+ struct pbuf* q;
+ char * buffer;
+ rt_err_t result = RT_EOK;
+ rt_rndis_eth_t device = (rt_rndis_eth_t)dev;
+
+ if(!device->parent.link_status)
+ {
+ RNDIS_PRINTF("linkdown, drop pkg\r\n");
+ return RT_EOK;
+ }
+
+ RT_ASSERT(p->tot_len < sizeof(device->tx_buffer));
+ if(p->tot_len > sizeof(device->tx_buffer))
+ {
+ RNDIS_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n",
+ sizeof(device->tx_buffer), p->tot_len);
+ p->tot_len = sizeof(device->tx_buffer);
+ }
+
+ /* wait for buffer free. */
+ result = rt_sem_take(&device->tx_buffer_free, RT_WAITING_FOREVER);
+ if(result != RT_EOK)
+ {
+ return result;
+ }
+
+ buffer = (char *)&device->tx_buffer + sizeof(struct rndis_packet_msg);
+ for (q = p; q != NULL; q = q->next)
+ {
+ memcpy(buffer, q->payload, q->len);
+ buffer += q->len;
+ }
+
+ /* send */
+ {
+ rndis_packet_msg_t msg;
+
+ msg = (rndis_packet_msg_t)&device->tx_buffer;
+
+ msg->MessageType = REMOTE_NDIS_PACKET_MSG;
+ msg->DataOffset = sizeof(struct rndis_packet_msg) - 8;
+ msg->DataLength = p->tot_len;
+ msg->OOBDataLength = 0;
+ msg->OOBDataOffset = 0;
+ msg->NumOOBDataElements = 0;
+ msg->PerPacketInfoOffset = 0;
+ msg->PerPacketInfoLength = 0;
+ msg->VcHandle = 0;
+ msg->Reserved = 0;
+ msg->MessageLength = sizeof(struct rndis_packet_msg) + p->tot_len;
+
+ if((msg->MessageLength & 0x3F) == 0)
+ {
+ /* pad a dummy. */
+ msg->MessageLength += 1;
+ }
+
+ device->eps.ep_in->request.buffer = (void *)&device->tx_buffer;
+ device->eps.ep_in->request.size = msg->MessageLength;
+ device->eps.ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(device->func->device, device->eps.ep_in, &device->eps.ep_in->request);
+ }
+
+ return result;
+}
+#endif /* RT_USING_LWIP */
+
+#ifdef RNDIS_DELAY_LINK_UP
+/* the delay linkup timer handler. */
+static void timer_timeout(void* parameter)
+{
+ RNDIS_PRINTF("delay link up!\r\n");
+ _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->parent.parent.user_data,
+ RNDIS_STATUS_MEDIA_CONNECT);
+ eth_device_linkchange(&((rt_rndis_eth_t)parameter)->parent, RT_TRUE);
+}
+#endif /* RNDIS_DELAY_LINK_UP */
+
+/**
+ * This function will create a cdc rndis class instance.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+ufunction_t rt_usbd_function_rndis_create(udevice_t device)
+{
+ ufunction_t cdc;
+ rt_rndis_eth_t _rndis;
+ cdc_eps_t eps;
+ uintf_t intf_comm, intf_data;
+ ualtsetting_t comm_setting, data_setting;
+ ucdc_data_desc_t data_desc;
+ ucdc_comm_desc_t comm_desc;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+
+ /* set usb device string description */
+ rt_usbd_device_set_string(device, _ustring);
+
+ /* create a cdc class */
+ cdc = rt_usbd_function_new(device, &_dev_desc, &ops);
+ rt_usbd_device_set_qualifier(device, &dev_qualifier);
+ _rndis= rt_malloc(sizeof(struct rt_rndis_eth));
+ rt_memset(_rndis, 0, sizeof(struct rt_rndis_eth));
+ cdc->user_data = _rndis;
+
+ _rndis->func = cdc;
+ /* create a cdc class endpoints collection */
+ eps = &_rndis->eps;
+ /* create a cdc communication interface and a cdc data interface */
+ intf_comm = rt_usbd_interface_new(device, _interface_handler);
+ intf_data = rt_usbd_interface_new(device, _interface_handler);
+
+ /* create a communication alternate setting and a data alternate setting */
+ comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_comm_descriptor));
+ data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
+
+ /* config desc in alternate setting */
+ rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
+ (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
+ rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
+ /* configure the cdc interface descriptor */
+ _cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num);
+
+ /* create a command endpoint */
+ comm_desc = (ucdc_comm_desc_t)comm_setting->desc;
+ eps->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
+ /* add the command endpoint to the cdc communication interface */
+ rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd);
+
+ /* add the communication alternate setting to the communication interface,
+ then set default setting of the interface */
+ rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
+ rt_usbd_set_altsetting(intf_comm, 0);
+ /* add the communication interface to the cdc class */
+ rt_usbd_function_add_interface(cdc, intf_comm);
+
+ /* create a bulk in and a bulk out endpoint */
+ data_desc = (ucdc_data_desc_t)data_setting->desc;
+ eps->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
+ eps->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
+
+ /* add the bulk out and bulk in endpoints to the data alternate setting */
+ rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in);
+ rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out);
+
+ /* add the data alternate setting to the data interface
+ then set default setting of the interface */
+ rt_usbd_interface_add_altsetting(intf_data, data_setting);
+ rt_usbd_set_altsetting(intf_data, 0);
+
+ /* add the cdc data interface to cdc class */
+ rt_usbd_function_add_interface(cdc, intf_data);
+
+ rt_usbd_os_comp_id_desc_add_os_func_comp_id_desc(device->os_comp_id_desc, &rndis_func_comp_id_desc);
+
+
+#ifdef RT_USING_LWIP
+
+ rt_list_init(&_rndis->response_list);
+ _rndis->need_notify = RT_TRUE;
+
+ rt_sem_init(&_rndis->tx_buffer_free, "ue_tx", 1, RT_IPC_FLAG_FIFO);
+
+#ifdef RNDIS_DELAY_LINK_UP
+ rt_timer_init(&_rndis->timer,
+ "RNDIS",
+ timer_timeout,
+ _rndis,
+ RT_TICK_PER_SECOND * 2,
+ RT_TIMER_FLAG_ONE_SHOT);
+#endif /* RNDIS_DELAY_LINK_UP */
+
+ /* OUI 00-00-00, only for test. */
+ _rndis->dev_addr[0] = 0x34;
+ _rndis->dev_addr[1] = 0x97;
+ _rndis->dev_addr[2] = 0xF6;
+ /* generate random MAC. */
+ _rndis->dev_addr[3] = 0x94;//*(const rt_uint8_t *)(0x1fff7a10);
+ _rndis->dev_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x1fff7a14);
+ _rndis->dev_addr[5] = 0x12;//(const rt_uint8_t *)(0x1fff7a18);
+ /* OUI 00-00-00, only for test. */
+ _rndis->host_addr[0] = 0x34;
+ _rndis->host_addr[1] = 0x97;
+ _rndis->host_addr[2] = 0xF6;
+ /* generate random MAC. */
+ _rndis->host_addr[3] = 0x94;//*(const rt_uint8_t *)(0x0FE081F0);
+ _rndis->host_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x0FE081F1);
+ _rndis->host_addr[5] = 0x13;//*(const rt_uint8_t *)(0x0FE081F2);
+
+ _rndis->parent.parent.init = rt_rndis_eth_init;
+ _rndis->parent.parent.open = rt_rndis_eth_open;
+ _rndis->parent.parent.close = rt_rndis_eth_close;
+ _rndis->parent.parent.read = rt_rndis_eth_read;
+ _rndis->parent.parent.write = rt_rndis_eth_write;
+ _rndis->parent.parent.control = rt_rndis_eth_control;
+ _rndis->parent.parent.user_data = device;
+
+ _rndis->parent.eth_rx = rt_rndis_eth_rx;
+ _rndis->parent.eth_tx = rt_rndis_eth_tx;
+
+ /* register eth device */
+ eth_device_init(&((rt_rndis_eth_t)cdc->user_data)->parent, "u0");
+
+#endif /* RT_USING_LWIP */
+
+ return cdc;
+}
diff --git a/components/drivers/usb/usbdevice/class/rndis.h b/components/drivers/usb/usbdevice/class/rndis.h
new file mode 100644
index 0000000000..1374338c14
--- /dev/null
+++ b/components/drivers/usb/usbdevice/class/rndis.h
@@ -0,0 +1,222 @@
+/*
+ * File : rndis.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-12-24 heyuanjie87 first version
+ */
+
+#ifndef __RNDIS_H__
+#define __RNDIS_H__
+
+#include <rtthread.h>
+
+#define USB_ETH_MTU 1500+14
+#define RNDIS_MESSAGE_BUFFER_SIZE 128
+
+#define RESPONSE_AVAILABLE 0x00000001
+
+/* Remote NDIS version numbers */
+#define RNDIS_MAJOR_VERSION 1
+#define RNDIS_MINOR_VERSION 0
+
+/* common status values */
+#define RNDIS_STATUS_SUCCESS 0X00000000
+#define RNDIS_STATUS_FAILURE 0XC0000001
+#define RNDIS_STATUS_INVALID_DATA 0XC0010015
+#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB
+#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B
+#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C
+
+/* Remote NDIS message types */
+#define REMOTE_NDIS_PACKET_MSG 0x00000001
+#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002
+#define REMOTE_NDIS_HALT_MSG 0X00000003
+#define REMOTE_NDIS_QUERY_MSG 0X00000004
+#define REMOTE_NDIS_SET_MSG 0X00000005
+#define REMOTE_NDIS_RESET_MSG 0X00000006
+#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007
+#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008
+#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002
+#define REMOTE_NDIS_QUERY_CMPLT 0X80000004
+#define REMOTE_NDIS_SET_CMPLT 0X80000005
+#define REMOTE_NDIS_RESET_CMPLT 0X80000006
+#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008
+
+/* device flags */
+#define RNDIS_DF_CONNECTIONLESS 0x00000001
+#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
+/* mediums */
+#define RNDIS_MEDIUM_802_3 0x00000000
+
+struct ucls_rndis
+{
+ uep_t notify;
+ rt_uint32_t filter;
+ rt_bool_t header;
+ rt_uint8_t rndis_state;
+ rt_uint8_t media_state;
+ rt_uint8_t ethaddr[6];
+};
+
+/* Remote NDIS generic message type */
+struct rndis_gen_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+};
+typedef struct rndis_gen_msg* rndis_gen_msg_t;
+
+struct rndis_packet_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t DataOffset;
+ rt_uint32_t DataLength;
+ rt_uint32_t OOBDataOffset;
+ rt_uint32_t OOBDataLength;
+ rt_uint32_t NumOOBDataElements;
+ rt_uint32_t PerPacketInfoOffset;
+ rt_uint32_t PerPacketInfoLength;
+ rt_uint32_t VcHandle;
+ rt_uint32_t Reserved;
+};
+typedef struct rndis_packet_msg* rndis_packet_msg_t;
+
+/* Remote NDIS Initialize Message */
+struct rndis_init_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t MajorVersion;
+ rt_uint32_t MinorVersion;
+ rt_uint32_t MaxTransferSize;
+};
+typedef struct rndis_init_msg* rndis_init_msg_t;
+
+/* Response */
+struct rndis_init_cmplt
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t Status;
+ rt_uint32_t MajorVersion;
+ rt_uint32_t MinorVersion;
+ rt_uint32_t DeviceFlags;
+ rt_uint32_t Medium;
+ rt_uint32_t MaxPacketsPerTransfer;
+ rt_uint32_t MaxTransferSize;
+ rt_uint32_t PacketAlignmentFactor;
+ rt_uint32_t AfListOffset;
+ rt_uint32_t AfListSize;
+};
+typedef struct rndis_init_cmplt* rndis_init_cmplt_t;
+
+/* Remote NDIS Halt Message */
+struct rndis_halt_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+};
+
+/* Remote NDIS Query Message */
+struct rndis_query_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t Oid;
+ rt_uint32_t InformationBufferLength;
+ rt_uint32_t InformationBufferOffset;
+ rt_uint32_t DeviceVcHandle;
+};
+typedef struct rndis_query_msg* rndis_query_msg_t;
+
+/* Response */
+struct rndis_query_cmplt
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t Status;
+ rt_uint32_t InformationBufferLength;
+ rt_uint32_t InformationBufferOffset;
+};
+typedef struct rndis_query_cmplt* rndis_query_cmplt_t;
+
+/* Remote NDIS Set Message */
+struct rndis_set_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t Oid;
+ rt_uint32_t InformationBufferLength;
+ rt_uint32_t InformationBufferOffset;
+ rt_uint32_t DeviceVcHandle;
+};
+typedef struct rndis_set_msg* rndis_set_msg_t;
+
+/* Response */
+struct rndis_set_cmplt
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t Status;
+};
+typedef struct rndis_set_cmplt* rndis_set_cmplt_t;
+
+/* Remote NDIS Soft Reset Message */
+struct rndis_reset_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t Reserved;
+};
+
+/* Remote NDIS Indicate Status Message */
+struct rndis_indicate_status_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t Status;
+ rt_uint32_t StatusBufferLength;
+ rt_uint32_t StatusBufferOffset;
+};
+typedef struct rndis_indicate_status_msg* rndis_indicate_status_msg_t;
+
+struct rndis_keepalive_msg
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestID;
+};
+typedef struct rndis_keepalive_msg* rndis_keepalive_msg_t;
+
+/* Response: */
+struct rndis_keepalive_cmplt
+{
+ rt_uint32_t MessageType;
+ rt_uint32_t MessageLength;
+ rt_uint32_t RequestId;
+ rt_uint32_t Status;
+};
+typedef struct rndis_keepalive_cmplt* rndis_keepalive_cmplt_t;
+
+
+
+
+
+
+
+#endif