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.
This commit is contained in:
Wayne Lin
2023-09-07 12:43:30 +08:00
committed by sakumisu
parent bc1e7c4bd5
commit dd1f1d3ba8
13 changed files with 244 additions and 109 deletions

View File

@@ -97,6 +97,7 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
src += Glob('class/msc/usbh_msc.c') src += Glob('class/msc/usbh_msc.c')
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']): if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
src += Glob('class/wireless/usbh_rndis.c') 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']): if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
src += Glob('port/dwc2/usb_hc_dwc2.c') 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('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/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) group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group') Return('group')

View File

@@ -299,7 +299,9 @@ static void hub_int_complete_callback(void *arg, int nbytes)
{ {
struct usbh_hub *hub = (struct usbh_hub *)arg; 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); usbh_hub_thread_wakeup(hub);
} }
} }

View File

@@ -171,8 +171,8 @@ struct usbd_endpoint cdc_in_ep = {
.ep_cb = usbd_cdc_acm_bulk_in .ep_cb = usbd_cdc_acm_bulk_in
}; };
struct usbd_interface intf0; static struct usbd_interface intf0;
struct usbd_interface intf1; static struct usbd_interface intf1;
void cdc_acm_init(void) void cdc_acm_init(void)
{ {

View File

@@ -102,12 +102,33 @@ static const uint8_t cdc_descriptor[] = {
}; };
const uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; 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 #ifdef RT_USING_LWIP
#include <rtthread.h> #include <rtthread.h>
#include <rtdevice.h> #include <rtdevice.h>
#include <netif/ethernetif.h> #include <netif/ethernetif.h>
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; struct eth_device rndis_dev;
static rt_err_t rt_usbd_rndis_control(rt_device_t dev, int cmd, void *args) 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/netif.h"
#include "lwip/pbuf.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 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 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); 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 */ /* Network interface name */
#define IFNAME0 'E' #define IFNAME0 'E'
#define IFNAME1 'X' #define IFNAME1 'X'
err_t linkoutput_fn(struct netif *netif, struct pbuf *p) err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
{ {

View File

@@ -226,7 +226,7 @@ void hid_keyboard_init(void)
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64]; 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 }; const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };

View File

@@ -256,15 +256,20 @@ void hid_mouse_init(void)
*/ */
void hid_mouse_test(void) void hid_mouse_test(void)
{ {
/*!< move mouse pointer */ int counter = 0;
mouse_cfg.x += 10; while (counter < 1000) {
mouse_cfg.y = 0; /*!< 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); int ret = usbd_ep_start_write(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
if (ret < 0) { if (ret < 0) {
return; return;
} }
hid_state = HID_STATE_BUSY; hid_state = HID_STATE_BUSY;
while (hid_state == HID_STATE_BUSY) { while (hid_state == HID_STATE_BUSY) {
}
counter++;
} }
} }

View File

@@ -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) 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; *block_size = BLOCK_SIZE;
} }
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length) 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); memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0; return 0;
} }
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length) 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); memcpy(mass_block[sector].BlockSpace, buffer, length);
return 0; return 0;
} }

View File

@@ -325,14 +325,17 @@ static void dwc2_set_turnaroundtime(uint32_t hclk, uint8_t speed)
UsbTrd = USBD_DEFAULT_TRDT_VALUE; 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 &= ~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) static void dwc2_set_txfifo(uint8_t fifo, uint16_t size)
{ {
uint8_t i; uint8_t i;
uint32_t Tx_Offset; uint32_t Tx_Offset;
uint32_t Tx_Size;
/* TXn min size = 16 words. (n : Transmit FIFO index) /* TXn min size = 16 words. (n : Transmit FIFO index)
When a TxFIFO is not used, the Configuration should be as follows: 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) { if (fifo == 0U) {
USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset; USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
Tx_Size = USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ;
} else { } else {
Tx_Offset += (USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ) >> 16; Tx_Offset += (USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ) >> 16;
for (i = 0U; i < (fifo - 1U); i++) { 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 */ /* Multiply Tx_Size by 2 to get higher performance */
USB_OTG_GLB->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset; 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) 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_DEV->DCFG &= ~USB_OTG_DCFG_DESCDMA;
USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN; USB_OTG_GLB->GAHBCFG |= (USB_OTG_GAHBCFG_DMAEN | USB_OTG_GAHBCFG_HBSTLEN_2);
#else #else
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
#endif #endif
@@ -688,6 +697,15 @@ int usb_dc_init(void)
#endif #endif
#if USB_NUM_BIDIR_ENDPOINTS > 5 #if USB_NUM_BIDIR_ENDPOINTS > 5
dwc2_set_txfifo(5, CONFIG_USB_DWC2_TX5_FIFO_SIZE / 4); 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 #endif
USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT; USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_SDIS; USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_SDIS;

View File

@@ -241,6 +241,10 @@ typedef struct
#define USB_OTG_DCFG_ERRATIM_Msk (0x1UL << USB_OTG_DCFG_ERRATIM_Pos) /*!< 0x00008000 */ #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_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_Pos (24U)
#define USB_OTG_DCFG_PERSCHIVL_Msk (0x3UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x03000000 */ #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 */ #define USB_OTG_DCFG_PERSCHIVL USB_OTG_DCFG_PERSCHIVL_Msk /*!< Periodic scheduling interval */

View File

@@ -1151,7 +1151,7 @@ int usbh_submit_urb(struct usbh_urb *urb)
pipe = urb->pipe; 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; return -ENODEV;
} }

View File

@@ -15,6 +15,7 @@
#include "usbh_msc.h" #include "usbh_msc.h"
#define MAX_PARTITION_COUNT 5 #define MAX_PARTITION_COUNT 5
#define CONFIG_DFS_MOUNT_POINT "/"
struct ustor_data { struct ustor_data {
struct dfs_partition part; struct dfs_partition part;
@@ -251,7 +252,7 @@ rt_err_t rt_udisk_run(struct usbh_msc *msc_class)
stor_r->dev_cnt++; 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); rt_kprintf("udisk part %d mount successfully\n", i);
} else { } else {
rt_kprintf("udisk part %d mount failed\n", i); 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); rt_device_register(&stor_r->dev[0], dname, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
stor_r->dev_cnt++; 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"); rt_kprintf("Mount FAT on Udisk successful.\n");
} else { } else {
rt_kprintf("Mount FAT on Udisk failed.\n"); 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; data = (struct ustor_data *)dev->user_data;
/* unmount filesystem */ /* unmount filesystem */
dfs_unmount("/"); dfs_unmount(CONFIG_DFS_MOUNT_POINT);
/* delete semaphore */ /* delete semaphore */
rt_sem_delete(data->part.lock); rt_sem_delete(data->part.lock);

84
third_party/rt-thread-4.1.1/msh_cmd.c vendored Normal file
View File

@@ -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 <rtthread.h>
#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

View File

@@ -8,12 +8,13 @@
#include <netdev.h> #include <netdev.h>
/* define the rdnis device state*/ /* define the rdnis device state*/
#define RNDIS_BUS_UNINITIALIZED 0 #define RNDIS_BUS_UNINITIALIZED 0
#define RNDIS_BUS_INITIALIZED 1 #define RNDIS_BUS_INITIALIZED 1
#define RNDIS_INITIALIZED 2 #define RNDIS_INITIALIZED 2
#define RNDIS_DATA_INITIALIZED 3 #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 RNDIS_NET_DEV_NAME "u0"
#define MAX_ADDR_LEN 6 #define MAX_ADDR_LEN 6
@@ -27,8 +28,7 @@ struct usbh_user_rndis {
void *user_data; void *user_data;
}; };
struct rndis_packet_msg struct rndis_packet_msg {
{
rt_uint32_t MessageType; rt_uint32_t MessageType;
rt_uint32_t MessageLength; rt_uint32_t MessageLength;
rt_uint32_t DataOffset; rt_uint32_t DataOffset;
@@ -65,12 +65,12 @@ struct rt_rndis_eth {
rt_uint32_t rndis_state; rt_uint32_t rndis_state;
rt_thread_t rndis_recv; rt_thread_t rndis_recv;
rt_timer_t keepalive_timer; rt_thread_t keepalive_timer;
}; };
typedef struct rt_rndis_eth *rt_rndis_eth_t; typedef struct rt_rndis_eth *rt_rndis_eth_t;
struct usbh_user_rndis *g_user_rndis; struct usbh_user_rndis *g_user_rndis = RT_NULL;
USB_NOCACHE_RAM_SECTION struct rt_rndis_eth usbh_rndis_eth_device; 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) 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); ret = usbh_rndis_bulk_out_transfer(rndis_class->rndis_class, buffer, nbytes, 5000);
rt_mutex_release(usbh_rndis_eth_device.rndis_mutex); rt_mutex_release(usbh_rndis_eth_device.rndis_mutex);
if (ret != nbytes) { 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; 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) void rt_usbh_rndis_data_recv_entry(void *pdata)
{ {
int ret = 0;
struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata; struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata;
rt_rndis_eth_t device = RT_NULL; rt_rndis_eth_t device = (rt_rndis_eth_t)rndis_class->user_data;
device = (rt_rndis_eth_t)rndis_class->user_data; rndis_data_packet_t sRndisDataPkt;
err_t err;
struct pbuf *p;
rndis_data_packet_t *pmsg;
int pmg_offset;
int payload_offset;
if ((pdata == RT_NULL) || (rndis_class == RT_NULL) || //device->rx_buf_ptr = device->rx_buffer;
(device == RT_NULL)) {
return;
}
device->rx_buf_ptr = device->rx_buffer;
while (1) { while (1) {
pmg_offset = 0; int ret = 0;
payload_offset = 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); ret = usbh_rndis_bulk_in_transfer(rndis_class->rndis_class, device->rx_buf_ptr, RNDIS_ETH_BUFFER_LEN, RT_WAITING_FOREVER);
if (ret <= 0) { if (ret <= 0) {
rt_thread_mdelay(1); rt_thread_mdelay(1);
continue; continue;
} }
while (ret > 0) { 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) { if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
/* allocate buffer */ /* 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) { if (p != NULL) {
struct pbuf *q; struct pbuf *q;
for (q = p; q != NULL; q = q->next) { for (q = p; q != NULL; q = q->next) {
/* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ void *src = (void *)(device->rx_buf_ptr + pmg_offset + (2 * sizeof(uint32_t)) + pmsg->DataOffset + payload_offset);
memcpy(q->payload, ((uint8_t *)(&pmsg->DataOffset) + pmsg->DataOffset + payload_offset), q->len);
rt_memcpy(q->payload,
src,
q->len);
payload_offset += q->len; payload_offset += q->len;
} }
/* entry point to the LwIP stack */ /* entry point to the LwIP stack */
/* notify to upper layer */ /* 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")); LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n"));
pbuf_free(p); pbuf_free(p);
p = NULL; 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) void rt_rndis_dev_keepalive_timeout(void *pdata)
{ {
struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata; struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata;
static rt_uint32_t keepalive_error = 0;
if (rndis_class == RT_NULL) { while (1) {
return; 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*/ 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.rndis_state = RNDIS_INITIALIZED;
usbh_rndis_eth_device.keepalive_timer = rt_timer_create("keeplive", rt_rndis_dev_keepalive_timeout, usbh_rndis_eth_device.keepalive_timer = rt_thread_create("keeplive",
rndis_class, (void (*)(void *parameter))rt_rndis_dev_keepalive_timeout,
RT_TICK_PER_SECOND * RNDIS_DEV_KEEPALIVE_TIMEOUT / 1000, rndis_class,
RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); RNDIS_THREAD_STACK_SIZE,
5,
20);
if (usbh_rndis_eth_device.keepalive_timer == RT_NULL) { if (usbh_rndis_eth_device.keepalive_timer == RT_NULL) {
ret = -RT_ENOMEM; ret = -RT_ENOMEM;
goto __exit; goto __exit;
} }
rt_timer_start(usbh_rndis_eth_device.keepalive_timer);
rndis_class->user_data = (struct rt_device *)&usbh_rndis_eth_device; 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, (void (*)(void *parameter))rt_usbh_rndis_data_recv_entry,
rndis_class, rndis_class,
1024 + 512, RNDIS_THREAD_STACK_SIZE,
5, 5,
20); 20);
@@ -301,8 +309,6 @@ rt_err_t rt_rndis_run(struct usbh_user_rndis *rndis_class)
/*the LINK SPEED is 100Mbps*/ /*the LINK SPEED is 100Mbps*/
usbh_rndis_eth_device.rndis_speed = rndis_class->rndis_class->link_speed; 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++) { for (j = 0; j < MAX_ADDR_LEN; j++) {
usbh_rndis_eth_device.dev_addr[j] = rndis_class->rndis_class->mac[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*/ 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; 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.rndis_recv);
rt_thread_startup(usbh_rndis_eth_device.keepalive_timer);
RNDIS_DEV_PRINTF("rndis dev start!\n"); RNDIS_DEV_PRINTF("rndis dev start!\n");
usbh_rndis_eth_device.rndis_class = rndis_class; 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); RT_ASSERT(g_user_rndis != RT_NULL);
g_user_rndis->rndis_class = rndis_class; g_user_rndis->rndis_class = rndis_class;
if (rt_rndis_run(g_user_rndis) == RT_EOK) { 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_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; info->rndis_recv = RT_NULL;
} }
eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE); 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; 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)*/ /*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) { if (info->keepalive_timer) {
rt_timer_stop(info->keepalive_timer); rt_thread_delete(info->keepalive_timer);
rt_timer_delete(info->keepalive_timer);
info->keepalive_timer = RT_NULL; info->keepalive_timer = RT_NULL;
} }
rt_mutex_release(usbh_rndis_eth_device.rndis_mutex);
info->rndis_state = RNDIS_BUS_UNINITIALIZED; 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_ASSERT(g_user_rndis != RT_NULL);
rt_rndis_stop(g_user_rndis); rt_rndis_stop(g_user_rndis);
usb_free(g_user_rndis); usb_free(g_user_rndis);
g_user_rndis = RT_NULL;
} }
/** /**
* This function rndis eth device. * 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 */ /* ethernet device interface */
/* transmit packet. */ /* transmit packet. */
extern int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, extern int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class,
uint32_t oid, uint32_t query_len, 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; break;
} }
RNDIS_DEV_PRINTF("linkdown, drop pkg\r\n"); 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); ret = usbh_rndis_query_msg_transfer(device->rndis_class->rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len);
if (ret < 0) { if (ret < 0) {
return -EBUSY; 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) { if (device->frame_debug == RT_TRUE) {
rt_kprintf("msg @ %08x\n", msg);
hex_data_print("rndis eth tx", (rt_uint8_t *)msg, msg->MessageLength); 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); 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
#endif #endif
__WEAK void lowlevel_usb_init(void) __WEAK void
lowlevel_usb_init(void)
{ {
} }
int usbh_rndis_eth_device_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. */ /* OUI 00-00-00, only for test. */
usbh_rndis_eth_device.dev_addr[0] = 0xFF; usbh_rndis_eth_device.dev_addr[0] = 0xFF;
usbh_rndis_eth_device.dev_addr[1] = 0xFF; usbh_rndis_eth_device.dev_addr[1] = 0xFF;
@@ -573,9 +588,9 @@ int usbh_rndis_eth_device_init(void)
lowlevel_usb_init(); 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() ** Function name eth_rndis_frame_debug()