From cc9ce52bae2383dc5766a17991f2c6c074527b0e Mon Sep 17 00:00:00 2001 From: ZYH Date: Mon, 10 Jun 2019 14:10:08 +0800 Subject: [PATCH 1/2] [Components][USB][RNDIS] fix hotplug and "delay linkup" --- components/drivers/Kconfig | 7 + .../drivers/usb/usbdevice/class/rndis.c | 232 ++++++++++++------ .../drivers/usb/usbdevice/class/rndis.h | 9 + 3 files changed, 171 insertions(+), 77 deletions(-) diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 45494c6a6e..d0588a7b65 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -640,6 +640,13 @@ menu "Using USB" string "msc class disk name" default "flash0" endif + + if RT_USB_DEVICE_RNDIS + config RNDIS_DELAY_LINK_UP + bool "Delay linkup media connection" + default n + endif + if RT_USB_DEVICE_HID config RT_USB_DEVICE_HID_KEYBOARD bool "Use to HID device as Keyboard" diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index 8996b728e6..c025f4ef6f 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -13,21 +13,21 @@ * 2013-07-09 aozima support respone chain list. * 2013-07-18 aozima re-initial respone chain list when RNDIS restart. * 2017-11-25 ZYH fix it and add OS descriptor + * 2019-06-10 ZYH fix hot plug and delay linkup */ #include +#ifdef RT_USB_DEVICE_RNDIS #include "cdc.h" #include "rndis.h" #include "ndis.h" -//#define RNDIS_DEBUG -//#define RNDIS_DELAY_LINK_UP +/* define RNDIS_DELAY_LINK_UP by menuconfig for delay linkup */ + +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "RNDIS" +#include -#ifdef RNDIS_DEBUG -#define RNDIS_PRINTF rt_kprintf("[RNDIS] "); rt_kprintf -#else -#define RNDIS_PRINTF(...) -#endif /* RNDIS_DEBUG */ /* RT-Thread LWIP ethernet interface */ #include @@ -314,7 +314,7 @@ static rt_err_t _rndis_init_response(ufunction_t func, rndis_init_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -360,7 +360,7 @@ static rndis_query_cmplt_t _create_resp(rt_size_t size) if(resp == RT_NULL) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); return RT_NULL; } @@ -510,7 +510,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) break; default: - RNDIS_PRINTF("OID %X\n", msg->Oid); + LOG_W("Not support OID %X", msg->Oid); ret = -RT_ERROR; break; } @@ -518,7 +518,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) response = rt_malloc(sizeof(struct rt_rndis_response)); if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -557,7 +557,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -577,8 +577,10 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) case OID_GEN_CURRENT_PACKET_FILTER: oid_packet_filter = *((rt_uint32_t *)((rt_uint8_t *)&(msg->RequestId) + \ msg->InformationBufferOffset)); + /* TODO: make complier happy */ oid_packet_filter = oid_packet_filter; - RNDIS_PRINTF("OID_GEN_CURRENT_PACKET_FILTER\r\n"); + + LOG_D("OID_GEN_CURRENT_PACKET_FILTER"); #ifdef RNDIS_DELAY_LINK_UP /* link up. */ @@ -592,6 +594,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) break; default: + LOG_W("Unknow rndis set 0x%02X", msg->Oid); resp->Status = RNDIS_STATUS_FAILURE; return RT_EOK; } @@ -609,6 +612,58 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) return RT_EOK; } +static rt_err_t _rndis_reset_response(ufunction_t func,rndis_set_msg_t msg) +{ + struct rndis_reset_cmplt * resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_reset_cmplt)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + /* reset packet filter */ + + oid_packet_filter = 0x0000000; + + /* link down eth */ + + eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + rt_sem_release(&((rt_rndis_eth_t)func->user_data)->tx_buffer_free); + eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); + + + resp->MessageType = REMOTE_NDIS_RESET_CMPLT; + resp->MessageLength = sizeof(struct rndis_reset_cmplt); + resp->Status = RNDIS_STATUS_SUCCESS; + resp->AddressingReset = 1; + + response->buffer = resp; + + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + return RT_EOK; +} + static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg) { rndis_keepalive_cmplt_t resp; @@ -619,7 +674,7 @@ static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -652,34 +707,45 @@ static rt_err_t _rndis_msg_parser(ufunction_t func, rt_uint8_t *msg) switch (((rndis_gen_msg_t) msg)->MessageType) { case REMOTE_NDIS_INITIALIZE_MSG: + LOG_D("REMOTE_NDIS_INITIALIZE_MSG"); ret = _rndis_init_response(func, (rndis_init_msg_t) msg); break; case REMOTE_NDIS_HALT_MSG: - RNDIS_PRINTF("halt\n"); + LOG_D("REMOTE_NDIS_HALT_MSG"); /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + rt_sem_release(&((rt_rndis_eth_t)func->user_data)->tx_buffer_free); + eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); + break; case REMOTE_NDIS_QUERY_MSG: + LOG_D("REMOTE_NDIS_QUERY_MSG"); ret = _rndis_query_response(func,(rndis_query_msg_t) msg); break; case REMOTE_NDIS_SET_MSG: + LOG_D("REMOTE_NDIS_SET_MSG"); ret = _rndis_set_response(func,(rndis_set_msg_t) msg); - RNDIS_PRINTF("set\n"); break; case REMOTE_NDIS_RESET_MSG: - RNDIS_PRINTF("reset\n"); + LOG_D("REMOTE_NDIS_RESET_MSG"); + ret = _rndis_reset_response(func,(rndis_set_msg_t) msg); break; case REMOTE_NDIS_KEEPALIVE_MSG: + LOG_D("REMOTE_NDIS_KEEPALIVE_MSG"); ret = _rndis_keepalive_response(func,(rndis_keepalive_msg_t) msg); break; default: - RNDIS_PRINTF("msg %X\n", ((rndis_gen_msg_t) msg)->MessageType); + LOG_W("not support RNDIS msg %X", ((rndis_gen_msg_t) msg)->MessageType); ret = -RT_ERROR; break; } @@ -718,7 +784,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) if(rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { - RNDIS_PRINTF("response_list is empty!\r\n"); + LOG_D("response_list is empty!"); ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE; return RT_EOK; } @@ -741,7 +807,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) { rt_uint32_t * data; - RNDIS_PRINTF("auto append next response!\r\n"); + LOG_I("auto append next response!"); data = (rt_uint32_t *)((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer; data[0] = RESPONSE_AVAILABLE; data[1] = 0; @@ -758,55 +824,6 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) return RT_EOK; } -#ifdef RNDIS_DELAY_LINK_UP -/** - * This function will set rndis connect status. - * - * @param device the usb device object. - * @param status the connect status. - * - * @return RT_EOK on successful. - */ -static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) -{ - rndis_indicate_status_msg_t resp; - struct rt_rndis_response * response; - - response = rt_malloc(sizeof(struct rt_rndis_response)); - resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); - - if( (response == RT_NULL) || (resp == RT_NULL) ) - { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); - - if(response != RT_NULL) - rt_free(response); - - if(resp != RT_NULL) - rt_free(resp); - - return -RT_ENOMEM; - } - - resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; - resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ - resp->Status = status; - resp->StatusBufferLength = 0; - resp->StatusBufferOffset = 0; - - response->buffer = resp; - { - rt_base_t level = rt_hw_interrupt_disable(); - rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); - rt_hw_interrupt_enable(level); - } - - _rndis_response_available(func); - - return RT_EOK; -} -#endif /* RNDIS_DELAY_LINK_UP */ - /** * This function will handle rndis interface request. * @@ -831,7 +848,7 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) break; default: - RNDIS_PRINTF("unkown setup->request!\r\n"); + LOG_W("unkown setup->request 0x%02X !", setup->bRequest); break; } @@ -933,6 +950,8 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; + LOG_I("plugged in"); + eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps; eps->ep_in->buffer = ((rt_rndis_eth_t)func->user_data)->tx_pool; eps->ep_out->buffer = ((rt_rndis_eth_t)func->user_data)->rx_pool; @@ -945,6 +964,7 @@ static rt_err_t _function_enable(ufunction_t func) ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -981,7 +1001,7 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { - RNDIS_PRINTF("plugged out\n"); + LOG_I("plugged out"); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -996,7 +1016,7 @@ static rt_err_t _function_disable(ufunction_t func) while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next; - RNDIS_PRINTF("remove resp chain list!\r\n"); + LOG_D("remove resp chain list!"); rt_list_remove(&response->list); rt_free((void *)response->buffer); @@ -1007,8 +1027,16 @@ static rt_err_t _function_disable(ufunction_t func) rt_hw_interrupt_enable(level); } + /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + rt_sem_release(&((rt_rndis_eth_t)func->user_data)->tx_buffer_free); + eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); + return RT_EOK; } @@ -1141,14 +1169,14 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p) if(!device->parent.link_status) { - RNDIS_PRINTF("linkdown, drop pkg\r\n"); + LOG_I("linkdown, drop pkg"); return RT_EOK; } RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); if(p->tot_len > sizeof(device->tx_buffer)) { - RNDIS_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("RNDIS MTU is:%d, but the send packet size is %d", sizeof(device->tx_buffer), p->tot_len); p->tot_len = sizeof(device->tx_buffer); } @@ -1215,11 +1243,59 @@ const static struct rt_device_ops rndis_device_ops = #endif /* RT_USING_LWIP */ #ifdef RNDIS_DELAY_LINK_UP + +/** + * This function will set rndis connect status. + * + * @param device the usb device object. + * @param status the connect status. + * + * @return RT_EOK on successful. + */ +static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) +{ + rndis_indicate_status_msg_t resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; + resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ + resp->Status = status; + resp->StatusBufferLength = 0; + resp->StatusBufferOffset = 0; + + response->buffer = resp; + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + _rndis_response_available(func); + + return RT_EOK; +} + /* the delay linkup timer handler. */ static void timer_timeout(void* parameter) { - RNDIS_PRINTF("delay link up!\r\n"); - _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->parent.parent.user_data, + LOG_I("delay link up!"); + _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->func, RNDIS_STATUS_MEDIA_CONNECT); eth_device_linkchange(&((rt_rndis_eth_t)parameter)->parent, RT_TRUE); } @@ -1372,4 +1448,6 @@ int rt_usbd_rndis_class_register(void) rt_usbd_class_register(&rndis_class); return 0; } -INIT_PREV_EXPORT(rt_usbd_rndis_class_register); \ No newline at end of file +INIT_PREV_EXPORT(rt_usbd_rndis_class_register); + +#endif /* RT_USB_DEVICE_RNDIS */ diff --git a/components/drivers/usb/usbdevice/class/rndis.h b/components/drivers/usb/usbdevice/class/rndis.h index 000ea62baf..fcdd249984 100644 --- a/components/drivers/usb/usbdevice/class/rndis.h +++ b/components/drivers/usb/usbdevice/class/rndis.h @@ -180,6 +180,15 @@ struct rndis_reset_msg rt_uint32_t Reserved; }; +/* Remote NDIS Soft Reset Response */ +struct rndis_reset_cmplt +{ + rt_uint32_t MessageType; + rt_uint32_t MessageLength; + rt_uint32_t Status; + rt_uint32_t AddressingReset; +}; + /* Remote NDIS Indicate Status Message */ struct rndis_indicate_status_msg { From 7a75e449b606d724a4f2ec90a8d8701f3c232a56 Mon Sep 17 00:00:00 2001 From: ZYH Date: Mon, 10 Jun 2019 14:10:59 +0800 Subject: [PATCH 2/2] [Components][USB][ECM] fix hotplug --- components/drivers/usb/usbdevice/class/ecm.c | 47 +++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c index cda1a8bf1b..9103493f2c 100644 --- a/components/drivers/usb/usbdevice/class/ecm.c +++ b/components/drivers/usb/usbdevice/class/ecm.c @@ -6,17 +6,16 @@ * Change Logs: * Date Author Notes * 2017-11-19 ZYH first version + * 2019-06-10 ZYH fix hotplug */ #include +#ifdef RT_USB_DEVICE_ECM #include "cdc.h" - -#ifdef ECM_DEBUG -#define ECM_PRINTF rt_kprintf("[ECM] "); rt_kprintf -#else -#define ECM_PRINTF(...) -#endif /* ECM_DEBUG */ +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "ECM" +#include /* RT-Thread LWIP ethernet interface */ #include @@ -216,15 +215,21 @@ static rt_err_t _cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notif return RT_EOK; } + static rt_err_t _ecm_set_eth_packet_filter(ufunction_t func, ureq_t setup) { rt_ecm_eth_t _ecm_eth = (rt_ecm_eth_t)func->user_data; dcd_ep0_send_status(func->device->dcd); - /* send link up. */ eth_device_linkchange(&_ecm_eth->parent, RT_TRUE); - _cdc_send_notifi(func,UCDC_NOTIFI_NETWORK_CONNECTION,1,0); + _cdc_send_notifi(func, UCDC_NOTIFI_NETWORK_CONNECTION, 1, 0); + +#ifdef LWIP_USING_DHCPD + extern void dhcpd_start(const char *netif_name); + dhcpd_start("u0"); +#endif + return RT_EOK; } /** @@ -243,10 +248,11 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) switch(setup->bRequest) { case CDC_SET_ETH_PACKET_FILTER: + LOG_D("CDC_SET_ETH_PACKET_FILTER"); _ecm_set_eth_packet_filter(func, setup); break; default: - rt_kprintf("setup->bRequest:0x%02X",setup->bRequest); + LOG_E("Unknow setup->bRequest: 0x%02X", setup->bRequest); break; } return RT_EOK; @@ -402,14 +408,13 @@ rt_err_t rt_ecm_eth_tx(rt_device_t dev, struct pbuf* p) if(!ecm_eth_dev->parent.link_status) { - ECM_PRINTF("linkdown, drop pkg\r\n"); + LOG_D("linkdown, drop pkg"); return RT_EOK; } - // RT_ASSERT(p->tot_len < USB_ETH_MTU); if(p->tot_len > USB_ETH_MTU) { - ECM_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("ECM MTU is:%d, but the send packet size is %d", USB_ETH_MTU, p->tot_len); p->tot_len = USB_ETH_MTU; } @@ -461,10 +466,17 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data; + + LOG_D("plugged in"); + eps = (cdc_eps_t)&ecm_device->eps; eps->ep_out->buffer = ecm_device->rx_pool; + + /* reset eth rx tx */ + rt_sem_release(&ecm_device->tx_buffer_free); ecm_device->rx_size = 0; ecm_device->rx_offset = 0; + eth_device_ready(&ecm_device->parent); eps->ep_out->request.buffer = (void *)eps->ep_out->buffer; eps->ep_out->request.size = EP_MAXPACKET(eps->ep_out); @@ -482,7 +494,16 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { + LOG_D("plugged out"); + eth_device_linkchange(&((rt_ecm_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + rt_sem_release(&((rt_ecm_eth_t)func->user_data)->tx_buffer_free); + ((rt_ecm_eth_t)func->user_data)->rx_size = 0; + ((rt_ecm_eth_t)func->user_data)->rx_offset = 0; + eth_device_ready(&((rt_ecm_eth_t)func->user_data)->parent); + return RT_EOK; } @@ -643,3 +664,5 @@ int rt_usbd_ecm_class_register(void) return 0; } INIT_PREV_EXPORT(rt_usbd_ecm_class_register); + +#endif /* RT_USB_DEVICE_ECM */