From dd1f1d3ba80d979ef5c0153bf3897ccf45febeac Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Thu, 7 Sep 2023 12:43:30 +0800 Subject: [PATCH] Update hcd-ehci, dcd-dwc2 and examples. 1. Add some example Msh commands. 2. Fix device enumeration on EXT hub. 3. Re-file some templates. 4. Extend end-point number of dwc2 device driver. 5. Re-file rndis_host implementation includes a. rt_mutex_take in ISR b. 2rd pmsg is unaligned issue. c. destroy u0 ethernet resource after removing dongle. --- SConscript | 3 + class/hub/usbh_hub.c | 4 +- demo/cdc_acm_template.c | 4 +- demo/cdc_rndis_template.c | 49 +++--- demo/hid_keyboard_template.c | 2 +- demo/hid_mouse_template.c | 23 +-- demo/msc_ram_template.c | 6 +- port/dwc2/usb_dc_dwc2.c | 26 +++- port/dwc2/usb_dwc2_reg.h | 4 + port/ehci/usb_hc_ehci.c | 2 +- third_party/rt-thread-4.1.1/dfs/udisk.c | 7 +- third_party/rt-thread-4.1.1/msh_cmd.c | 84 +++++++++++ .../rt-thread-4.1.1/rndis_host/rndis_host.c | 139 ++++++++++-------- 13 files changed, 244 insertions(+), 109 deletions(-) create mode 100644 third_party/rt-thread-4.1.1/msh_cmd.c diff --git a/SConscript b/SConscript index 71b4cd22..d9594298 100644 --- a/SConscript +++ b/SConscript @@ -97,6 +97,7 @@ if GetDepend(['PKG_CHERRYUSB_HOST']): src += Glob('class/msc/usbh_msc.c') if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']): src += Glob('class/wireless/usbh_rndis.c') + src += Glob('third_party/rt-thread-4.1.1/rndis_host/rndis_host.c') if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']): src += Glob('port/dwc2/usb_hc_dwc2.c') @@ -119,6 +120,8 @@ if GetDepend(['PKG_CHERRYUSB_HOST']): src += Glob('class/vendor/cp201x/usbh_cp210x.c') src += Glob('third_party/rt-thread-4.1.1/dfs/drv_usbh_cp210x_rtt.c') +src += Glob('third_party/rt-thread-4.1.1/msh_cmd.c') + group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group') diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c index dd4ec5ed..6917bd2d 100644 --- a/class/hub/usbh_hub.c +++ b/class/hub/usbh_hub.c @@ -299,7 +299,9 @@ static void hub_int_complete_callback(void *arg, int nbytes) { struct usbh_hub *hub = (struct usbh_hub *)arg; - if (nbytes > 0) { + // >=0 can pass device enumeration on EXT hub. + if (nbytes >= 0) + { usbh_hub_thread_wakeup(hub); } } diff --git a/demo/cdc_acm_template.c b/demo/cdc_acm_template.c index 494330d0..a8933b81 100644 --- a/demo/cdc_acm_template.c +++ b/demo/cdc_acm_template.c @@ -171,8 +171,8 @@ struct usbd_endpoint cdc_in_ep = { .ep_cb = usbd_cdc_acm_bulk_in }; -struct usbd_interface intf0; -struct usbd_interface intf1; +static struct usbd_interface intf0; +static struct usbd_interface intf1; void cdc_acm_init(void) { diff --git a/demo/cdc_rndis_template.c b/demo/cdc_rndis_template.c index bebc9ccb..c41bca7f 100644 --- a/demo/cdc_rndis_template.c +++ b/demo/cdc_rndis_template.c @@ -102,12 +102,33 @@ static const uint8_t cdc_descriptor[] = { }; const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; +/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ +#define IP_ADDR0 (uint8_t)192 +#define IP_ADDR1 (uint8_t)168 +#define IP_ADDR2 (uint8_t)123 +#define IP_ADDR3 (uint8_t)100 + +/*NETMASK*/ +#define NETMASK_ADDR0 (uint8_t)255 +#define NETMASK_ADDR1 (uint8_t)255 +#define NETMASK_ADDR2 (uint8_t)255 +#define NETMASK_ADDR3 (uint8_t)0 + +/*Gateway Address*/ +#define GW_ADDR0 (uint8_t)192 +#define GW_ADDR1 (uint8_t)168 +#define GW_ADDR2 (uint8_t)123 +#define GW_ADDR3 (uint8_t)1 #ifdef RT_USING_LWIP #include #include #include +const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); +const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); +const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + struct eth_device rndis_dev; static rt_err_t rt_usbd_rndis_control(rt_device_t dev, int cmd, void *args) @@ -161,33 +182,15 @@ void rt_usbd_rndis_init(void) #include "lwip/netif.h" #include "lwip/pbuf.h" -/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ -#define IP_ADDR0 (uint8_t)192 -#define IP_ADDR1 (uint8_t)168 -#define IP_ADDR2 (uint8_t)123 -#define IP_ADDR3 (uint8_t)100 - -/*NETMASK*/ -#define NETMASK_ADDR0 (uint8_t)255 -#define NETMASK_ADDR1 (uint8_t)255 -#define NETMASK_ADDR2 (uint8_t)255 -#define NETMASK_ADDR3 (uint8_t)0 - -/*Gateway Address*/ -#define GW_ADDR0 (uint8_t)192 -#define GW_ADDR1 (uint8_t)168 -#define GW_ADDR2 (uint8_t)123 -#define GW_ADDR3 (uint8_t)1 - -static struct netif rndis_netif; //network interface - const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); +static struct netif rndis_netif; //network interface + /* Network interface name */ -#define IFNAME0 'E' -#define IFNAME1 'X' +#define IFNAME0 'E' +#define IFNAME1 'X' err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { @@ -203,7 +206,7 @@ err_t linkoutput_fn(struct netif *netif, struct pbuf *p) err_t rndisif_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; diff --git a/demo/hid_keyboard_template.c b/demo/hid_keyboard_template.c index cb9d593c..214c5978 100644 --- a/demo/hid_keyboard_template.c +++ b/demo/hid_keyboard_template.c @@ -226,7 +226,7 @@ void hid_keyboard_init(void) USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64]; -void hid_keyboard_test(uint8_t busid) +void hid_keyboard_test(void) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/demo/hid_mouse_template.c b/demo/hid_mouse_template.c index 81aff89d..38be541c 100644 --- a/demo/hid_mouse_template.c +++ b/demo/hid_mouse_template.c @@ -256,15 +256,20 @@ void hid_mouse_init(void) */ void hid_mouse_test(void) { - /*!< move mouse pointer */ - mouse_cfg.x += 10; - mouse_cfg.y = 0; + int counter = 0; + while (counter < 1000) { + /*!< move mouse pointer */ + mouse_cfg.x += 40; + mouse_cfg.y += 0; - int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } - hid_state = HID_STATE_BUSY; - while (hid_state == HID_STATE_BUSY) { + int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4); + if (ret < 0) { + return; + } + hid_state = HID_STATE_BUSY; + while (hid_state == HID_STATE_BUSY) { + } + + counter++; } } diff --git a/demo/msc_ram_template.c b/demo/msc_ram_template.c index 84cd7bea..8092756a 100644 --- a/demo/msc_ram_template.c +++ b/demo/msc_ram_template.c @@ -132,19 +132,19 @@ BLOCK_TYPE mass_block[BLOCK_COUNT]; void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { - *block_num = 1000; //Pretend having so many buffer,not has actually. + *block_num = BLOCK_COUNT; //Pretend having so many buffer,not has actually. *block_size = BLOCK_SIZE; } int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length) { - if (sector < 10) + if (sector < BLOCK_COUNT) memcpy(buffer, mass_block[sector].BlockSpace, length); return 0; } int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length) { - if (sector < 10) + if (sector < BLOCK_COUNT) memcpy(mass_block[sector].BlockSpace, buffer, length); return 0; } diff --git a/port/dwc2/usb_dc_dwc2.c b/port/dwc2/usb_dc_dwc2.c index 508071a7..544d6e5c 100644 --- a/port/dwc2/usb_dc_dwc2.c +++ b/port/dwc2/usb_dc_dwc2.c @@ -325,14 +325,17 @@ static void dwc2_set_turnaroundtime(uint32_t hclk, uint8_t speed) UsbTrd = USBD_DEFAULT_TRDT_VALUE; } + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_TOCAL; + USB_OTG_GLB->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - USB_OTG_GLB->GUSBCFG |= (uint32_t)((UsbTrd << 10) & USB_OTG_GUSBCFG_TRDT); + USB_OTG_GLB->GUSBCFG |= (uint32_t)((UsbTrd << USB_OTG_GUSBCFG_TRDT_Pos) & USB_OTG_GUSBCFG_TRDT); } static void dwc2_set_txfifo(uint8_t fifo, uint16_t size) { uint8_t i; uint32_t Tx_Offset; + uint32_t Tx_Size; /* TXn min size = 16 words. (n : Transmit FIFO index) When a TxFIFO is not used, the Configuration should be as follows: @@ -348,6 +351,7 @@ static void dwc2_set_txfifo(uint8_t fifo, uint16_t size) if (fifo == 0U) { USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset; + Tx_Size = USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ; } else { Tx_Offset += (USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ) >> 16; for (i = 0U; i < (fifo - 1U); i++) { @@ -356,7 +360,11 @@ static void dwc2_set_txfifo(uint8_t fifo, uint16_t size) /* Multiply Tx_Size by 2 to get higher performance */ USB_OTG_GLB->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset; + + Tx_Size = USB_OTG_GLB->DIEPTXF[fifo - 1U]; } + + USB_LOG_INFO("fifo-%02d size:%04d %08x\n", fifo, size, Tx_Size); } static uint8_t dwc2_get_devspeed(void) @@ -665,8 +673,9 @@ int usb_dc_init(void) } } - USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_2; - USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN; + USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DESCDMA; + USB_OTG_GLB->GAHBCFG |= (USB_OTG_GAHBCFG_DMAEN | USB_OTG_GAHBCFG_HBSTLEN_2); + #else USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; #endif @@ -688,6 +697,15 @@ int usb_dc_init(void) #endif #if USB_NUM_BIDIR_ENDPOINTS > 5 dwc2_set_txfifo(5, CONFIG_USB_DWC2_TX5_FIFO_SIZE / 4); +#endif +#if USB_NUM_BIDIR_ENDPOINTS > 6 + dwc2_set_txfifo(6, CONFIG_USB_DWC2_TX6_FIFO_SIZE / 4); +#endif +#if USB_NUM_BIDIR_ENDPOINTS > 7 + dwc2_set_txfifo(7, CONFIG_USB_DWC2_TX7_FIFO_SIZE / 4); +#endif +#if USB_NUM_BIDIR_ENDPOINTS > 8 + dwc2_set_txfifo(8, CONFIG_USB_DWC2_TX8_FIFO_SIZE / 4); #endif USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT; USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_SDIS; @@ -821,7 +839,7 @@ int usbd_ep_close(const uint8_t ep) /* Clear and unmask endpoint disabled interrupt */ USB_OTG_INEP(ep_idx)->DIEPINT |= USB_OTG_DIEPINT_EPDISD; } - + USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07))); USB_OTG_DEV->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07))); USB_OTG_INEP(ep_idx)->DIEPCTL = 0; diff --git a/port/dwc2/usb_dwc2_reg.h b/port/dwc2/usb_dwc2_reg.h index e911b504..173861d9 100644 --- a/port/dwc2/usb_dwc2_reg.h +++ b/port/dwc2/usb_dwc2_reg.h @@ -241,6 +241,10 @@ typedef struct #define USB_OTG_DCFG_ERRATIM_Msk (0x1UL << USB_OTG_DCFG_ERRATIM_Pos) /*!< 0x00008000 */ #define USB_OTG_DCFG_ERRATIM USB_OTG_DCFG_ERRATIM_Msk /*!< Erratic error interrupt mask */ +#define USB_OTG_DCFG_DESCDMA_Pos (23U) +#define USB_OTG_DCFG_DESCDMA_Msk (0x1UL << USB_OTG_DCFG_DESCDMA_Pos) +#define USB_OTG_DCFG_DESCDMA USB_OTG_DCFG_DESCDMA_Msk + #define USB_OTG_DCFG_PERSCHIVL_Pos (24U) #define USB_OTG_DCFG_PERSCHIVL_Msk (0x3UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x03000000 */ #define USB_OTG_DCFG_PERSCHIVL USB_OTG_DCFG_PERSCHIVL_Msk /*!< Periodic scheduling interval */ diff --git a/port/ehci/usb_hc_ehci.c b/port/ehci/usb_hc_ehci.c index f53bd944..145320f9 100644 --- a/port/ehci/usb_hc_ehci.c +++ b/port/ehci/usb_hc_ehci.c @@ -1151,7 +1151,7 @@ int usbh_submit_urb(struct usbh_urb *urb) pipe = urb->pipe; - if (!pipe->inuse || !(EHCI_HCOR->portsc[0] & EHCI_PORTSC_CCS) || !pipe->hport->connected) { + if (!pipe->inuse /*|| !(EHCI_HCOR->portsc[pipe->hport->port-1] & EHCI_PORTSC_CCS)*/ || !pipe->hport->connected) { return -ENODEV; } diff --git a/third_party/rt-thread-4.1.1/dfs/udisk.c b/third_party/rt-thread-4.1.1/dfs/udisk.c index 64ff590f..7603bc38 100644 --- a/third_party/rt-thread-4.1.1/dfs/udisk.c +++ b/third_party/rt-thread-4.1.1/dfs/udisk.c @@ -15,6 +15,7 @@ #include "usbh_msc.h" #define MAX_PARTITION_COUNT 5 +#define CONFIG_DFS_MOUNT_POINT "/" struct ustor_data { struct dfs_partition part; @@ -251,7 +252,7 @@ rt_err_t rt_udisk_run(struct usbh_msc *msc_class) stor_r->dev_cnt++; - if (dfs_mount(stor_r->dev[i].parent.name, "/", "elm", 0, 0) == 0) { + if (dfs_mount(stor_r->dev[i].parent.name, CONFIG_DFS_MOUNT_POINT, "elm", 0, 0) == 0) { rt_kprintf("udisk part %d mount successfully\n", i); } else { rt_kprintf("udisk part %d mount failed\n", i); @@ -285,7 +286,7 @@ rt_err_t rt_udisk_run(struct usbh_msc *msc_class) rt_device_register(&stor_r->dev[0], dname, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); stor_r->dev_cnt++; - if (dfs_mount(stor_r->dev[0].parent.name, "/", "elm", 0, 0) == 0) { + if (dfs_mount(stor_r->dev[0].parent.name, CONFIG_DFS_MOUNT_POINT, "elm", 0, 0) == 0) { rt_kprintf("Mount FAT on Udisk successful.\n"); } else { rt_kprintf("Mount FAT on Udisk failed.\n"); @@ -325,7 +326,7 @@ rt_err_t rt_udisk_stop(struct usbh_msc *msc_class) data = (struct ustor_data *)dev->user_data; /* unmount filesystem */ - dfs_unmount("/"); + dfs_unmount(CONFIG_DFS_MOUNT_POINT); /* delete semaphore */ rt_sem_delete(data->part.lock); diff --git a/third_party/rt-thread-4.1.1/msh_cmd.c b/third_party/rt-thread-4.1.1/msh_cmd.c new file mode 100644 index 00000000..4070ad93 --- /dev/null +++ b/third_party/rt-thread-4.1.1/msh_cmd.c @@ -0,0 +1,84 @@ +/**************************************************************************/ /** +* +* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2023-8-9 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(PKG_USING_CHERRYUSB) + +#if defined(PKG_CHERRYUSB_DEVICE_CDC_TEMPLATE) +void cdc_acm_init(void); +MSH_CMD_EXPORT(cdc_acm_init, start cdc_acm_init); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_HID_MOUSE_TEMPLATE) +void hid_mouse_init(void); +void hid_mouse_test(void); + +MSH_CMD_EXPORT(hid_mouse_init, start hid_mouse_init); +MSH_CMD_EXPORT(hid_mouse_test, start hid_mouse_test); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_HID_KEYBOARD_TEMPLATE) +void hid_keyboard_init(void); +void hid_keyboard_test(void); + +MSH_CMD_EXPORT(hid_keyboard_init, start hid_keyboard_init); +MSH_CMD_EXPORT(hid_keyboard_test, start hid_keyboard_test); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE) +void msc_ram_init(void); +MSH_CMD_EXPORT(msc_ram_init, start msc_ram_init); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_RNDIS_TEMPLATE) +void cdc_rndis_init(void); +MSH_CMD_EXPORT(cdc_rndis_init, start cdc_rndis_init); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_VIDEO_TEMPLATE) +void video_init(void); +void video_test(void); + +MSH_CMD_EXPORT(video_init, start video_init); +MSH_CMD_EXPORT(video_test, start video_test); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE) +void audio_v1_init(void); +void audio_v1_test(void); + +MSH_CMD_EXPORT(audio_v1_init, start audio_v1_init); +MSH_CMD_EXPORT(audio_v1_test, start audio_v1_test); +#endif + +#if defined(PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE) +void audio_v2_init(void); +void audio_v2_test(void); + +MSH_CMD_EXPORT(audio_v2_init, start audio_v2_init); +MSH_CMD_EXPORT(audio_v2_test, start audio_v2_test); +#endif + +#if defined(PKG_CHERRYUSB_HOST) +void usbh_class_test(void); +MSH_CMD_EXPORT(usbh_class_test, start usbh_class_test); + +int lsusb(int argc, char **argv); +MSH_CMD_EXPORT(lsusb, start lsusb); + +int usbh_initialize(void); +//INIT_APP_EXPORT(usbh_initialize); +MSH_CMD_EXPORT(usbh_initialize, start usbh_initialize); +#endif + +#endif diff --git a/third_party/rt-thread-4.1.1/rndis_host/rndis_host.c b/third_party/rt-thread-4.1.1/rndis_host/rndis_host.c index a1bfb35c..e8c4cfbf 100644 --- a/third_party/rt-thread-4.1.1/rndis_host/rndis_host.c +++ b/third_party/rt-thread-4.1.1/rndis_host/rndis_host.c @@ -8,12 +8,13 @@ #include /* define the rdnis device state*/ -#define RNDIS_BUS_UNINITIALIZED 0 -#define RNDIS_BUS_INITIALIZED 1 -#define RNDIS_INITIALIZED 2 -#define RNDIS_DATA_INITIALIZED 3 +#define RNDIS_BUS_UNINITIALIZED 0 +#define RNDIS_BUS_INITIALIZED 1 +#define RNDIS_INITIALIZED 2 +#define RNDIS_DATA_INITIALIZED 3 -#define USB_ETH_MTU 1500 + 14 +#define USB_ETH_MTU (1500 + 14) +#define RNDIS_THREAD_STACK_SIZE (4096) #define RNDIS_NET_DEV_NAME "u0" #define MAX_ADDR_LEN 6 @@ -27,8 +28,7 @@ struct usbh_user_rndis { void *user_data; }; -struct rndis_packet_msg -{ +struct rndis_packet_msg { rt_uint32_t MessageType; rt_uint32_t MessageLength; rt_uint32_t DataOffset; @@ -65,12 +65,12 @@ struct rt_rndis_eth { rt_uint32_t rndis_state; rt_thread_t rndis_recv; - rt_timer_t keepalive_timer; + rt_thread_t keepalive_timer; }; typedef struct rt_rndis_eth *rt_rndis_eth_t; -struct usbh_user_rndis *g_user_rndis; -USB_NOCACHE_RAM_SECTION struct rt_rndis_eth usbh_rndis_eth_device; +struct usbh_user_rndis *g_user_rndis = RT_NULL; +USB_NOCACHE_RAM_SECTION struct rt_rndis_eth usbh_rndis_eth_device = { 0 }; void hex_data_print(const char *name, const rt_uint8_t *buf, rt_size_t size) { @@ -139,7 +139,7 @@ static rt_err_t rt_rndis_msg_data_send(struct usbh_user_rndis *rndis_class, rt_u ret = usbh_rndis_bulk_out_transfer(rndis_class->rndis_class, buffer, nbytes, 5000); rt_mutex_release(usbh_rndis_eth_device.rndis_mutex); if (ret != nbytes) { - rt_kprintf("rndis msg send fial\r\n"); + rt_kprintf("rndis msg send fail(%d %d)\r\n", ret, nbytes); } return ret; } @@ -187,55 +187,62 @@ static rt_err_t rt_rndis_keepalive_msg(struct usbh_user_rndis *rndis_class) */ void rt_usbh_rndis_data_recv_entry(void *pdata) { - int ret = 0; struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata; - rt_rndis_eth_t device = RT_NULL; - device = (rt_rndis_eth_t)rndis_class->user_data; - err_t err; - struct pbuf *p; - rndis_data_packet_t *pmsg; - int pmg_offset; - int payload_offset; + rt_rndis_eth_t device = (rt_rndis_eth_t)rndis_class->user_data; + rndis_data_packet_t sRndisDataPkt; - if ((pdata == RT_NULL) || (rndis_class == RT_NULL) || - (device == RT_NULL)) { - return; - } - - device->rx_buf_ptr = device->rx_buffer; + //device->rx_buf_ptr = device->rx_buffer; while (1) { - pmg_offset = 0; - payload_offset = 0; + int ret = 0; + int pmg_offset = 0; + int payload_offset = 0; ret = usbh_rndis_bulk_in_transfer(rndis_class->rndis_class, device->rx_buf_ptr, RNDIS_ETH_BUFFER_LEN, RT_WAITING_FOREVER); if (ret <= 0) { rt_thread_mdelay(1); continue; } + while (ret > 0) { - pmsg = (rndis_data_packet_t *)(device->rx_buf_ptr + pmg_offset); + rndis_data_packet_t *pmsg = (rndis_data_packet_t *)(device->rx_buf_ptr + pmg_offset); + if (pmg_offset & 0x3) { + /* Not word-aligned case */ + //rt_kprintf("pmsg@%08x Not word-aligned case\n", pmsg); + + rt_memcpy(&sRndisDataPkt, pmsg, sizeof(rndis_data_packet_t)); + pmsg = &sRndisDataPkt; + } + if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) { /* allocate buffer */ - p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL); + struct pbuf *p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL); if (p != NULL) { struct pbuf *q; for (q = p; q != NULL; q = q->next) { - /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ - memcpy(q->payload, ((uint8_t *)(&pmsg->DataOffset) + pmsg->DataOffset + payload_offset), q->len); + void *src = (void *)(device->rx_buf_ptr + pmg_offset + (2 * sizeof(uint32_t)) + pmsg->DataOffset + payload_offset); + + rt_memcpy(q->payload, + src, + q->len); + payload_offset += q->len; } /* entry point to the LwIP stack */ /* notify to upper layer */ - if(device->parent.netif->input(p, device->parent.netif)!= ERR_OK ) - { + + if (device->parent.netif->input(p, device->parent.netif) != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n")); pbuf_free(p); p = NULL; } - pmg_offset += pmsg->MessageLength; - ret -= pmsg->MessageLength; } + } else { + rt_kprintf("pmsg->MessageType=%d\n", pmsg->MessageType); + break; } + + pmg_offset += pmsg->MessageLength; + ret -= pmsg->MessageLength; } } } @@ -243,15 +250,14 @@ void rt_usbh_rndis_data_recv_entry(void *pdata) void rt_rndis_dev_keepalive_timeout(void *pdata) { struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata; - static rt_uint32_t keepalive_error = 0; - if (rndis_class == RT_NULL) { - return; + while (1) { + rt_thread_mdelay(RT_TICK_PER_SECOND * RNDIS_DEV_KEEPALIVE_TIMEOUT / 1000); + + rt_mutex_take(usbh_rndis_eth_device.rndis_mutex, RT_WAITING_FOREVER); + rt_rndis_keepalive_msg(rndis_class); + rt_mutex_release(usbh_rndis_eth_device.rndis_mutex); } - - rt_mutex_take(usbh_rndis_eth_device.rndis_mutex, RT_WAITING_FOREVER); - rt_rndis_keepalive_msg(rndis_class); - rt_mutex_release(usbh_rndis_eth_device.rndis_mutex); } /** @@ -274,22 +280,24 @@ rt_err_t rt_rndis_run(struct usbh_user_rndis *rndis_class) to reset the device, or to tear down the data and control channels*/ usbh_rndis_eth_device.rndis_state = RNDIS_INITIALIZED; - usbh_rndis_eth_device.keepalive_timer = rt_timer_create("keeplive", rt_rndis_dev_keepalive_timeout, - rndis_class, - RT_TICK_PER_SECOND * RNDIS_DEV_KEEPALIVE_TIMEOUT / 1000, - RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); + usbh_rndis_eth_device.keepalive_timer = rt_thread_create("keeplive", + (void (*)(void *parameter))rt_rndis_dev_keepalive_timeout, + rndis_class, + RNDIS_THREAD_STACK_SIZE, + 5, + 20); if (usbh_rndis_eth_device.keepalive_timer == RT_NULL) { ret = -RT_ENOMEM; goto __exit; } - rt_timer_start(usbh_rndis_eth_device.keepalive_timer); + rndis_class->user_data = (struct rt_device *)&usbh_rndis_eth_device; - usbh_rndis_eth_device.rndis_recv = rt_thread_create("rndis", + usbh_rndis_eth_device.rndis_recv = rt_thread_create("rndis_recv", (void (*)(void *parameter))rt_usbh_rndis_data_recv_entry, rndis_class, - 1024 + 512, + RNDIS_THREAD_STACK_SIZE, 5, 20); @@ -301,8 +309,6 @@ rt_err_t rt_rndis_run(struct usbh_user_rndis *rndis_class) /*the LINK SPEED is 100Mbps*/ usbh_rndis_eth_device.rndis_speed = rndis_class->rndis_class->link_speed; - eth_device_linkchange(&usbh_rndis_eth_device.parent, rndis_class->rndis_class->link_status); - for (j = 0; j < MAX_ADDR_LEN; j++) { usbh_rndis_eth_device.dev_addr[j] = rndis_class->rndis_class->mac[j]; } @@ -316,6 +322,8 @@ __exit: it can exchange REMOTE_NDIS_PACKET_MSG messages for network data transfer with the device on the data channel*/ usbh_rndis_eth_device.rndis_state = RNDIS_DATA_INITIALIZED; rt_thread_startup(usbh_rndis_eth_device.rndis_recv); + rt_thread_startup(usbh_rndis_eth_device.keepalive_timer); + RNDIS_DEV_PRINTF("rndis dev start!\n"); usbh_rndis_eth_device.rndis_class = rndis_class; @@ -332,8 +340,10 @@ void usbh_rndis_run(struct usbh_rndis *rndis_class) RT_ASSERT(g_user_rndis != RT_NULL); g_user_rndis->rndis_class = rndis_class; if (rt_rndis_run(g_user_rndis) == RT_EOK) { + /* Allocate ethernet resource. */ eth_device_init(&usbh_rndis_eth_device.parent, RNDIS_NET_DEV_NAME); - eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE); + //eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE); + eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_TRUE); } } @@ -348,16 +358,17 @@ rt_err_t rt_rndis_stop(struct usbh_user_rndis *rndis_class) info->rndis_recv = RT_NULL; } eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE); + + /* Destroy ethernet resource. */ + eth_device_deinit(&usbh_rndis_eth_device.parent); + usbh_rndis_eth_device.rndis_class = RT_NULL; /*disable the other thread etx call the rt_timer_start(rndis->keepalive_timer) cause the RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer)*/ - rt_mutex_take(usbh_rndis_eth_device.rndis_mutex, RT_WAITING_FOREVER); if (info->keepalive_timer) { - rt_timer_stop(info->keepalive_timer); - rt_timer_delete(info->keepalive_timer); + rt_thread_delete(info->keepalive_timer); info->keepalive_timer = RT_NULL; } - rt_mutex_release(usbh_rndis_eth_device.rndis_mutex); info->rndis_state = RNDIS_BUS_UNINITIALIZED; @@ -370,6 +381,7 @@ void usbh_rndis_stop(struct usbh_rndis *rndis_class) RT_ASSERT(g_user_rndis != RT_NULL); rt_rndis_stop(g_user_rndis); usb_free(g_user_rndis); + g_user_rndis = RT_NULL; } /** * This function rndis eth device. @@ -428,7 +440,6 @@ static rt_err_t rt_rndis_eth_control(rt_device_t dev, int cmd, void *args) /* ethernet device interface */ - /* transmit packet. */ extern int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, @@ -455,7 +466,7 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf *p) break; } RNDIS_DEV_PRINTF("linkdown, drop pkg\r\n"); - while(recount--) { + while (recount--) { ret = usbh_rndis_query_msg_transfer(device->rndis_class->rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len); if (ret < 0) { return -EBUSY; @@ -507,6 +518,7 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf *p) } if (device->frame_debug == RT_TRUE) { + rt_kprintf("msg @ %08x\n", msg); hex_data_print("rndis eth tx", (rt_uint8_t *)msg, msg->MessageLength); } result = rt_rndis_msg_data_send(device->rndis_class, (rt_uint8_t *)msg, msg->MessageLength); @@ -527,13 +539,16 @@ const static struct rt_device_ops rndis_device_ops = { #endif #endif -__WEAK void lowlevel_usb_init(void) +__WEAK void +lowlevel_usb_init(void) { - } int usbh_rndis_eth_device_init(void) { + /* Initialize all data member in usbh_rndis_eth_device */ + rt_memset(&usbh_rndis_eth_device, 0, sizeof(struct rt_rndis_eth)); + /* OUI 00-00-00, only for test. */ usbh_rndis_eth_device.dev_addr[0] = 0xFF; usbh_rndis_eth_device.dev_addr[1] = 0xFF; @@ -573,9 +588,9 @@ int usbh_rndis_eth_device_init(void) lowlevel_usb_init(); - return RT_EOK; + return 0; } -INIT_APP_EXPORT(usbh_rndis_eth_device_init); +INIT_DEVICE_EXPORT(usbh_rndis_eth_device_init); /********************************************************************************************************* ** Function name eth_rndis_frame_debug()