diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 45494c6a6ed68e0bd2150b005cd3e72f2118a303..d0588a7b65d847a952c4f9c99770eb7f3e972433 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 8996b728e6640a6e60efda44691dd17e27c652f0..c025f4ef6fef95fd95520165badba055a70b2c74 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 000ea62baf40da3bbe453f21abd80ebf27476d41..fcdd2499843ad80478ab2f92cf5cae573f6a03cf 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 {