Эх сурвалжийг харах

update rndis device driver and template

sakumisu 3 жил өмнө
parent
commit
36de428845

+ 4 - 2
cherryusb_config_template.h

@@ -93,6 +93,8 @@
 #define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
 #endif
 
+#define CONFIG_USBDEV_RNDIS_USING_LWIP
+
 /* ================ USB HOST Stack Configuration ================== */
 
 #define CONFIG_USBHOST_MAX_RHPORTS          1
@@ -136,8 +138,8 @@
 
 /* ================ EHCI Configuration ================ */
 
-#define CONFIG_USB_EHCI_HCCR_BASE   (0x20072000)
-#define CONFIG_USB_EHCI_HCOR_BASE   (0x20072000 + 0x10)
+#define CONFIG_USB_EHCI_HCCR_BASE       (0x20072000)
+#define CONFIG_USB_EHCI_HCOR_BASE       (0x20072000 + 0x10)
 #define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
 // #define CONFIG_USB_EHCI_INFO_ENABLE
 // #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE

+ 138 - 2
class/cdc/usb_cdc.h

@@ -344,8 +344,8 @@ struct cdc_ecm_descriptor {
     USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
     int_ep,                                                /* bEndpointAddress */              \
     0x03,                                                  /* bmAttributes */                  \
-    0x40, 0x00,                                            /* wMaxPacketSize */                \
-    0x00,                                                  /* bInterval */                     \
+    0x08, 0x00,                                            /* wMaxPacketSize */                \
+    0x0a,                                                  /* bInterval */                     \
     0x09,                                                  /* bLength */                       \
     USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
     (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
@@ -409,8 +409,144 @@ struct cdc_ecm_descriptor {
     USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
     int_ep,                                                /* bEndpointAddress */              \
     0x03,                                                  /* bmAttributes */                  \
+    0x08, 0x00,                                            /* wMaxPacketSize */                \
+    0x10,                                                  /* bInterval */                     \
+    0x09,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
+    (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
+    0x00,                                                  /* bAlternateSetting */             \
+    0x02,                                                  /* bNumEndpoints */                 \
+    CDC_DATA_INTERFACE_CLASS,                              /* bInterfaceClass */               \
+    0x00,                                                  /* bInterfaceSubClass */            \
+    0x00,                                                  /* bInterfaceProtocol */            \
+    0x00,                                                  /* iInterface */                    \
+    0x07,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
+    out_ep,                                                /* bEndpointAddress */              \
+    0x02,                                                  /* bmAttributes */                  \
     0x00, 0x02,                                            /* wMaxPacketSize */                \
     0x00,                                                  /* bInterval */                     \
+    0x07,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
+    in_ep,                                                 /* bEndpointAddress */              \
+    0x02,                                                  /* bmAttributes */                  \
+    0x00, 0x02,                                            /* wMaxPacketSize */                \
+    0x00                                                   /* bInterval */
+#endif
+// clang-format on
+
+/*Length of template descriptor: 66 bytes*/
+#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
+// clang-format off
+#ifndef CONFIG_USB_HS
+#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx)             \
+    /* Interface Associate */                                                                  \
+    0x08,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION,             /* bDescriptorType */               \
+    bFirstInterface,                                       /* bFirstInterface */               \
+    0x02,                                                  /* bInterfaceCount */               \
+    USB_DEVICE_CLASS_WIRELESS,                             /* bFunctionClass */                \
+    CDC_DIRECT_LINE_CONTROL_MODEL,                         /* bFunctionSubClass */             \
+    CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO,   /* bFunctionProtocol */             \
+    0x00,                                                  /* iFunction */                     \
+    0x09,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
+    bFirstInterface,                                       /* bInterfaceNumber */              \
+    0x00,                                                  /* bAlternateSetting */             \
+    0x01,                                                  /* bNumEndpoints */                 \
+    USB_DEVICE_CLASS_WIRELESS,                             /* bInterfaceClass */               \
+    CDC_DIRECT_LINE_CONTROL_MODEL,                         /* bInterfaceSubClass */            \
+    CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO,   /* bInterfaceProtocol */            \
+    str_idx,                                               /* iInterface */                    \
+    0x05,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_HEADER,                                  /* bDescriptorSubtype */            \
+    WBVAL(CDC_V1_10),                                      /* bcdCDC */                        \
+    0x05,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_CALL_MANAGEMENT,                         /* bDescriptorSubtype */            \
+    0x00,                                                  /* bmCapabilities */                \
+    (uint8_t)(bFirstInterface + 1),                        /* bDataInterface */                \
+    0x04,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT,             /* bDescriptorSubtype */            \
+    0x00,                                                  /* bmCapabilities */                \
+    0x05,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_UNION,                                   /* bDescriptorSubtype */            \
+    bFirstInterface,                                       /* bMasterInterface */              \
+    (uint8_t)(bFirstInterface + 1),                        /* bSlaveInterface0 */              \
+    0x07,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
+    int_ep,                                                /* bEndpointAddress */              \
+    0x03,                                                  /* bmAttributes */                  \
+    0x08, 0x00,                                            /* wMaxPacketSize */                \
+    0x10,                                                  /* bInterval */                     \
+    0x09,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
+    (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \
+    0x00,                                                  /* bAlternateSetting */             \
+    0x02,                                                  /* bNumEndpoints */                 \
+    CDC_DATA_INTERFACE_CLASS,                              /* bInterfaceClass */               \
+    0x00,                                                  /* bInterfaceSubClass */            \
+    0x00,                                                  /* bInterfaceProtocol */            \
+    0x00,                                                  /* iInterface */                    \
+    0x07,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
+    out_ep,                                                /* bEndpointAddress */              \
+    0x02,                                                  /* bmAttributes */                  \
+    0x40, 0x00,                                            /* wMaxPacketSize */                \
+    0x00,                                                  /* bInterval */                     \
+    0x07,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
+    in_ep,                                                 /* bEndpointAddress */              \
+    0x02,                                                  /* bmAttributes */                  \
+    0x40, 0x00,                                            /* wMaxPacketSize */                \
+    0x00                                                   /* bInterval */
+#else
+#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx)             \
+    /* Interface Associate */                                                                  \
+    0x08,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION,             /* bDescriptorType */               \
+    bFirstInterface,                                       /* bFirstInterface */               \
+    0x02,                                                  /* bInterfaceCount */               \
+    USB_DEVICE_CLASS_WIRELESS,                             /* bFunctionClass */                \
+    CDC_DIRECT_LINE_CONTROL_MODEL,                         /* bFunctionSubClass */             \
+    CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO,   /* bFunctionProtocol */             \
+    0x00,                                                  /* iFunction */                     \
+    0x09,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
+    bFirstInterface,                                       /* bInterfaceNumber */              \
+    0x00,                                                  /* bAlternateSetting */             \
+    0x01,                                                  /* bNumEndpoints */                 \
+    USB_DEVICE_CLASS_WIRELESS,                             /* bInterfaceClass */               \
+    CDC_DIRECT_LINE_CONTROL_MODEL,                         /* bInterfaceSubClass */            \
+    CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO,   /* bInterfaceProtocol */            \
+    str_idx,                                               /* iInterface */                    \
+    0x05,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_HEADER,                                  /* bDescriptorSubtype */            \
+    WBVAL(CDC_V1_10),                                      /* bcdCDC */                        \
+    0x05,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_CALL_MANAGEMENT,                         /* bDescriptorSubtype */            \
+    0x00,                                                  /* bmCapabilities */                \
+    (uint8_t)(bFirstInterface + 1),                        /* bDataInterface */                \
+    0x04,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT,             /* bDescriptorSubtype */            \
+    0x00,                                                  /* bmCapabilities */                \
+    0x05,                                                  /* bLength */                       \
+    CDC_CS_INTERFACE,                                      /* bDescriptorType */               \
+    CDC_FUNC_DESC_UNION,                                   /* bDescriptorSubtype */            \
+    bFirstInterface,                                       /* bMasterInterface */              \
+    (uint8_t)(bFirstInterface + 1),                        /* bSlaveInterface0 */              \
+    0x07,                                                  /* bLength */                       \
+    USB_DESCRIPTOR_TYPE_ENDPOINT,                          /* bDescriptorType */               \
+    int_ep,                                                /* bEndpointAddress */              \
+    0x03,                                                  /* bmAttributes */                  \
+    0x08, 0x00,                                            /* wMaxPacketSize */                \
+    0x10,                                                  /* bInterval */                     \
     0x09,                                                  /* bLength */                       \
     USB_DESCRIPTOR_TYPE_INTERFACE,                         /* bDescriptorType */               \
     (uint8_t)(bFirstInterface + 1),                        /* bInterfaceNumber */              \

+ 7 - 0
class/wireless/ndis.h

@@ -258,6 +258,13 @@ struct NDIS_PM_PACKET_PATTERN {
 #define NDIS_MAC_OPTION_8021P_PRIORITY      0x00000040
 #define NDIS_MAC_OPTION_RESERVED            0x80000000
 
+/** Hardware status of the underlying NIC */
+#define NDIS_HW_STS_READY        0x00000000UL
+#define NDIS_HW_STS_INITIALIZING 0x00000001UL
+#define NDIS_HW_STS_RESET        0x00000002UL
+#define NDIS_HW_STS_CLOSING      0x00000003UL
+#define NDIS_HW_STS_NOT_READY    0x00000004UL
+
 #endif /* _LINUX_NDIS_H */
 
 /** @} */

+ 192 - 64
class/wireless/usbd_rndis.c

@@ -7,33 +7,56 @@
 #include "usbd_rndis.h"
 #include "rndis_protocol.h"
 
+#define RNDIS_OUT_EP_IDX 0
+#define RNDIS_IN_EP_IDX  1
+#define RNDIS_INT_EP_IDX 2
+
+/* Describe EndPoints configuration */
+static struct usbd_endpoint rndis_ep_data[3];
+
 #define RNDIS_INQUIRY_PUT(src, len)   (memcpy(infomation_buffer, src, len))
 #define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
 
+#ifdef CONFIG_USB_HS
+#define RNDIS_MAX_PACKET_SIZE 512
+#else
+#define RNDIS_MAX_PACKET_SIZE 512
+#endif
+
+#ifndef CONFIG_USB_HS
+#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */
+#else
+#define RNDIS_LINK_SPEED 480000000 /* Link baudrate (480Mbit/s for USB-HS) */
+#endif
+
 /* Device data structure */
 struct usbd_rndis_cfg_priv {
     uint32_t drv_version;
-    uint32_t media_status;
+    uint32_t link_status;
     uint32_t speed;
-    uint32_t mtu;
     uint32_t net_filter;
     usb_eth_stat_t eth_state;
     rndis_state_t init_state;
-    uint8_t int_ep;
     uint8_t mac[6];
-    uint32_t vendor_id;
-    uint8_t *vendor_desc;
 } usbd_rndis_cfg = { .drv_version = 0x0001,
-                     .media_status = NDIS_MEDIA_STATE_DISCONNECTED,
-                     .mtu = CONFIG_USBDEV_RNDIS_MTU,
+                     .link_status = NDIS_MEDIA_STATE_DISCONNECTED,
                      .speed = RNDIS_LINK_SPEED,
                      .init_state = rndis_uninitialized,
-                     .mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 },
-                     .vendor_id = 0xffffffff,
-                     .vendor_desc = "CherryUSB" };
+                     .mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 } };
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+volatile uint8_t *g_rndis_rx_data_buffer;
+volatile uint32_t g_rndis_rx_data_length;
+volatile uint32_t g_rndis_tx_data_length;
 
 /* RNDIS options list */
 const uint32_t oid_supported_list[] = {
+    /* General OIDs */
     OID_GEN_SUPPORTED_LIST,
     OID_GEN_HARDWARE_STATUS,
     OID_GEN_MEDIA_SUPPORTED,
@@ -47,32 +70,46 @@ const uint32_t oid_supported_list[] = {
     OID_GEN_VENDOR_DRIVER_VERSION,
     OID_GEN_CURRENT_PACKET_FILTER,
     OID_GEN_MAXIMUM_TOTAL_SIZE,
-    OID_GEN_PROTOCOL_OPTIONS,
-    OID_GEN_MAC_OPTIONS,
     OID_GEN_MEDIA_CONNECT_STATUS,
-    OID_GEN_MAXIMUM_SEND_PACKETS,
+
+    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,
-    OID_802_3_MAC_OPTIONS
-};
 
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
-USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    /* 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 int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
 
 static void rndis_notify_rsp(void)
 {
-    usbd_ep_start_write(usbd_rndis_cfg.int_ep, NOTIFY_RESPONSE_AVAILABLE, 8);
+    usbd_ep_start_write(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
 }
 
 static int rndis_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
 {
     switch (setup->bRequest) {
         case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
-            rndis_encapsulated_cmd_handler(data, len);
+            rndis_encapsulated_cmd_handler(*data, setup->wLength);
             break;
         case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
             *data = rndis_encapsulated_resp_buffer;
@@ -82,6 +119,8 @@ static int rndis_class_interface_request_handler(struct usb_setup_packet *setup,
         default:
             return -1;
     }
+
+    return 0;
 }
 
 static int rndis_init_cmd_handler(uint8_t *data, uint32_t len);
@@ -96,22 +135,16 @@ static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len)
     switch (((rndis_generic_msg_t *)data)->MessageType) {
         case REMOTE_NDIS_INITIALIZE_MSG:
             return rndis_init_cmd_handler(data, len);
-            break;
         case REMOTE_NDIS_HALT_MSG:
             return rndis_halt_cmd_handler(data, len);
-            break;
         case REMOTE_NDIS_QUERY_MSG:
             return rndis_query_cmd_handler(data, len);
-            break;
         case REMOTE_NDIS_SET_MSG:
             return rndis_set_cmd_handler(data, len);
-            break;
         case REMOTE_NDIS_RESET_MSG:
             return rndis_reset_cmd_handler(data, len);
-            break;
         case REMOTE_NDIS_KEEPALIVE_MSG:
             return rndis_keepalive_cmd_handler(data, len);
-            break;
 
         default:
             break;
@@ -134,7 +167,7 @@ static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
     resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
     resp->Medium = RNDIS_MEDIUM_802_3;
     resp->MaxPacketsPerTransfer = 1;
-    resp->MaxTransferSize = usbd_rndis_cfg.mtu + ETH_HEADER_SIZE + sizeof(rndis_data_packet_t);
+    resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + sizeof(rndis_data_packet_t);
     resp->PacketAlignmentFactor = 0;
     resp->AfListOffset = 0;
     resp->AfListSize = 0;
@@ -177,63 +210,56 @@ static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
             RNDIS_INQUIRY_PUT(oid_supported_list, sizeof(oid_supported_list));
             infomation_len = sizeof(oid_supported_list);
             break;
-        case OID_GEN_VENDOR_DRIVER_VERSION:
-            RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.drv_version);
+        case OID_GEN_HARDWARE_STATUS:
+            RNDIS_INQUIRY_PUT_LE32(NDIS_HW_STS_READY);
             infomation_len = 4;
             break;
-        case OID_802_3_CURRENT_ADDRESS:
-            RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
-            infomation_len = 6;
-            break;
-        case OID_802_3_PERMANENT_ADDRESS:
-            RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
-            infomation_len = 6;
-            break;
         case OID_GEN_MEDIA_SUPPORTED:
-            RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
-            infomation_len = 4;
-            break;
         case OID_GEN_MEDIA_IN_USE:
             RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
             infomation_len = 4;
             break;
-        case OID_GEN_PHYSICAL_MEDIUM:
-            RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
+        case OID_GEN_MAXIMUM_FRAME_SIZE:
+        case OID_GEN_TRANSMIT_BLOCK_SIZE:
+        case OID_GEN_RECEIVE_BLOCK_SIZE:
+            RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE);
             infomation_len = 4;
             break;
-        case OID_GEN_HARDWARE_STATUS:
-            RNDIS_INQUIRY_PUT_LE32(0);
+        case OID_GEN_VENDOR_ID:
+            RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_VENDOR_ID);
             infomation_len = 4;
             break;
-        case OID_GEN_LINK_SPEED:
-            RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
+        case OID_GEN_VENDOR_DRIVER_VERSION:
+            RNDIS_INQUIRY_PUT_LE32(0x0001);
             infomation_len = 4;
             break;
-        case OID_GEN_VENDOR_ID:
-            RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.vendor_id);
+        case OID_GEN_VENDOR_DESCRIPTION:
+            RNDIS_INQUIRY_PUT(CONFIG_USBDEV_RNDIS_VENDOR_DESC, strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC));
+            infomation_len = (strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC) + 1);
+            break;
+        case OID_802_3_CURRENT_ADDRESS:
+        case OID_802_3_PERMANENT_ADDRESS:
+            RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
+            infomation_len = 6;
+            break;
+        case OID_GEN_PHYSICAL_MEDIUM:
+            RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
             infomation_len = 4;
             break;
-        case OID_GEN_VENDOR_DESCRIPTION:
-            RNDIS_INQUIRY_PUT(usbd_rndis_cfg.vendor_desc, strlen(usbd_rndis_cfg.vendor_desc) + 1);
-            infomation_len = (strlen(usbd_rndis_cfg.vendor_desc) + 1);
+        case OID_GEN_LINK_SPEED:
+            RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
+            infomation_len = 4;
             break;
         case OID_GEN_CURRENT_PACKET_FILTER:
             RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.net_filter);
             infomation_len = 4;
             break;
-        case OID_GEN_MAXIMUM_FRAME_SIZE:
-            RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu);
-            infomation_len = 4;
-            break;
         case OID_GEN_MAXIMUM_TOTAL_SIZE:
-        case OID_GEN_TRANSMIT_BLOCK_SIZE:
-        case OID_GEN_RECEIVE_BLOCK_SIZE:
-            //RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu + ETH_HEADER_SIZE + sizeof(rndis_data_packet_t));
-            RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu + ETH_HEADER_SIZE);
+            RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE);
             infomation_len = 4;
             break;
         case OID_GEN_MEDIA_CONNECT_STATUS:
-            RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.media_status);
+            RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.link_status);
             infomation_len = 4;
             break;
         case OID_GEN_RNDIS_CONFIG_PARAMETER:
@@ -401,7 +427,13 @@ static void rndis_notify_handler(uint8_t event, void *arg)
 {
     switch (event) {
         case USBD_EVENT_RESET:
-
+            usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
+            break;
+        case USBD_EVENT_CONFIGURED:
+            g_rndis_rx_data_length = 0;
+            g_rndis_tx_data_length = 0;
+            usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_CONNECTED;
+            usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
             break;
 
         default:
@@ -409,7 +441,95 @@ static void rndis_notify_handler(uint8_t event, void *arg)
     }
 }
 
-struct usbd_interface *usbd_rndis_alloc_intf(uint8_t int_ep, uint8_t mac[6], uint32_t vendor_id, uint8_t *vendor_desc)
+void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
+{
+    rndis_data_packet_t *hdr;
+
+    hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
+    g_rndis_rx_data_buffer = g_rndis_rx_buffer;
+    if ((hdr->MessageType != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
+        usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+        return;
+    }
+
+    /* Point to the payload and update the message length */
+    g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
+    g_rndis_rx_data_length = hdr->DataLength;
+
+    usbd_rndis_data_recv((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
+}
+
+void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
+{
+    if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
+        /* send zlp */
+        usbd_ep_start_write(ep, NULL, 0);
+    } else {
+        g_rndis_tx_data_length = 0;
+    }
+}
+
+#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
+#include <lwip/pbuf.h>
+
+struct pbuf *usbd_rndis_eth_rx(void)
+{
+    struct pbuf *p;
+
+    if (g_rndis_rx_data_length == 0) {
+        return NULL;
+    }
+    p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
+    if (p == NULL) {
+        return NULL;
+    }
+    memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
+    p->len = g_rndis_rx_data_length;
+
+    g_rndis_rx_data_length = 0;
+    usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+
+    return p;
+}
+
+int usbd_rndis_eth_tx(struct pbuf *p)
+{
+    struct pbuf *q;
+    uint8_t *buffer;
+    rndis_data_packet_t *hdr;
+
+    if (usbd_rndis_cfg.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
+        return 0;
+    }
+
+    if (g_rndis_tx_data_length > 0) {
+        return -EBUSY;
+    }
+
+    if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
+        p->tot_len = sizeof(g_rndis_tx_buffer);
+    }
+
+    buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
+    for (q = p; q != NULL; q = q->next) {
+        memcpy(buffer, q->payload, q->len);
+        buffer += q->len;
+    }
+
+    hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
+
+    memset(hdr, 0, sizeof(rndis_data_packet_t));
+    hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
+    hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
+    hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
+    hdr->DataLength = p->tot_len;
+
+    g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
+
+    return usbd_ep_start_write(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
+}
+#endif
+struct usbd_interface *usbd_rndis_alloc_intf(uint8_t out_ep, uint8_t in_ep, uint8_t int_ep, uint8_t mac[6])
 {
     struct usbd_interface *intf = (struct usbd_interface *)usb_malloc(sizeof(struct usbd_interface));
     if (intf == NULL) {
@@ -417,10 +537,18 @@ struct usbd_interface *usbd_rndis_alloc_intf(uint8_t int_ep, uint8_t mac[6], uin
         return NULL;
     }
 
-    usbd_rndis_cfg.int_ep = int_ep;
     memcpy(usbd_rndis_cfg.mac, mac, 6);
-    usbd_rndis_cfg.vendor_id = vendor_id;
-    usbd_rndis_cfg.vendor_desc = vendor_desc;
+
+    rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
+    rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
+    rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr = in_ep;
+    rndis_ep_data[RNDIS_IN_EP_IDX].ep_cb = rndis_bulk_in;
+    rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
+    rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = NULL;
+
+    usbd_add_endpoint(&rndis_ep_data[RNDIS_OUT_EP_IDX]);
+    usbd_add_endpoint(&rndis_ep_data[RNDIS_IN_EP_IDX]);
+    usbd_add_endpoint(&rndis_ep_data[RNDIS_INT_EP_IDX]);
 
     intf->class_interface_handler = rndis_class_interface_request_handler;
     intf->class_endpoint_handler = NULL;

+ 6 - 12
class/wireless/usbd_rndis.h

@@ -8,22 +8,16 @@
 
 #include "usb_cdc.h"
 
-#define ETH_HEADER_SIZE         14
-#define CONFIG_USBDEV_RNDIS_MTU 1500 /* MTU value */
-
-#ifndef CONFIG_USB_HS
-#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */
-#else
-#define RNDIS_LINK_SPEED 480000000 /* Link baudrate (480Mbit/s for USB-HS) */
-#endif
-
-#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-struct usbd_interface *usbd_rndis_alloc_intf(uint8_t int_ep, uint8_t mac[6], uint32_t vendor_id, uint8_t *vendor_desc);
+struct usbd_interface *usbd_rndis_alloc_intf(uint8_t out_ep, uint8_t in_ep, uint8_t int_ep, uint8_t mac[6]);
+
+#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
+struct pbuf *usbd_rndis_eth_rx(void);
+int usbd_rndis_eth_tx(struct pbuf *p);
+#endif
 
 #ifdef __cplusplus
 }

+ 174 - 0
demo/cdc_rndis_template.c

@@ -0,0 +1,174 @@
+#include "usbd_core.h"
+#include "usbd_rndis.h"
+
+/*!< endpoint address */
+#define CDC_IN_EP  0x81
+#define CDC_OUT_EP 0x02
+#define CDC_INT_EP 0x83
+
+#define USBD_VID           0xEFFF
+#define USBD_PID           0xEFFF
+#define USBD_MAX_POWER     100
+#define USBD_LANGID_STRING 1033
+
+/*!< config descriptor size */
+#define USB_CONFIG_SIZE (9 + CDC_RNDIS_DESCRIPTOR_LEN)
+
+/*!< global descriptor */
+static const uint8_t cdc_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    CDC_RNDIS_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
+    ///////////////////////////////////////
+    /// string0 descriptor
+    ///////////////////////////////////////
+    USB_LANGID_INIT(USBD_LANGID_STRING),
+    ///////////////////////////////////////
+    /// string1 descriptor
+    ///////////////////////////////////////
+    0x14,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    'C', 0x00,                  /* wcChar0 */
+    'h', 0x00,                  /* wcChar1 */
+    'e', 0x00,                  /* wcChar2 */
+    'r', 0x00,                  /* wcChar3 */
+    'r', 0x00,                  /* wcChar4 */
+    'y', 0x00,                  /* wcChar5 */
+    'U', 0x00,                  /* wcChar6 */
+    'S', 0x00,                  /* wcChar7 */
+    'B', 0x00,                  /* wcChar8 */
+    ///////////////////////////////////////
+    /// string2 descriptor
+    ///////////////////////////////////////
+    0x2A,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    'C', 0x00,                  /* wcChar0 */
+    'h', 0x00,                  /* wcChar1 */
+    'e', 0x00,                  /* wcChar2 */
+    'r', 0x00,                  /* wcChar3 */
+    'r', 0x00,                  /* wcChar4 */
+    'y', 0x00,                  /* wcChar5 */
+    'U', 0x00,                  /* wcChar6 */
+    'S', 0x00,                  /* wcChar7 */
+    'B', 0x00,                  /* wcChar8 */
+    ' ', 0x00,                  /* wcChar9 */
+    'R', 0x00,                  /* wcChar10 */
+    'N', 0x00,                  /* wcChar11 */
+    'D', 0x00,                  /* wcChar12 */
+    'I', 0x00,                  /* wcChar13 */
+    'S', 0x00,                  /* wcChar14 */
+    ' ', 0x00,                  /* wcChar15 */
+    'D', 0x00,                  /* wcChar16 */
+    'E', 0x00,                  /* wcChar17 */
+    'M', 0x00,                  /* wcChar18 */
+    'O', 0x00,                  /* wcChar19 */
+    ///////////////////////////////////////
+    /// string3 descriptor
+    ///////////////////////////////////////
+    0x16,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    '2', 0x00,                  /* wcChar0 */
+    '0', 0x00,                  /* wcChar1 */
+    '2', 0x00,                  /* wcChar2 */
+    '2', 0x00,                  /* wcChar3 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
+    '6', 0x00,                  /* wcChar9 */
+#ifdef CONFIG_USB_HS
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x02,
+    0x02,
+    0x01,
+    0x40,
+    0x01,
+    0x00,
+#endif
+    0x00
+};
+
+#ifdef RT_USING_LWIP
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <netif/ethernetif.h>
+
+struct eth_device rndis_dev;
+
+void usbd_configure_done_callback(void)
+{
+    eth_device_linkchange(&rndis_dev, RT_TRUE);
+}
+
+uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
+static rt_err_t rt_usbd_rndis_control(rt_device_t dev, int cmd, void *args)
+{
+    switch (cmd) {
+        case NIOCTL_GADDR:
+
+            /* get mac address */
+            if (args)
+                rt_memcpy(args, mac, 6);
+            else
+                return -RT_ERROR;
+
+            break;
+
+        default:
+            break;
+    }
+
+    return RT_EOK;
+}
+
+struct pbuf *rt_usbd_rndis_eth_rx(rt_device_t dev)
+{
+    return usbd_rndis_eth_rx();
+}
+
+rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    return usbd_rndis_eth_tx(p);
+}
+
+void usbd_rndis_data_recv(uint8_t *data, uint32_t len)
+{
+    eth_device_ready(&rndis_dev);
+}
+
+void rt_usbd_rndis_init(void)
+{
+    rndis_dev.parent.control = rt_usbd_rndis_control;
+    rndis_dev.eth_rx = rt_usbd_rndis_eth_rx;
+    rndis_dev.eth_tx = rt_usbd_rndis_eth_tx;
+
+    eth_device_init(&rndis_dev, "u0");
+
+    eth_device_linkchange(&rndis_dev, RT_FALSE);
+}
+#else
+void usbd_configure_done_callback(void)
+{
+}
+
+#endif /* RT_USING_LWIP */
+
+/* function ------------------------------------------------------------------*/
+void cdc_rndis_init(void)
+{
+#ifdef RT_USING_LWIP
+    rt_usbd_rndis_init();
+#endif
+    usbd_desc_register(cdc_descriptor);
+    usbd_add_interface(usbd_rndis_alloc_intf(CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
+    usbd_add_interface(usbd_rndis_alloc_intf(CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
+    usbd_initialize();
+}