Explorar el Código

[Components][USB][Class and
Core]修复了协议栈在ep0请求大于端点描述最大包时无法正确读取的bug
增加了rndis class LWIP on USB

uestczyh222 hace 7 años
padre
commit
f4fb716167

+ 8 - 0
components/drivers/KConfig

@@ -132,6 +132,10 @@ menu "Using USB"
                     config _RT_USB_DEVICE_HID
                         bool "Enable to use device as HID device"
                         select RT_USB_DEVICE_HID
+                    config _RT_USB_DEVICE_RNDIS
+                        bool "Enable to use device as rndis device"
+                        select RT_USB_DEVICE_RNDIS
+                        depends on RT_USING_LWIP
                     config _RT_USB_DEVICE_ECM
                         bool "Enable to use device as ecm device"
                         select RT_USB_DEVICE_ECM
@@ -150,6 +154,10 @@ menu "Using USB"
                     config RT_USB_DEVICE_HID
                         bool "Enable to use device as HID device"
                         default n
+                    config RT_USB_DEVICE_RNDIS
+                        bool "Enable to use device as rndis device"
+                        default n
+                        depends on RT_USING_LWIP
                     config RT_USB_DEVICE_ECM
                         bool "Enable to use device as ecm device"
                         default n

+ 3 - 0
components/drivers/usb/usbdevice/SConscript

@@ -19,6 +19,9 @@ if GetDepend('RT_USB_DEVICE_MSTORAGE'):
 if GetDepend('RT_USB_DEVICE_ECM'):
 	src += Glob('class/ecm.c')
 
+if GetDepend('RT_USB_DEVICE_RNDIS'):
+	src += Glob('class/rndis.c')
+
 if GetDepend('RT_USB_DEVICE_WINUSB'):
 	src += Glob('class/winusb.c')
 

+ 229 - 0
components/drivers/usb/usbdevice/class/ndis.h

@@ -0,0 +1,229 @@
+/*
+ * ndis.h 
+ * 
+ * Modified by Colin O'Flynn <coflynn@newae.com>
+ * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
+ * 
+ * Thanks to the cygwin development team, 
+ * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
+ * 
+ * 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__ */

+ 1325 - 0
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;
+}

+ 222 - 0
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

+ 14 - 2
components/drivers/usb/usbdevice/core/core.c

@@ -871,6 +871,10 @@ static rt_err_t _ep0_out_notify(udevice_t device, struct ep_msg* ep_msg)
             ep0->rx_indicate(device, size);
         }        
     }
+    else
+    {
+        rt_usbd_ep0_read(device, ep0->request.buffer, ep0->request.remain_size,ep0->rx_indicate);
+    }
 
     return RT_EOK;
 }
@@ -2054,18 +2058,26 @@ rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size,
     rt_err_t (*rx_ind)(udevice_t device, rt_size_t size))
 {
     uep_t ep0;
+    rt_size_t read_size = 0;
 
     RT_ASSERT(device != RT_NULL);
     RT_ASSERT(device->dcd != RT_NULL);
     RT_ASSERT(buffer != RT_NULL);
 
     ep0 = &device->dcd->ep0;
-    ep0->request.size = size;
     ep0->request.buffer = buffer;    
     ep0->request.remain_size = size;
     ep0->rx_indicate = rx_ind;
+    if(size >= ep0->id->maxpacket)
+    {
+        read_size = ep0->id->maxpacket;
+    }
+    else
+    {
+        read_size = size;
+    }
     device->dcd->stage = STAGE_DOUT;
-    dcd_ep_read_prepare(device->dcd, EP0_OUT_ADDR, buffer, size);
+    dcd_ep_read_prepare(device->dcd, EP0_OUT_ADDR, buffer, read_size);
 
     return size;
 }