Просмотр исходного кода

refactor(platform): update platform support

sakumisu 1 год назад
Родитель
Сommit
865d2f5d96

+ 30 - 30
Kconfig.cherryusb

@@ -197,19 +197,22 @@ if CHERRYUSB
             prompt "Enable usb msc driver"
             default n
 
-        config CHERRYUSB_HOST_CDC_RNDIS
+        config CHERRYUSB_HOST_CDC_ECM
             bool
-            prompt "Enable usb rndis driver"
+            prompt "Enable usb cdc ecm driver"
+            select USBHOST_PLATFORM_CDC_ECM
             default n
 
-        config CHERRYUSB_HOST_CDC_ECM
+        config CHERRYUSB_HOST_CDC_RNDIS
             bool
-            prompt "Enable usb cdc ecm driver"
+            prompt "Enable usb rndis driver"
+            select USBHOST_PLATFORM_CDC_RNDIS
             default n
 
         config CHERRYUSB_HOST_CDC_NCM
             bool
             prompt "Enable usb cdc ncm driver"
+            select USBHOST_PLATFORM_CDC_NCM
             default n
 
         config CHERRYUSB_HOST_VIDEO
@@ -230,11 +233,13 @@ if CHERRYUSB
         config CHERRYUSB_HOST_ASIX
             bool
             prompt "Enable usb asix driver"
+            select USBHOST_PLATFORM_ASIX
             default n
 
         config CHERRYUSB_HOST_RTL8152
             bool
             prompt "Enable usb rtl8152 driver"
+            select USBHOST_PLATFORM_RTL8152
             default n
 
         config CHERRYUSB_HOST_FTDI
@@ -252,6 +257,26 @@ if CHERRYUSB
             prompt "Enable usb cp210x driver"
             default n
 
+        config CHERRYUSB_HOST_PL2303
+            bool
+            prompt "Enable usb pl2303 driver"
+            default n
+
+        config USBHOST_PLATFORM_CDC_ECM
+            bool
+
+        config USBHOST_PLATFORM_CDC_RNDIS
+            bool
+
+        config USBHOST_PLATFORM_CDC_NCM
+            bool
+
+        config USBHOST_PLATFORM_ASIX
+            bool
+
+        config USBHOST_PLATFORM_RTL152
+            bool
+
         config CHERRYUSB_HOST_TEMPLATE
             bool
             prompt "Use usb host template"
@@ -270,34 +295,9 @@ if CHERRYUSB
                 depends on CHERRYUSB_HOST_HID
             config TEST_USBH_MSC
                 int
-                prompt "demo for test msc, do not enable because it has used dfs instead"
+                prompt "demo for test msc"
                 default 0
                 depends on CHERRYUSB_HOST_MSC
-            config TEST_USBH_CDC_ECM
-                int
-                prompt "demo for test cdc ecm"
-                default 0
-                depends on CHERRYUSB_HOST_CDC_ECM
-            config TEST_USBH_CDC_NCM
-                int
-                prompt "demo for test cdc ncm"
-                default 0
-                depends on CHERRYUSB_HOST_CDC_NCM
-            config TEST_USBH_RNDIS
-                int
-                prompt "demo for test cdc rndis"
-                default 0
-                depends on CHERRYUSB_HOST_CDC_RNDIS
-            config TEST_USBH_ASIX
-                int
-                prompt "demo for test asix"
-                default 0
-                depends on CHERRYUSB_HOST_ASIX
-            config TEST_USBH_RTL8152
-                int
-                prompt "demo for test rtl8152"
-                default 0
-                depends on CHERRYUSB_HOST_RTL8152
         endif
     endif
 

+ 2 - 15
README.md

@@ -36,27 +36,14 @@ Taking into account USB performance issues and trying to achieve the theoretical
 
 ## Directoy Structure
 
-```
-.
-├── class
-├── common
-├── core
-├── demo
-├── docs
-├── osal
-├── packet capture
-└── port
-└── tools
-
-```
-
 |   Directory       |  Description            |
 |:-------------:|:---------------------------:|
 |class          |  usb class driver           |
 |common         |  usb spec macros and utils  |
 |core           |  usb core implementation    |
-|demo           |  different chips demo       |
+|demo           |  usb device and host demo   |
 |osal           |  os wrapper                 |
+|platform       |  class support for other os |
 |docs           |  doc for guiding            |
 |port           |  usb dcd and hcd porting    |
 |tools          |  tool url                   |

+ 2 - 13
README_zh.md

@@ -36,26 +36,15 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带
 
 ## 目录结构
 
-```
-.
-├── class
-├── common
-├── core
-├── demo
-├── docs
-├── osal
-└── port
-└── tools
-```
-
 |   目录名       |  描述                          |
 |:-------------:|:-------------------------------:|
 |class          |  usb class 类主从驱动           |
 |common         |  usb spec 定义、常用宏、标准接口定义 |
 |core           |  usb 主从协议栈核心实现          |
-|demo           |  示例                            |
+|demo           |  主从 class demo                 |
 |docs           |  文档                            |
 |osal           |  os 封装层                       |
+|platform       |  其他 os 全家桶适配              |
 |port           |  usb 主从需要实现的 porting 接口 |
 |tools          |  工具链接                        |
 

+ 12 - 5
SConscript

@@ -191,11 +191,18 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
     if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
         src += Glob('demo/usb_host.c')
 
-    if GetDepend('RT_USING_DFS'):
-       src += Glob('third_party/rt-thread-5.0/dfs_usbh_msc.c')
-
-src += Glob('third_party/rt-thread-5.0/usb_msh.c')
-src += Glob('third_party/rt-thread-5.0/usb_check.c')
+    if GetDepend('RT_USING_DFS') and GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
+       src += Glob('platform/rtthread/usbh_dfs.c')
+
+    if GetDepend('PKG_CHERRYUSB_HOST_CDC_ECM') \
+        or GetDepend('PKG_CHERRYUSB_HOST_CDC_RNDIS') \
+        or GetDepend('PKG_CHERRYUSB_HOST_CDC_NCM') \
+        or GetDepend('PKG_CHERRYUSB_HOST_CDC_ASIX') \
+        or GetDepend('PKG_CHERRYUSB_HOST_CDC_RTL8152'):
+       src += Glob('platform/rtthread/usbh_lwip.c')
+
+src += Glob('platform/rtthread/usb_msh.c')
+src += Glob('platform/rtthread/usb_check.c')
 
 group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
 

+ 8 - 40
class/cdc/usbh_cdc_ecm.c

@@ -230,14 +230,6 @@ void usbh_cdc_ecm_rx_thread(void *argument)
 {
     uint32_t g_cdc_ecm_rx_length;
     int ret;
-    err_t err;
-    struct pbuf *p;
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-    pbuf_type type = PBUF_ROM;
-#else
-    pbuf_type type = PBUF_POOL;
-#endif
-    struct netif *netif = (struct netif *)argument;
 
     USB_LOG_INFO("Create cdc ecm rx thread\r\n");
     // clang-format off
@@ -269,23 +261,9 @@ find_class:
         if (g_cdc_ecm_rx_length % USB_GET_MAXPACKETSIZE(g_cdc_ecm_class.bulkin->wMaxPacketSize)) {
             USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_length);
 
-            p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_length, type);
-            if (p != NULL) {
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-                p->payload = g_cdc_ecm_rx_buffer;
-#else
-                memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
-#endif
-                g_cdc_ecm_rx_length = 0;
+            usbh_cdc_ecm_eth_input(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_length);
 
-                err = netif->input(p, netif);
-                if (err != ERR_OK) {
-                    pbuf_free(p);
-                }
-            } else {
-                g_cdc_ecm_rx_length = 0;
-                USB_LOG_ERR("No memory to alloc pbuf for cdc ecm rx\r\n");
-            }
+            g_cdc_ecm_rx_length = 0;
         } else {
             /* read continue util read short packet */
             if (g_cdc_ecm_rx_length > CONFIG_USBHOST_CDC_ECM_ETH_MAX_SIZE) {
@@ -301,30 +279,20 @@ delete:
     // clang-format on
 }
 
-err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
+int usbh_cdc_ecm_eth_output(uint8_t *buf, uint32_t buflen)
 {
-    int ret;
-    struct pbuf *q;
     uint8_t *buffer = g_cdc_ecm_tx_buffer;
 
     if (g_cdc_ecm_class.connect_status == false) {
-        return ERR_BUF;
-    }
-
-    for (q = p; q != NULL; q = q->next) {
-        memcpy(buffer, q->payload, q->len);
-        buffer += q->len;
+        return -USB_ERR_NOTCONN;
     }
 
-    USB_LOG_DBG("txlen:%d\r\n", p->tot_len);
+    memcpy(buffer, buf, buflen);
 
-    usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, p->tot_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
-    ret = usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
-    if (ret < 0) {
-        return ERR_BUF;
-    }
+    USB_LOG_DBG("txlen:%d\r\n", buflen);
 
-    return ERR_OK;
+    usbh_bulk_urb_fill(&g_cdc_ecm_class.bulkout_urb, g_cdc_ecm_class.hport, g_cdc_ecm_class.bulkout, g_cdc_ecm_tx_buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
+    return usbh_submit_urb(&g_cdc_ecm_class.bulkout_urb);
 }
 
 __WEAK void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)

+ 2 - 8
class/cdc/usbh_cdc_ecm.h

@@ -8,9 +8,6 @@
 
 #include "usb_cdc.h"
 
-#include "lwip/netif.h"
-#include "lwip/pbuf.h"
-
 struct usbh_cdc_ecm {
     struct usbh_hubport *hport;
     struct usb_endpoint_descriptor *bulkin;  /* Bulk IN endpoint */
@@ -29,10 +26,6 @@ struct usbh_cdc_ecm {
     uint16_t max_segment_size;
     uint32_t speed[2];
 
-    ip_addr_t ipaddr;
-    ip_addr_t netmask;
-    ip_addr_t gateway;
-
     void *user_data;
 };
 
@@ -45,7 +38,8 @@ int usbh_cdc_ecm_get_connect_status(struct usbh_cdc_ecm *cdc_ecm_class);
 void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class);
 void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class);
 
-err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p);
+int usbh_cdc_ecm_eth_output(uint8_t *buf, uint32_t buflen);
+void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen);
 void usbh_cdc_ecm_rx_thread(void *argument);
 
 #ifdef __cplusplus

+ 9 - 40
class/cdc/usbh_cdc_ncm.c

@@ -248,14 +248,6 @@ void usbh_cdc_ncm_rx_thread(void *argument)
 {
     uint32_t g_cdc_ncm_rx_length;
     int ret;
-    err_t err;
-    struct pbuf *p;
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-    pbuf_type type = PBUF_ROM;
-#else
-    pbuf_type type = PBUF_POOL;
-#endif
-    struct netif *netif = (struct netif *)argument;
 
     USB_LOG_INFO("Create cdc ncm rx thread\r\n");
     // clang-format off
@@ -311,20 +303,8 @@ find_class:
                 if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
                     USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
 
-                    p = pbuf_alloc(PBUF_RAW, ndp16_datagram->wDatagramLength, type);
-                    if (p != NULL) {
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-                        p->payload = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
-#else
-                        memcpy(p->payload, (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex], ndp16_datagram->wDatagramLength);
-#endif
-                        err = netif->input(p, netif);
-                        if (err != ERR_OK) {
-                            pbuf_free(p);
-                        }
-                    } else {
-                        USB_LOG_ERR("No memory to alloc pbuf for cdc ncm rx\r\n");
-                    }
+                    uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
+                    usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength);
                 }
             }
 
@@ -344,15 +324,13 @@ delete:
     // clang-format on
 }
 
-err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
+int usbh_cdc_ncm_eth_output(uint8_t *buf, uint32_t buflen)
 {
-    int ret;
-    struct pbuf *q;
     uint8_t *buffer;
     struct cdc_ncm_ndp16_datagram *ndp16_datagram;
 
     if (g_cdc_ncm_class.connect_status == false) {
-        return ERR_BUF;
+        return -USB_ERR_NOTCONN;
     }
 
     struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_tx_buffer[0];
@@ -360,8 +338,8 @@ err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
     nth16->dwSignature = CDC_NCM_NTH16_SIGNATURE;
     nth16->wHeaderLength = 12;
     nth16->wSequence = g_cdc_ncm_class.bulkout_sequence++;
-    nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(p->tot_len, 4);
-    nth16->wNdpIndex = 16 + USB_ALIGN_UP(p->tot_len, 4);
+    nth16->wBlockLength = 16 + 16 + USB_ALIGN_UP(buflen, 4);
+    nth16->wNdpIndex = 16 + USB_ALIGN_UP(buflen, 4);
 
     struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex];
 
@@ -371,28 +349,19 @@ err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
 
     ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 0];
     ndp16_datagram->wDatagramIndex = 16;
-    ndp16_datagram->wDatagramLength = p->tot_len;
+    ndp16_datagram->wDatagramLength = buflen;
 
     ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_tx_buffer[nth16->wNdpIndex + 8 + 4 * 1];
     ndp16_datagram->wDatagramIndex = 0;
     ndp16_datagram->wDatagramLength = 0;
 
     buffer = &g_cdc_ncm_tx_buffer[16];
-
-    for (q = p; q != NULL; q = q->next) {
-        memcpy(buffer, q->payload, q->len);
-        buffer += q->len;
-    }
+    memcpy(buffer, buf, buflen);
 
     USB_LOG_DBG("txlen:%d\r\n", nth16->wBlockLength);
 
     usbh_bulk_urb_fill(&g_cdc_ncm_class.bulkout_urb, g_cdc_ncm_class.hport, g_cdc_ncm_class.bulkout, g_cdc_ncm_tx_buffer, nth16->wBlockLength, USB_OSAL_WAITING_FOREVER, NULL, NULL);
-    ret = usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
-    if (ret < 0) {
-        return ERR_BUF;
-    }
-
-    return ERR_OK;
+    return usbh_submit_urb(&g_cdc_ncm_class.bulkout_urb);
 }
 
 __WEAK void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)

+ 2 - 8
class/cdc/usbh_cdc_ncm.h

@@ -8,9 +8,6 @@
 
 #include "usb_cdc.h"
 
-#include "lwip/netif.h"
-#include "lwip/pbuf.h"
-
 struct usbh_cdc_ncm {
     struct usbh_hubport *hport;
     struct usb_endpoint_descriptor *bulkin;  /* Bulk IN endpoint */
@@ -33,10 +30,6 @@ struct usbh_cdc_ncm {
     uint16_t max_segment_size;
     uint32_t speed[2];
 
-    ip_addr_t ipaddr;
-    ip_addr_t netmask;
-    ip_addr_t gateway;
-
     void *user_data;
 };
 
@@ -49,7 +42,8 @@ int usbh_cdc_ncm_get_connect_status(struct usbh_cdc_ncm *cdc_ncm_class);
 void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class);
 void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class);
 
-err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p);
+int usbh_cdc_ncm_eth_output(uint8_t *buf, uint32_t buflen);
+void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen);
 void usbh_cdc_ncm_rx_thread(void *argument);
 
 #ifdef __cplusplus

+ 20 - 51
class/vendor/net/usbh_asix.c

@@ -653,16 +653,8 @@ void usbh_asix_rx_thread(void *argument)
 {
     uint32_t g_asix_rx_length;
     int ret;
-    err_t err;
     uint16_t len;
     uint16_t len_crc;
-    struct pbuf *p;
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-    pbuf_type type = PBUF_ROM;
-#else
-    pbuf_type type = PBUF_POOL;
-#endif
-    struct netif *netif = (struct netif *)argument;
 
     USB_LOG_INFO("Create asix rx thread\r\n");
     // clang-format off
@@ -702,23 +694,9 @@ find_class:
 
             USB_LOG_DBG("rxlen:%d\r\n", g_asix_rx_length);
 
-            p = pbuf_alloc(PBUF_RAW, len, type);
-            if (p != NULL) {
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-                p->payload = (uint8_t *)&g_asix_rx_buffer[4];
-#else
-                memcpy(p->payload, (uint8_t *)&g_asix_rx_buffer[4], len);
-#endif
-                g_asix_rx_length = 0;
-
-                err = netif->input(p, netif);
-                if (err != ERR_OK) {
-                    pbuf_free(p);
-                }
-            } else {
-                g_asix_rx_length = 0;
-                USB_LOG_ERR("No memory to alloc pbuf for asix rx\r\n");
-            }
+            uint8_t *buf = (uint8_t *)&g_asix_rx_buffer[4];
+            usbh_asix_eth_input(buf, len);
+            g_asix_rx_length = 0;
         } else {
             if (g_asix_rx_length > CONFIG_USBHOST_ASIX_ETH_MAX_SIZE) {
                 USB_LOG_ERR("Rx packet is overflow\r\n");
@@ -733,46 +711,37 @@ delete:
     // clang-format on
 }
 
-err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p)
+int usbh_asix_eth_output(uint8_t *buf, uint32_t buflen)
 {
-    int ret;
-    struct pbuf *q;
     uint16_t actual_len;
-    uint8_t *buffer = &g_asix_tx_buffer[4];
+    uint8_t *buffer;
 
     if (g_asix_class.connect_status == false) {
-        return ERR_BUF;
+        return -USB_ERR_NOTCONN;
     }
 
-    for (q = p; q != NULL; q = q->next) {
-        memcpy(buffer, q->payload, q->len);
-        buffer += q->len;
-    }
+    buffer = &g_asix_tx_buffer[4];
+    memcpy(buffer, buf, buflen);
 
-    g_asix_tx_buffer[0] = p->tot_len & 0xff;
-    g_asix_tx_buffer[1] = (p->tot_len >> 8) & 0xff;
+    g_asix_tx_buffer[0] = buflen & 0xff;
+    g_asix_tx_buffer[1] = (buflen >> 8) & 0xff;
     g_asix_tx_buffer[2] = ~g_asix_tx_buffer[0];
     g_asix_tx_buffer[3] = ~g_asix_tx_buffer[1];
 
-    if (!(p->tot_len + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
-        USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 8);
-        g_asix_tx_buffer[p->tot_len + 4 + 0] = 0x00;
-        g_asix_tx_buffer[p->tot_len + 4 + 1] = 0x00;
-        g_asix_tx_buffer[p->tot_len + 4 + 2] = 0xff;
-        g_asix_tx_buffer[p->tot_len + 4 + 3] = 0xff;
-        actual_len = p->tot_len + 8;
+    if (!(buflen + 4) % USB_GET_MAXPACKETSIZE(g_asix_class.bulkout->wMaxPacketSize)) {
+        USB_LOG_DBG("txlen:%d\r\n", buflen + 8);
+        g_asix_tx_buffer[buflen + 4 + 0] = 0x00;
+        g_asix_tx_buffer[buflen + 4 + 1] = 0x00;
+        g_asix_tx_buffer[buflen + 4 + 2] = 0xff;
+        g_asix_tx_buffer[buflen + 4 + 3] = 0xff;
+        actual_len = buflen + 8;
     } else {
-        USB_LOG_DBG("txlen:%d\r\n", p->tot_len + 4);
-        actual_len = p->tot_len + 4;
+        USB_LOG_DBG("txlen:%d\r\n", buflen + 4);
+        actual_len = buflen + 4;
     }
 
     usbh_bulk_urb_fill(&g_asix_class.bulkout_urb, g_asix_class.hport, g_asix_class.bulkout, g_asix_tx_buffer, actual_len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
-    ret = usbh_submit_urb(&g_asix_class.bulkout_urb);
-    if (ret < 0) {
-        return ERR_BUF;
-    }
-
-    return ERR_OK;
+    return usbh_submit_urb(&g_asix_class.bulkout_urb);
 }
 
 __WEAK void usbh_asix_run(struct usbh_asix *asix_class)

+ 2 - 8
class/vendor/net/usbh_asix.h

@@ -6,9 +6,6 @@
 #ifndef USBH_ASIX_H
 #define USBH_ASIX_H
 
-#include "lwip/netif.h"
-#include "lwip/pbuf.h"
-
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 
 #define AX_CMD_SET_SW_MII         0x06
@@ -156,10 +153,6 @@ struct usbh_asix {
     bool connect_status;
     uint8_t mac[6];
 
-    ip_addr_t ipaddr;
-    ip_addr_t netmask;
-    ip_addr_t gateway;
-
     void *user_data;
 };
 
@@ -172,8 +165,9 @@ int usbh_asix_get_connect_status(struct usbh_asix *asix_class);
 void usbh_asix_run(struct usbh_asix *asix_class);
 void usbh_asix_stop(struct usbh_asix *asix_class);
 
+int usbh_asix_eth_output(uint8_t *buf, uint32_t buflen);
+void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen);
 void usbh_asix_rx_thread(void *argument);
-err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p);
 
 #ifdef __cplusplus
 }

+ 12 - 41
class/vendor/net/usbh_rtl8152.c

@@ -2122,16 +2122,8 @@ void usbh_rtl8152_rx_thread(void *argument)
 {
     uint32_t g_rtl8152_rx_length;
     int ret;
-    err_t err;
     uint16_t len;
     uint16_t data_offset;
-    struct pbuf *p;
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-    pbuf_type type = PBUF_ROM;
-#else
-    pbuf_type type = PBUF_POOL;
-#endif
-    struct netif *netif = (struct netif *)argument;
 
     USB_LOG_INFO("Create rtl8152 rx thread\r\n");
     // clang-format off
@@ -2181,20 +2173,9 @@ find_class:
 
                 USB_LOG_DBG("data_offset:%d, eth len:%d\r\n", data_offset, len);
 
-                p = pbuf_alloc(PBUF_RAW, len, type);
-                if (p != NULL) {
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-                    p->payload = (uint8_t *)&g_rtl8152_rx_buffer[data_offset + sizeof(struct rx_desc)];
-#else
-                    memcpy(p->payload, (uint8_t *)&g_rtl8152_rx_buffer[data_offset + sizeof(struct rx_desc)], len);
-#endif
-                    err = netif->input(p, netif);
-                    if (err != ERR_OK) {
-                        pbuf_free(p);
-                    }
-                } else {
-                    USB_LOG_ERR("No memory to alloc pbuf for rtl8152 rx\r\n");
-                }
+                uint8_t *buf = (uint8_t *)&g_rtl8152_rx_buffer[data_offset + sizeof(struct rx_desc)];
+                usbh_rtl8152_eth_input(buf, len);
+
                 data_offset += (len + sizeof(struct rx_desc));
                 g_rtl8152_rx_length -= (len + sizeof(struct rx_desc));
 
@@ -2217,36 +2198,26 @@ delete:
     // clang-format on
 }
 
-err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p)
+int usbh_rtl8152_eth_output(uint8_t *buf, uint32_t buflen)
 {
-    int ret;
-    struct pbuf *q;
     uint8_t *buffer;
-    struct tx_desc *tx_desc = (struct tx_desc *)g_rtl8152_tx_buffer;
+    struct tx_desc *tx_desc;
 
     if (g_rtl8152_class.connect_status == false) {
-        return ERR_BUF;
+        return -USB_ERR_NOTCONN;
     }
 
-    tx_desc->opts1 = p->tot_len | TX_FS | TX_LS;
+    tx_desc = (struct tx_desc *)g_rtl8152_tx_buffer;
+    tx_desc->opts1 = buflen | TX_FS | TX_LS;
     tx_desc->opts2 = 0;
 
     buffer = g_rtl8152_tx_buffer + sizeof(struct tx_desc);
+    memcpy(buffer, buf, buflen);
 
-    for (q = p; q != NULL; q = q->next) {
-        memcpy(buffer, q->payload, q->len);
-        buffer += q->len;
-    }
-
-    USB_LOG_DBG("txlen:%d\r\n", p->tot_len + sizeof(struct tx_desc));
-
-    usbh_bulk_urb_fill(&g_rtl8152_class.bulkout_urb, g_rtl8152_class.hport, g_rtl8152_class.bulkout, g_rtl8152_tx_buffer, p->tot_len + sizeof(struct tx_desc), USB_OSAL_WAITING_FOREVER, NULL, NULL);
-    ret = usbh_submit_urb(&g_rtl8152_class.bulkout_urb);
-    if (ret < 0) {
-        return ERR_BUF;
-    }
+    USB_LOG_DBG("txlen:%d\r\n", buflen + sizeof(struct tx_desc));
 
-    return ERR_OK;
+    usbh_bulk_urb_fill(&g_rtl8152_class.bulkout_urb, g_rtl8152_class.hport, g_rtl8152_class.bulkout, g_rtl8152_tx_buffer, buflen + sizeof(struct tx_desc), USB_OSAL_WAITING_FOREVER, NULL, NULL);
+    return usbh_submit_urb(&g_rtl8152_class.bulkout_urb);
 }
 
 __WEAK void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)

+ 2 - 8
class/vendor/net/usbh_rtl8152.h

@@ -6,9 +6,6 @@
 #ifndef USBH_RTL8152_H
 #define USBH_RTL8152_H
 
-#include "lwip/netif.h"
-#include "lwip/pbuf.h"
-
 struct usbh_rtl8152 {
     struct usbh_hubport *hport;
     struct usb_endpoint_descriptor *bulkin;  /* Bulk IN endpoint */
@@ -24,10 +21,6 @@ struct usbh_rtl8152 {
     bool connect_status;
     uint32_t speed[2];
 
-    ip_addr_t ipaddr;
-    ip_addr_t netmask;
-    ip_addr_t gateway;
-
     uint8_t version;
     uint8_t eee_adv;
     uint8_t eee_en;
@@ -63,8 +56,9 @@ int usbh_rtl8152_get_connect_status(struct usbh_rtl8152 *rtl8152_class);
 void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class);
 void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class);
 
+int usbh_rtl8152_eth_output(uint8_t *buf, uint32_t buflen);
+void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen);
 void usbh_rtl8152_rx_thread(void *argument);
-err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p);
 
 #ifdef __cplusplus
 }

+ 15 - 46
class/wireless/usbh_rndis.c

@@ -425,18 +425,10 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
 void usbh_rndis_rx_thread(void *argument)
 {
     uint32_t g_rndis_rx_length;
-    uint32_t pmg_offset;
     int ret;
-    err_t err;
-    struct pbuf *p;
+    uint32_t pmg_offset;
     rndis_data_packet_t *pmsg;
     rndis_data_packet_t temp;
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-    pbuf_type type = PBUF_ROM;
-#else
-    pbuf_type type = PBUF_POOL;
-#endif
-    struct netif *netif = (struct netif *)argument;
 
     USB_LOG_INFO("Create rndis rx thread\r\n");
     // clang-format off
@@ -481,28 +473,15 @@ find_class:
                 }
 
                 if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
-                    p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, type);
-                    if (p != NULL) {
-                        void *src = (void *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
-#if LWIP_TCPIP_CORE_LOCKING_INPUT
-                        p->payload = src;
-#else
-                        memcpy(p->payload, src, pmsg->DataLength);
-#endif
-                        err = netif->input(p, netif);
-                        if (err != ERR_OK) {
-                            pbuf_free(p);
-                        }
-                        pmg_offset += pmsg->MessageLength;
-                        g_rndis_rx_length -= pmsg->MessageLength;
-
-                        /* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
-                        if (g_rndis_rx_length < 4) {
-                            g_rndis_rx_length = 0;
-                        }
-                    } else {
+                    uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
+
+                    usbh_rndis_eth_input(buf, pmsg->DataLength);
+                    pmg_offset += pmsg->MessageLength;
+                    g_rndis_rx_length -= pmsg->MessageLength;
+
+                    /* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
+                    if (g_rndis_rx_length < 4) {
                         g_rndis_rx_length = 0;
-                        USB_LOG_ERR("No memory to alloc pbuf for rndis rx\r\n");
                     }
                 } else {
                     USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
@@ -525,31 +504,26 @@ delete:
     // clang-format on
 }
 
-err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
+int usbh_rndis_eth_output(uint8_t *buf, uint32_t buflen)
 {
-    int ret;
-    struct pbuf *q;
     uint8_t *buffer;
     rndis_data_packet_t *hdr;
     uint32_t len;
 
     if (g_rndis_class.connect_status == false) {
-        return ERR_BUF;
+        return -USB_ERR_NOTCONN;
     }
 
     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->MessageLength = sizeof(rndis_data_packet_t) + buflen;
     hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
-    hdr->DataLength = p->tot_len;
+    hdr->DataLength = buflen;
 
     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;
-    }
+    memcpy(buffer, buf, buflen);
 
     len = hdr->MessageLength;
     /* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
@@ -560,12 +534,7 @@ err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
     USB_LOG_DBG("txlen:%d\r\n", len);
 
     usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
-    ret = usbh_submit_urb(&g_rndis_class.bulkout_urb);
-    if (ret < 0) {
-        return ERR_BUF;
-    }
-
-    return ERR_OK;
+    return usbh_submit_urb(&g_rndis_class.bulkout_urb);
 }
 
 __WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)

+ 2 - 8
class/wireless/usbh_rndis.h

@@ -8,9 +8,6 @@
 
 #include "usb_cdc.h"
 
-#include "lwip/netif.h"
-#include "lwip/pbuf.h"
-
 struct usbh_rndis {
     struct usbh_hubport *hport;
     struct usb_endpoint_descriptor *bulkin;  /* Bulk IN endpoint */
@@ -30,10 +27,6 @@ struct usbh_rndis {
     bool connect_status;
     uint8_t mac[6];
 
-    ip_addr_t ipaddr;
-    ip_addr_t netmask;
-    ip_addr_t gateway;
-
     void *user_data;
 };
 
@@ -47,7 +40,8 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
 void usbh_rndis_run(struct usbh_rndis *rndis_class);
 void usbh_rndis_stop(struct usbh_rndis *rndis_class);
 
-err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p);
+int usbh_rndis_eth_output(uint8_t *buf, uint32_t buflen);
+void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen);
 void usbh_rndis_rx_thread(void *argument);
 
 #ifdef __cplusplus

+ 14 - 0
platform/README.md

@@ -0,0 +1,14 @@
+# Platform Support
+
+This is a platform support for other os with their own components.
+
+| Platform  |  fs          |  net         | serial       |
+|:---------:|:------------:|:------------:|:------------:|
+|none       |  fatfs       | lwip         |  none        |
+|rtthread   |  dfs         | lwip         |  rt_device   |
+|nuttx      |  nuttx block driver | nuttx net  |  nuttx char driver|
+|threadx    |  filex       | netx         | none         |
+
+- **fs** is for usbd_msc and usbh_msc
+- **net** is for cdc_ecm, cdc_rndis, cdc_ncm, asix, rtl8152 and so on.
+- **serial** is for cdc_acm, ch340, ftdi, cp210x, pl2303 and so on.

+ 7 - 1
third_party/fatfs-0.14/source/port/fatfs_usbh.c → platform/none/usbh_fatfs.c

@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include "ff.h"
 #include "diskio.h"
 #include "usbh_core.h"
@@ -9,6 +14,7 @@ int USB_disk_status(void)
 {
     return 0;
 }
+
 int USB_disk_initialize(void)
 {
     active_msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
@@ -59,4 +65,4 @@ int USB_disk_ioctl(BYTE cmd, void *buff)
     }
 
     return result;
-}
+}

+ 504 - 0
platform/none/usbh_lwip.c

@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "netif/etharp.h"
+#include "lwip/netif.h"
+#include "lwip/pbuf.h"
+#include "lwip/tcpip.h"
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#include "lwip/prot/dhcp.h"
+#endif
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+#include "timers.h"
+
+#include "usbh_core.h"
+
+#if LWIP_TCPIP_CORE_LOCKING_INPUT !=1
+#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread
+#endif
+
+#if LWIP_TCPIP_CORE_LOCKING !=1
+#error must set LWIP_TCPIP_CORE_LOCKING to 1
+#endif
+
+#if PBUF_POOL_BUFSIZE < 1600
+#error PBUF_POOL_BUFSIZE must be larger than 1600
+#endif
+
+#define CONFIG_USBHOST_PLATFORM_CDC_ECM
+#define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
+#define CONFIG_USBHOST_PLATFORM_CDC_NCM
+#define CONFIG_USBHOST_PLATFORM_ASIX
+#define CONFIG_USBHOST_PLATFORM_RTL8152
+
+ip_addr_t g_ipaddr;
+ip_addr_t g_netmask;
+ip_addr_t g_gateway;
+
+void usbh_lwip_eth_input_common(struct netif *netif, uint8_t *buf, uint32_t len)
+{
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+    pbuf_type type = PBUF_REF;
+#else
+    pbuf_type type = PBUF_POOL;
+#endif
+    err_t err;
+    struct pbuf *p;
+
+    p = pbuf_alloc(PBUF_RAW, len, type);
+    if (p != NULL) {
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+        p->payload = buf;
+#else
+        memcpy(p->payload, buf, len);
+#endif
+        err = netif->input(p, netif);
+        if (err != ERR_OK) {
+            pbuf_free(p);
+        }
+    } else {
+        USB_LOG_ERR("No memory to alloc pbuf\r\n");
+    }
+}
+
+TimerHandle_t dhcp_handle;
+
+static void dhcp_timeout(TimerHandle_t xTimer)
+{
+    struct netif *netif = (struct netif *)pvTimerGetTimerID(xTimer);
+    struct dhcp *dhcp;
+
+    if (netif_is_up(netif)) {
+        dhcp = netif_dhcp_data(netif);
+
+        if (dhcp && (dhcp->state == DHCP_STATE_BOUND)) {
+            USB_LOG_INFO("IPv4 Address     : %s\r\n", ipaddr_ntoa(&netif->ip_addr));
+            USB_LOG_INFO("IPv4 Subnet mask : %s\r\n", ipaddr_ntoa(&netif->netmask));
+            USB_LOG_INFO("IPv4 Gateway     : %s\r\n\r\n", ipaddr_ntoa(&netif->gw));
+
+            xTimerStop(xTimer, 0);
+        }
+    }
+}
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_ECM
+#include "usbh_cdc_ecm.h"
+
+struct netif g_cdc_ecm_netif;
+
+static err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
+{
+    int ret = usbh_cdc_ecm_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return ERR_BUF;
+    } else {
+        return ERR_OK;
+    }
+}
+
+void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(&g_cdc_ecm_netif, buf, buflen);
+}
+
+static err_t usbh_cdc_ecm_if_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+    netif->mtu = 1500;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
+    netif->state = NULL;
+    netif->name[0] = 'E';
+    netif->name[1] = 'X';
+    netif->output = etharp_output;
+    netif->linkoutput = usbh_cdc_ecm_linkoutput;
+    return ERR_OK;
+}
+
+void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
+{
+    struct netif *netif = &g_cdc_ecm_netif;
+
+    netif->hwaddr_len = 6;
+    memcpy(netif->hwaddr, cdc_ecm_class->mac, 6);
+
+    IP4_ADDR(&g_ipaddr, 0, 0, 0, 0);
+    IP4_ADDR(&g_netmask, 0, 0, 0, 0);
+    IP4_ADDR(&g_gateway, 0, 0, 0, 0);
+
+    netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_cdc_ecm_if_init, tcpip_input);
+    netif_set_default(netif);
+    while (!netif_is_up(netif)) {
+    }
+
+    dhcp_handle = xTimerCreate((const char *)"dhcp", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
+    if (dhcp_handle == NULL) {
+        USB_LOG_ERR("timer creation failed! \r\n");
+        while (1) {
+        }
+    }
+
+    usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL);
+#if LWIP_DHCP
+    dhcp_start(netif);
+    xTimerStart(dhcp_handle, 0);
+#endif
+}
+
+void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
+{
+    struct netif *netif = &g_cdc_ecm_netif;
+#if LWIP_DHCP
+    dhcp_stop(netif);
+    dhcp_cleanup(netif);
+    xTimerStop(dhcp_handle, 0);
+    xTimerDelete(dhcp_handle, 0);
+#endif
+    netif_set_down(netif);
+    netif_remove(netif);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
+#include "usbh_rndis.h"
+
+TimerHandle_t timer_handle;
+
+static void rndis_dev_keepalive_timeout(TimerHandle_t xTimer)
+{
+    struct usbh_rndis *rndis_class = (struct usbh_rndis *)pvTimerGetTimerID(xTimer);
+    usbh_rndis_keepalive(rndis_class);
+}
+
+void timer_init(struct usbh_rndis *rndis_class)
+{
+    timer_handle = xTimerCreate((const char *)NULL, (TickType_t)5000, (UBaseType_t)pdTRUE, (void *const)rndis_class, (TimerCallbackFunction_t)rndis_dev_keepalive_timeout);
+    if (NULL != timer_handle) {
+        xTimerStart(timer_handle, 0);
+    } else {
+        USB_LOG_ERR("timer creation failed! \r\n");
+        for (;;) {
+            ;
+        }
+    }
+}
+
+struct netif g_rndis_netif;
+
+static err_t usbh_rndis_linkoutput(struct netif *netif, struct pbuf *p)
+{
+    int ret = usbh_rndis_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return ERR_BUF;
+    } else {
+        return ERR_OK;
+    }
+}
+
+void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(&g_rndis_netif, buf, buflen);
+}
+
+static err_t usbh_rndis_if_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+    netif->mtu = 1500;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
+    netif->state = NULL;
+    netif->name[0] = 'E';
+    netif->name[1] = 'X';
+    netif->output = etharp_output;
+    netif->linkoutput = usbh_rndis_linkoutput;
+    return ERR_OK;
+}
+
+void usbh_rndis_run(struct usbh_rndis *rndis_class)
+{
+    struct netif *netif = &g_rndis_netif;
+
+    netif->hwaddr_len = 6;
+    memcpy(netif->hwaddr, rndis_class->mac, 6);
+
+    IP4_ADDR(&g_ipaddr, 0, 0, 0, 0);
+    IP4_ADDR(&g_netmask, 0, 0, 0, 0);
+    IP4_ADDR(&g_gateway, 0, 0, 0, 0);
+
+    netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_rndis_if_init, tcpip_input);
+    netif_set_default(netif);
+    while (!netif_is_up(netif)) {
+    }
+
+    dhcp_handle = xTimerCreate((const char *)"dhcp", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
+    if (dhcp_handle == NULL) {
+        USB_LOG_ERR("timer creation failed! \r\n");
+        while (1) {
+        }
+    }
+
+    usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
+
+    //timer_init(rndis_class);
+
+#if LWIP_DHCP
+    dhcp_start(netif);
+    xTimerStart(dhcp_handle, 0);
+#endif
+}
+
+void usbh_rndis_stop(struct usbh_rndis *rndis_class)
+{
+    struct netif *netif = &g_rndis_netif;
+#if LWIP_DHCP
+    dhcp_stop(netif);
+    dhcp_cleanup(netif);
+    xTimerStop(dhcp_handle, 0);
+    xTimerDelete(dhcp_handle, 0);
+#endif
+    netif_set_down(netif);
+    netif_remove(netif);
+    // xTimerStop(timer_handle, 0);
+    // xTimerDelete(timer_handle, 0);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_NCM
+#include "usbh_cdc_ncm.h"
+
+struct netif g_cdc_ncm_netif;
+
+static err_t usbh_cdc_ncm_linkoutput(struct netif *netif, struct pbuf *p)
+{
+    int ret = usbh_cdc_ncm_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return ERR_BUF;
+    } else {
+        return ERR_OK;
+    }
+}
+
+void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(&g_cdc_ncm_netif, buf, buflen);
+}
+
+static err_t usbh_cdc_ncm_if_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+    netif->mtu = 1500;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
+    netif->state = NULL;
+    netif->name[0] = 'E';
+    netif->name[1] = 'X';
+    netif->output = etharp_output;
+    netif->linkoutput = usbh_cdc_ncm_linkoutput;
+    return ERR_OK;
+}
+
+void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
+{
+    struct netif *netif = &g_cdc_ncm_netif;
+
+    netif->hwaddr_len = 6;
+    memcpy(netif->hwaddr, cdc_ncm_class->mac, 6);
+
+    IP4_ADDR(&g_ipaddr, 0, 0, 0, 0);
+    IP4_ADDR(&g_netmask, 0, 0, 0, 0);
+    IP4_ADDR(&g_gateway, 0, 0, 0, 0);
+
+    netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_cdc_ncm_if_init, tcpip_input);
+    netif_set_default(netif);
+    while (!netif_is_up(netif)) {
+    }
+
+    dhcp_handle = xTimerCreate((const char *)"dhcp", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
+    if (dhcp_handle == NULL) {
+        USB_LOG_ERR("timer creation failed! \r\n");
+        while (1) {
+        }
+    }
+
+    usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, NULL);
+#if LWIP_DHCP
+    dhcp_start(netif);
+    xTimerStart(dhcp_handle, 0);
+#endif
+}
+
+void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
+{
+    struct netif *netif = &g_cdc_ncm_netif;
+#if LWIP_DHCP
+    dhcp_stop(netif);
+    dhcp_cleanup(netif);
+    xTimerStop(dhcp_handle, 0);
+    xTimerDelete(dhcp_handle, 0);
+#endif
+    netif_set_down(netif);
+    netif_remove(netif);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_ASIX
+#include "usbh_asix.h"
+
+struct netif g_asix_netif;
+
+static err_t usbh_asix_linkoutput(struct netif *netif, struct pbuf *p)
+{
+    int ret = usbh_asix_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return ERR_BUF;
+    } else {
+        return ERR_OK;
+    }
+}
+
+void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(&g_asix_netif, buf, buflen);
+}
+
+static err_t usbh_asix_if_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+    netif->mtu = 1500;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
+    netif->state = NULL;
+    netif->name[0] = 'E';
+    netif->name[1] = 'X';
+    netif->output = etharp_output;
+    netif->linkoutput = usbh_asix_linkoutput;
+    return ERR_OK;
+}
+
+void usbh_asix_run(struct usbh_asix *asix_class)
+{
+    struct netif *netif = &g_asix_netif;
+
+    netif->hwaddr_len = 6;
+    memcpy(netif->hwaddr, asix_class->mac, 6);
+
+    IP4_ADDR(&g_ipaddr, 0, 0, 0, 0);
+    IP4_ADDR(&g_netmask, 0, 0, 0, 0);
+    IP4_ADDR(&g_gateway, 0, 0, 0, 0);
+
+    netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_asix_if_init, tcpip_input);
+    netif_set_default(netif);
+    while (!netif_is_up(netif)) {
+    }
+
+    dhcp_handle = xTimerCreate((const char *)"dhcp", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
+    if (dhcp_handle == NULL) {
+        USB_LOG_ERR("timer creation failed! \r\n");
+        while (1) {
+        }
+    }
+
+    usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, NULL);
+#if LWIP_DHCP
+    dhcp_start(netif);
+    xTimerStart(dhcp_handle, 0);
+#endif
+}
+
+void usbh_asix_stop(struct usbh_asix *asix_class)
+{
+    struct netif *netif = &g_asix_netif;
+#if LWIP_DHCP
+    dhcp_stop(netif);
+    dhcp_cleanup(netif);
+    xTimerStop(dhcp_handle, 0);
+    xTimerDelete(dhcp_handle, 0);
+#endif
+    netif_set_down(netif);
+    netif_remove(netif);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_RTL8152
+#include "usbh_rtl8152.h"
+
+struct netif g_rtl8152_netif;
+
+static err_t usbh_rtl8152_linkoutput(struct netif *netif, struct pbuf *p)
+{
+    int ret = usbh_rtl8152_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return ERR_BUF;
+    } else {
+        return ERR_OK;
+    }
+}
+
+void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(&g_rtl8152_netif, buf, buflen);
+}
+
+static err_t usbh_rtl8152_if_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+    netif->mtu = 1500;
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
+    netif->state = NULL;
+    netif->name[0] = 'E';
+    netif->name[1] = 'X';
+    netif->output = etharp_output;
+    netif->linkoutput = usbh_rtl8152_linkoutput;
+    return ERR_OK;
+}
+
+void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
+{
+    struct netif *netif = &g_rtl8152_netif;
+
+    netif->hwaddr_len = 6;
+    memcpy(netif->hwaddr, rtl8152_class->mac, 6);
+
+    IP4_ADDR(&g_ipaddr, 0, 0, 0, 0);
+    IP4_ADDR(&g_netmask, 0, 0, 0, 0);
+    IP4_ADDR(&g_gateway, 0, 0, 0, 0);
+
+    netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_rtl8152_if_init, tcpip_input);
+    netif_set_default(netif);
+    while (!netif_is_up(netif)) {
+    }
+
+    dhcp_handle = xTimerCreate((const char *)"dhcp", (TickType_t)200, (UBaseType_t)pdTRUE, (void *const)netif, (TimerCallbackFunction_t)dhcp_timeout);
+    if (dhcp_handle == NULL) {
+        USB_LOG_ERR("timer creation failed! \r\n");
+        while (1) {
+        }
+    }
+
+    usb_osal_thread_create("usbh_rtl8152_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rtl8152_rx_thread, NULL);
+#if LWIP_DHCP
+    dhcp_start(netif);
+    xTimerStart(dhcp_handle, 0);
+#endif
+}
+
+void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
+{
+    struct netif *netif = &g_rtl8152_netif;
+#if LWIP_DHCP
+    dhcp_stop(netif);
+    dhcp_cleanup(netif);
+    xTimerStop(dhcp_handle, 0);
+    xTimerDelete(dhcp_handle, 0);
+#endif
+    netif_set_down(netif);
+    netif_remove(netif);
+}
+#endif

+ 189 - 0
platform/nuttx/usbh_fs.c

@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <nuttx/config.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/scsi.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/mutex.h>
+
+#include "usbh_core.h"
+#include "usbh_msc.h"
+
+#ifdef CONFIG_ARCH_CHIP_HPMICRO
+#include "hpm_misc.h"
+#define usbhmsc_phy2sysaddr(a) core_local_mem_to_sys_address(0, a)
+#else
+#define usbhmsc_phy2sysaddr(a) (a)
+#endif
+
+static int usbhost_open(FAR struct inode *inode);
+static int usbhost_close(FAR struct inode *inode);
+static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
+                            blkcnt_t startsector, unsigned int nsectors);
+static ssize_t usbhost_write(FAR struct inode *inode,
+                             FAR const unsigned char *buffer,
+                             blkcnt_t startsector, unsigned int nsectors);
+static int usbhost_geometry(FAR struct inode *inode,
+                            FAR struct geometry *geometry);
+static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg);
+/* Block driver operations.  This is the interface exposed to NuttX by the
+ * class that permits it to behave like a block driver.
+ */
+
+static const struct block_operations g_bops = {
+    usbhost_open,     /* open     */
+    usbhost_close,    /* close    */
+    usbhost_read,     /* read     */
+    usbhost_write,    /* write    */
+    usbhost_geometry, /* geometry */
+    usbhost_ioctl     /* ioctl    */
+};
+
+static int usbhost_open(FAR struct inode *inode)
+{
+    struct usbh_msc *msc_class;
+
+    DEBUGASSERT(inode->i_private);
+    msc_class = (struct usbh_msc *)inode->i_private;
+
+    if (msc_class->hport && msc_class->hport->connected) {
+        return OK;
+    } else {
+        return -ENODEV;
+    }
+}
+
+static int usbhost_close(FAR struct inode *inode)
+{
+    DEBUGASSERT(inode->i_private);
+    return 0;
+}
+
+static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
+                            blkcnt_t startsector, unsigned int nsectors)
+{
+    struct usbh_msc *msc_class;
+    int ret;
+
+    DEBUGASSERT(inode->i_private);
+    msc_class = (struct usbh_msc *)inode->i_private;
+
+    if (msc_class->hport && msc_class->hport->connected) {
+        ret = usbh_msc_scsi_read10(msc_class, startsector, (uint8_t *)usbhmsc_phy2sysaddr((uint32_t)buffer), nsectors);
+        if (ret < 0) {
+            return ret;
+        } else {
+#ifdef CONFIG_USBHOST_MSC_DCACHE
+            up_invalidate_dcache((uintptr_t)buffer, (uintptr_t)(buffer + nsectors * msc_class->blocksize));
+#endif
+            return nsectors;
+        }
+    } else {
+        return -ENODEV;
+    }
+}
+
+static ssize_t usbhost_write(FAR struct inode *inode,
+                             FAR const unsigned char *buffer,
+                             blkcnt_t startsector, unsigned int nsectors)
+{
+    struct usbh_msc *msc_class;
+    int ret;
+
+    DEBUGASSERT(inode->i_private);
+    msc_class = (struct usbh_msc *)inode->i_private;
+
+    if (msc_class->hport && msc_class->hport->connected) {
+#ifdef CONFIG_USBHOST_MSC_DCACHE
+        up_flush_dcache((uintptr_t)buffer, (uintptr_t)(buffer + nsectors * msc_class->blocksize));
+#endif
+        ret = usbh_msc_scsi_write10(msc_class, startsector, (uint8_t *)usbhmsc_phy2sysaddr((uint32_t)buffer), nsectors);
+        if (ret < 0) {
+            return ret;
+        } else {
+            return nsectors;
+        }
+    } else {
+        return -ENODEV;
+    }
+}
+
+static int usbhost_geometry(FAR struct inode *inode,
+                            FAR struct geometry *geometry)
+{
+    struct usbh_msc *msc_class;
+
+    DEBUGASSERT(inode->i_private);
+    msc_class = (struct usbh_msc *)inode->i_private;
+
+    if (msc_class->hport && msc_class->hport->connected) {
+        memset(geometry, 0, sizeof(*geometry));
+
+        geometry->geo_available = true;
+        geometry->geo_mediachanged = false;
+        geometry->geo_writeenabled = true;
+        geometry->geo_nsectors = msc_class->blocknum;
+        geometry->geo_sectorsize = msc_class->blocksize;
+
+        uinfo("nsectors: %" PRIdOFF " sectorsize: %" PRIi16 "\n",
+              geometry->geo_nsectors, geometry->geo_sectorsize);
+        return OK;
+    } else {
+        return -ENODEV;
+    }
+
+    return 0;
+}
+
+static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
+{
+    struct usbh_msc *msc_class;
+
+    DEBUGASSERT(inode->i_private);
+    msc_class = (struct usbh_msc *)inode->i_private;
+
+    if (msc_class->hport && msc_class->hport->connected) {
+        return -ENOTTY;
+    } else {
+        return -ENODEV;
+    }
+
+    return 0;
+}
+
+#define DEV_FORMAT "/dev/sd%c"
+
+void usbh_msc_run(struct usbh_msc *msc_class)
+{
+    char devname[32];
+
+    snprintf(devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
+
+    register_blockdriver(devname, &g_bops, 0, msc_class);
+}
+
+void usbh_msc_stop(struct usbh_msc *msc_class)
+{
+    char devname[32];
+
+    snprintf(devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
+
+    unregister_blockdriver(devname);
+}

+ 165 - 0
platform/nuttx/usbh_net.c

@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/net/ip.h>
+#include <nuttx/net/netdev.h>
+
+#include "usbh_core.h"
+
+#define CONFIG_USBHOST_PLATFORM_CDC_ECM
+#define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
+#define CONFIG_USBHOST_PLATFORM_CDC_NCM
+#define CONFIG_USBHOST_PLATFORM_ASIX
+#define CONFIG_USBHOST_PLATFORM_RTL8152
+
+struct usbh_net {
+    struct net_driver_s netdev;
+    struct work_s txpollwork;
+    bool linkup;
+};
+
+void usbh_net_eth_input_common(struct net_driver_s *dev, uint8_t *buf, size_t len, int (*eth_output)(uint8_t *buf, uint32_t buflen))
+{
+    FAR struct eth_hdr_s *hdr;
+
+    net_lock();
+
+    NETDEV_RXPACKETS(dev);
+
+    /* Any ACK or other response packet generated by the network stack
+   * will always be shorter than the received packet, therefore it is
+   * safe to pass the received frame buffer directly.
+   */
+
+    dev->d_buf = buf;
+    dev->d_len = len;
+
+    hdr = (FAR struct eth_hdr_s *)dev->d_buf;
+#ifdef CONFIG_NET_IPv4
+    if (hdr->type == HTONS(ETHTYPE_IP)) {
+        NETDEV_RXIPV4(dev);
+
+        /* Receive an IPv4 packet from the network device */
+
+        ipv4_input(dev);
+        if (dev->d_len > 0) {
+            /* And send the packet */
+            eth_output(dev->d_buf, dev->d_len);
+        }
+    } else
+#endif
+#ifdef CONFIG_NET_IPv6
+        if (hdr->type == HTONS(ETHTYPE_IP6)) {
+        NETDEV_RXIPV6(dev);
+
+        /* Give the IPv6 packet to the network layer */
+
+        ipv6_input(dev);
+
+        if (dev->d_len > 0) {
+            /* And send the packet */
+            eth_output(dev->d_buf, dev->d_len);
+        }
+    } else
+#endif
+#ifdef CONFIG_NET_ARP
+        if (hdr->type == HTONS(ETHTYPE_ARP)) {
+        NETDEV_RXARP(dev);
+
+        arp_input(dev);
+        if (dev->d_len > 0) {
+            eth_output(dev->d_buf, dev->d_len);
+        }
+    } else
+#endif
+    {
+        NETDEV_RXDROPPED(dev);
+    }
+
+    net_unlock();
+}
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
+#include "usbh_rndis.h"
+
+struct usbh_net g_rndis_dev;
+
+static int rndis_ifup(struct net_driver_s *dev)
+{
+    printf("rndis if up\r\n");
+    g_rndis_dev.linkup = true;
+    usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
+    return OK;
+}
+
+static int rndis_ifdown(struct net_driver_s *dev)
+{
+    printf("rndis if down\r\n");
+    g_rndis_dev.linkup = false;
+    return OK;
+}
+
+static int rndis_txpoll(struct net_driver_s *dev)
+{
+    return usbh_rndis_eth_output(g_rndis_dev.netdev.d_buf, g_rndis_dev.netdev.d_len);
+}
+
+static void rndis_txavail_work(void *arg)
+{
+    net_lock();
+
+    if (g_rndis_dev.linkup) {
+        devif_poll(&g_rndis_dev.netdev, rndis_txpoll);
+    } else {
+    }
+
+    net_unlock();
+}
+
+static int rndis_txavail(struct net_driver_s *dev)
+{
+    if (work_available(&g_rndis_dev.txpollwork)) {
+        work_queue(LPWORK, &g_rndis_dev.txpollwork, rndis_txavail_work, NULL, 0);
+    } else {
+        return -1;
+    }
+
+    return OK;
+}
+
+void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_net_eth_input_common(&g_rndis_dev.netdev, buf, buflen, usbh_rndis_eth_output);
+}
+
+void usbh_rndis_run(struct usbh_rndis *rndis_class)
+{
+    memset(&g_rndis_dev.netdev, 0, sizeof(struct net_driver_s));
+
+    g_rndis_dev.netdev.d_ifup = rndis_ifup;
+    g_rndis_dev.netdev.d_ifdown = rndis_ifdown;
+    g_rndis_dev.netdev.d_txavail = rndis_txavail;
+    g_rndis_dev.netdev.d_private = rndis_class;
+
+    for (uint8_t j = 0; j < 6; j++) {
+        g_rndis_dev.netdev.d_mac.ether.ether_addr_octet[j] = rndis_class->mac[j];
+    }
+    netdev_register(&g_rndis_dev.netdev, NET_LL_ETHERNET);
+}
+
+void usbh_rndis_stop(struct usbh_rndis *rndis_class)
+{
+}
+#endif

+ 17 - 0
platform/rtthread/usb_check.c

@@ -0,0 +1,17 @@
+#include "rtthread.h"
+
+#ifdef PKG_CHERRYUSB_HOST
+
+#ifndef RT_USING_TIMER_SOFT
+#error must enable RT_USING_TIMER_SOFT to support timer callback in thread
+#endif
+
+#if IDLE_THREAD_STACK_SIZE < 2048
+#error "IDLE_THREAD_STACK_SIZE must be greater than 2048"
+#endif
+
+#if RT_TIMER_THREAD_STACK_SIZE < 2048
+#error "RT_TIMER_THREAD_STACK_SIZE must be greater than 2048"
+#endif
+
+#endif

+ 0 - 0
third_party/rt-thread-5.0/usb_msh.c → platform/rtthread/usb_msh.c


+ 1 - 1
third_party/rt-thread-5.0/dfs_usbh_msc.c → platform/rtthread/usbh_dfs.c

@@ -238,4 +238,4 @@ void usbh_msc_stop(struct usbh_msc *msc_class)
 
     dfs_unmount(mount_point);
     rt_device_unregister(rt_device_find(name));
-}
+}

+ 415 - 0
platform/rtthread/usbh_lwip.c

@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "netif/etharp.h"
+#include "lwip/netif.h"
+#include "lwip/pbuf.h"
+#include "lwip/tcpip.h"
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#include "lwip/prot/dhcp.h"
+#endif
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <netif/ethernetif.h>
+
+#include "usbh_core.h"
+
+#include "lwip/opt.h"
+
+#ifndef RT_USING_LWIP212
+#error must enable RT_USING_LWIP212
+#endif
+
+#ifndef LWIP_NO_RX_THREAD
+#error must enable LWIP_NO_RX_THREAD, we do not use rtthread eth rx thread
+#endif
+
+#ifndef LWIP_NO_TX_THREAD
+#warning suggest you to enable LWIP_NO_TX_THREAD, we do not use rtthread eth tx thread
+#endif
+
+#if LWIP_TCPIP_CORE_LOCKING_INPUT !=1
+#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread
+#endif
+
+#if LWIP_TCPIP_CORE_LOCKING !=1
+#error must set LWIP_TCPIP_CORE_LOCKING to 1
+#endif
+
+#if PBUF_POOL_BUFSIZE < 1600
+#error PBUF_POOL_BUFSIZE must be larger than 1600
+#endif
+
+// #define CONFIG_USBHOST_PLATFORM_CDC_ECM
+// #define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
+// #define CONFIG_USBHOST_PLATFORM_CDC_NCM
+// #define CONFIG_USBHOST_PLATFORM_ASIX
+// #define CONFIG_USBHOST_PLATFORM_RTL8152
+
+void usbh_lwip_eth_input_common(struct netif *netif, uint8_t *buf, uint32_t len)
+{
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+    pbuf_type type = PBUF_REF;
+#else
+    pbuf_type type = PBUF_POOL;
+#endif
+    err_t err;
+    struct pbuf *p;
+
+    p = pbuf_alloc(PBUF_RAW, len, type);
+    if (p != NULL) {
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+        p->payload = buf;
+#else
+        memcpy(p->payload, buf, len);
+#endif
+        err = netif->input(p, netif);
+        if (err != ERR_OK) {
+            pbuf_free(p);
+        }
+    } else {
+        USB_LOG_ERR("No memory to alloc pbuf\r\n");
+    }
+}
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_ECM
+#include "usbh_cdc_ecm.h"
+
+static struct eth_device g_cdc_ecm_dev;
+
+static rt_err_t rt_usbh_cdc_ecm_control(rt_device_t dev, int cmd, void *args)
+{
+    struct usbh_cdc_ecm *cdc_ecm_class = (struct usbh_cdc_ecm *)dev->user_data;
+
+    switch (cmd) {
+        case NIOCTL_GADDR:
+
+            /* get mac address */
+            if (args)
+                rt_memcpy(args, cdc_ecm_class->mac, 6);
+            else
+                return -RT_ERROR;
+
+            break;
+
+        default:
+            break;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_usbh_cdc_ecm_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    int ret = usbh_cdc_ecm_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return -RT_ERROR;
+    } else {
+        return RT_EOK;
+    }
+}
+
+void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(g_cdc_ecm_dev.netif, buf, buflen);
+}
+
+void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
+{
+    memset(&g_cdc_ecm_dev, 0, sizeof(struct eth_device));
+
+    g_cdc_ecm_dev.parent.control = rt_usbh_cdc_ecm_control;
+    g_cdc_ecm_dev.eth_rx = NULL;
+    g_cdc_ecm_dev.eth_tx = rt_usbh_cdc_ecm_eth_tx;
+    g_cdc_ecm_dev.parent.user_data = cdc_ecm_class;
+
+    eth_device_init(&g_cdc_ecm_dev, "u0");
+    eth_device_linkchange(&g_cdc_ecm_dev, RT_TRUE);
+
+    usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL);
+}
+
+void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
+{
+    eth_device_deinit(&g_cdc_ecm_dev);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
+#include "usbh_rndis.h"
+
+static struct eth_device g_rndis_dev;
+
+static rt_timer_t keep_timer = RT_NULL;
+
+static void rndis_dev_keepalive_timeout(void *parameter)
+{
+    struct usbh_rndis *rndis_class = (struct usbh_rndis *)parameter;
+    usbh_rndis_keepalive(rndis_class);
+}
+
+static void timer_init(struct usbh_rndis *rndis_class)
+{
+    keep_timer = rt_timer_create("keep",
+                                 rndis_dev_keepalive_timeout,
+                                 rndis_class,
+                                 5000,
+                                 RT_TIMER_FLAG_PERIODIC |
+                                     RT_TIMER_FLAG_SOFT_TIMER);
+
+    rt_timer_start(keep_timer);
+}
+
+static rt_err_t rt_usbh_rndis_control(rt_device_t dev, int cmd, void *args)
+{
+    struct usbh_rndis *rndis_class = (struct usbh_rndis *)dev->user_data;
+
+    switch (cmd) {
+        case NIOCTL_GADDR:
+
+            /* get mac address */
+            if (args)
+                rt_memcpy(args, rndis_class->mac, 6);
+            else
+                return -RT_ERROR;
+
+            break;
+
+        default:
+            break;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_usbh_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    int ret = usbh_rndis_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return -RT_ERROR;
+    } else {
+        return RT_EOK;
+    }
+}
+
+void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(g_rndis_dev.netif, buf, buflen);
+}
+
+void usbh_rndis_run(struct usbh_rndis *rndis_class)
+{
+    memset(&g_rndis_dev, 0, sizeof(struct eth_device));
+
+    g_rndis_dev.parent.control = rt_usbh_rndis_control;
+    g_rndis_dev.eth_rx = NULL;
+    g_rndis_dev.eth_tx = rt_usbh_rndis_eth_tx;
+    g_rndis_dev.parent.user_data = rndis_class;
+
+    eth_device_init(&g_rndis_dev, "u2");
+    eth_device_linkchange(&g_rndis_dev, RT_TRUE);
+
+    usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
+    //timer_init(rndis_class);
+}
+
+void usbh_rndis_stop(struct usbh_rndis *rndis_class)
+{
+    eth_device_deinit(&g_rndis_dev);
+    // rt_timer_stop(keep_timer);
+    // rt_timer_delete(keep_timer);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_CDC_NCM
+#include "usbh_cdc_ncm.h"
+
+static struct eth_device g_cdc_ncm_dev;
+
+static rt_err_t rt_usbh_cdc_ncm_control(rt_device_t dev, int cmd, void *args)
+{
+    struct usbh_cdc_ncm *cdc_ncm_class = (struct usbh_cdc_ncm *)dev->user_data;
+
+    switch (cmd) {
+        case NIOCTL_GADDR:
+
+            /* get mac address */
+            if (args)
+                rt_memcpy(args, cdc_ncm_class->mac, 6);
+            else
+                return -RT_ERROR;
+
+            break;
+
+        default:
+            break;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_usbh_cdc_ncm_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    int ret = usbh_cdc_ncm_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return -RT_ERROR;
+    } else {
+        return RT_EOK;
+    }
+}
+
+void usbh_cdc_ncm_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(g_cdc_ncm_dev.netif, buf, buflen);
+}
+
+void usbh_cdc_ncm_run(struct usbh_cdc_ncm *cdc_ncm_class)
+{
+    memset(&g_cdc_ncm_dev, 0, sizeof(struct eth_device));
+
+    g_cdc_ncm_dev.parent.control = rt_usbh_cdc_ncm_control;
+    g_cdc_ncm_dev.eth_rx = NULL;
+    g_cdc_ncm_dev.eth_tx = rt_usbh_cdc_ncm_eth_tx;
+    g_cdc_ncm_dev.parent.user_data = cdc_ncm_class;
+
+    eth_device_init(&g_cdc_ncm_dev, "u1");
+    eth_device_linkchange(&g_cdc_ncm_dev, RT_TRUE);
+
+    usb_osal_thread_create("usbh_cdc_ncm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ncm_rx_thread, NULL);
+}
+
+void usbh_cdc_ncm_stop(struct usbh_cdc_ncm *cdc_ncm_class)
+{
+    eth_device_deinit(&g_cdc_ncm_dev);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_ASIX
+#include "usbh_asix.h"
+
+static struct eth_device g_asix_dev;
+
+static rt_err_t rt_usbh_asix_control(rt_device_t dev, int cmd, void *args)
+{
+    struct usbh_asix *asix_class = (struct usbh_asix *)dev->user_data;
+
+    switch (cmd) {
+        case NIOCTL_GADDR:
+
+            /* get mac address */
+            if (args)
+                rt_memcpy(args, asix_class->mac, 6);
+            else
+                return -RT_ERROR;
+
+            break;
+
+        default:
+            break;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_usbh_asix_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    int ret = usbh_asix_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return -RT_ERROR;
+    } else {
+        return RT_EOK;
+    }
+}
+
+void usbh_asix_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(g_asix_dev.netif, buf, buflen);
+}
+
+void usbh_asix_run(struct usbh_asix *asix_class)
+{
+    memset(&g_asix_dev, 0, sizeof(struct eth_device));
+
+    g_asix_dev.parent.control = rt_usbh_asix_control;
+    g_asix_dev.eth_rx = NULL;
+    g_asix_dev.eth_tx = rt_usbh_asix_eth_tx;
+    g_asix_dev.parent.user_data = asix_class;
+
+    eth_device_init(&g_asix_dev, "u3");
+    eth_device_linkchange(&g_asix_dev, RT_TRUE);
+
+    usb_osal_thread_create("usbh_asix_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_asix_rx_thread, NULL);
+}
+
+void usbh_asix_stop(struct usbh_asix *asix_class)
+{
+    eth_device_deinit(&g_asix_dev);
+}
+#endif
+
+#ifdef CONFIG_USBHOST_PLATFORM_RTL8152
+#include "usbh_rtl8152.h"
+
+static struct eth_device g_rtl8152_dev;
+
+static rt_err_t rt_usbh_rtl8152_control(rt_device_t dev, int cmd, void *args)
+{
+    struct usbh_rtl8152 *rtl8152_class = (struct usbh_rtl8152 *)dev->user_data;
+
+    switch (cmd) {
+        case NIOCTL_GADDR:
+
+            /* get mac address */
+            if (args)
+                rt_memcpy(args, rtl8152_class->mac, 6);
+            else
+                return -RT_ERROR;
+
+            break;
+
+        default:
+            break;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_usbh_rtl8152_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    int ret = usbh_rtl8152_eth_output(p->payload, p->tot_len);
+    if (ret < 0) {
+        return -RT_ERROR;
+    } else {
+        return RT_EOK;
+    }
+}
+
+void usbh_rtl8152_eth_input(uint8_t *buf, uint32_t buflen)
+{
+    usbh_lwip_eth_input_common(g_rtl8152_dev.netif, buf, buflen);
+}
+
+void usbh_rtl8152_run(struct usbh_rtl8152 *rtl8152_class)
+{
+    memset(&g_rtl8152_dev, 0, sizeof(struct eth_device));
+
+    g_rtl8152_dev.parent.control = rt_usbh_rtl8152_control;
+    g_rtl8152_dev.eth_rx = NULL;
+    g_rtl8152_dev.eth_tx = rt_usbh_rtl8152_eth_tx;
+    g_rtl8152_dev.parent.user_data = rtl8152_class;
+
+    eth_device_init(&g_rtl8152_dev, "u4");
+    eth_device_linkchange(&g_rtl8152_dev, RT_TRUE);
+
+    usb_osal_thread_create("usbh_rtl8152_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rtl8152_rx_thread, NULL);
+}
+
+void usbh_rtl8152_stop(struct usbh_rtl8152 *rtl8152_class)
+{
+    eth_device_deinit(&g_rtl8152_dev);
+}
+#endif

+ 0 - 0
platform/threadx/.gitkeep


+ 0 - 43
third_party/rt-thread-5.0/usb_check.c

@@ -1,43 +0,0 @@
-#include "rtthread.h"
-
-#ifdef PKG_CHERRYUSB_HOST
-
-#ifndef RT_USING_TIMER_SOFT
-#error must enable RT_USING_TIMER_SOFT to support timer callback in thread
-#endif
-
-#if IDLE_THREAD_STACK_SIZE < 2048
-#error "IDLE_THREAD_STACK_SIZE must be greater than 2048"
-#endif
-
-#if RT_TIMER_THREAD_STACK_SIZE < 2048
-#error "RT_TIMER_THREAD_STACK_SIZE must be greater than 2048"
-#endif
-
-#ifdef RT_USING_LWIP
-
-#include "lwip/opt.h"
-
-#ifndef RT_USING_LWIP212
-#error must enable RT_USING_LWIP212
-#endif
-
-#ifndef LWIP_NO_RX_THREAD
-#error must enable LWIP_NO_RX_THREAD, we do not use rtthread eth rx thread
-#endif
-
-#if LWIP_TCPIP_CORE_LOCKING_INPUT !=1
-#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread
-#endif
-
-#if LWIP_TCPIP_CORE_LOCKING !=1
-#error must set LWIP_TCPIP_CORE_LOCKING to 1
-#endif
-
-#if PBUF_POOL_BUFSIZE < 1514
-#error PBUF_POOL_BUFSIZE must be larger than 1514
-#endif
-
-#endif
-
-#endif