diff options
| -rw-r--r-- | class/wireless/usbh_rndis.c | 225 | ||||
| -rw-r--r-- | osal/usb_osal_freertos.c | 29 | ||||
| -rw-r--r-- | port/ch32/ch58x/usb_ch585_usbhs_dc.c | 6 |
3 files changed, 167 insertions, 93 deletions
diff --git a/class/wireless/usbh_rndis.c b/class/wireless/usbh_rndis.c index acee7043..2e657af1 100644 --- a/class/wireless/usbh_rndis.c +++ b/class/wireless/usbh_rndis.c @@ -40,12 +40,96 @@ static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class) return 0; } +static int usbh_rndis_parse_resp(struct usbh_rndis *rndis_class) +{ + struct usb_setup_packet *setup; + rndis_generic_msg_t *resp_generic; + int ret; + + if (!rndis_class || !rndis_class->hport) { + return -USB_ERR_INVAL; + } + setup = rndis_class->hport->setup; + + usbh_rndis_get_notification(rndis_class); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = sizeof(g_rndis_buf); + + ret = usbh_control_transfer(rndis_class->hport, setup, g_rndis_buf); + if (ret < sizeof(rndis_generic_msg_t)) { + USB_LOG_ERR("resp recv error, ret: %d\r\n", ret); + return ret; + } + + resp_generic = (rndis_generic_msg_t *)g_rndis_buf; + if (resp_generic->MessageLength != ret) { + USB_LOG_ERR("resp length error, expect: %d, actual: %d\r\n", resp_generic->MessageLength, ret); + return -USB_ERR_RANGE; + } + + switch (resp_generic->MessageType) { + case REMOTE_NDIS_INITIALIZE_CMPLT: + if (ret != sizeof(rndis_initialize_cmplt_t)) { + return -USB_ERR_RANGE; + } + rndis_initialize_cmplt_t *resp_init; + + resp_init = (rndis_initialize_cmplt_t *)g_rndis_buf; + + rndis_class->max_transfer_pkts = resp_init->MaxPacketsPerTransfer; + rndis_class->max_transfer_size = resp_init->MaxTransferSize; + USB_LOG_INFO("MaxPacketsPerTransfer: %u\r\n", (unsigned int)resp_init->MaxPacketsPerTransfer); + USB_LOG_INFO("MaxTransferSize: %u\r\n", (unsigned int)resp_init->MaxTransferSize); + break; + case REMOTE_NDIS_QUERY_CMPLT: + if (ret < sizeof(rndis_query_cmplt_t)) { + return -USB_ERR_RANGE; + } + + rndis_query_cmplt_t *resp_query; + resp_query = (rndis_query_cmplt_t *)g_rndis_buf; + + if (ret != (sizeof(rndis_query_cmplt_t) + resp_query->InformationBufferLength)) { + return -USB_ERR_RANGE; + } + if (resp_query->InformationBufferOffset != (sizeof(rndis_query_cmplt_t) - sizeof(rndis_generic_msg_t))) { + return -USB_ERR_RANGE; + } + + break; + case REMOTE_NDIS_SET_CMPLT: + break; + case REMOTE_NDIS_RESET_CMPLT: + break; + case REMOTE_NDIS_KEEPALIVE_CMPLT: + break; + case REMOTE_NDIS_INDICATE_STATUS_MSG: + if (ret != sizeof(rndis_indicate_status_t)) { + return -USB_ERR_RANGE; + } + + rndis_indicate_status_t *resp_indicate; + resp_indicate = (rndis_indicate_status_t *)g_rndis_buf; + + rndis_class->connect_status = (resp_indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) ? true : false; + break; + + default: + break; + } + + return ret; +} + static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) { struct usb_setup_packet *setup; - int ret = 0; + int ret; rndis_initialize_msg_t *cmd; - rndis_initialize_cmplt_t *resp; if (!rndis_class || !rndis_class->hport) { return -USB_ERR_INVAL; @@ -69,46 +153,36 @@ static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class) ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd); if (ret < 0) { - USB_LOG_ERR("init send error, ret: %d\r\n", ret); - return ret; - } - - usbh_rndis_get_notification(rndis_class); - - resp = (rndis_initialize_cmplt_t *)g_rndis_buf; - - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE; - setup->wValue = 0; - setup->wIndex = 0; - setup->wLength = sizeof(g_rndis_buf); - - ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); - if (ret < sizeof(rndis_initialize_cmplt_t)) { - USB_LOG_ERR("init recv error, ret: %d\r\n", ret); + USB_LOG_ERR("init msg send error, ret: %d\r\n", ret); return ret; } - rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer; - rndis_class->max_transfer_size = resp->MaxTransferSize; - USB_LOG_INFO("MaxPacketsPerTransfer: %u\r\n", (unsigned int)resp->MaxPacketsPerTransfer); - USB_LOG_INFO("MaxTransferSize: %u\r\n", (unsigned int)resp->MaxTransferSize); - - return ret; + return usbh_rndis_parse_resp(rndis_class); } -int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len) +static int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, + uint32_t oid, + uint32_t query_len, + uint8_t *info, + uint32_t info_max_len, + uint32_t *info_len) { struct usb_setup_packet *setup; - int ret = 0; + int ret; rndis_query_msg_t *cmd; rndis_query_cmplt_t *resp; if (!rndis_class || !rndis_class->hport) { return -USB_ERR_INVAL; } + + if(query_len > (sizeof(g_rndis_buf) - sizeof(rndis_query_msg_t))) { + return -USB_ERR_NOMEM; + } + setup = rndis_class->hport->setup; + cmd = (rndis_query_msg_t *)g_rndis_buf; cmd->MessageType = REMOTE_NDIS_QUERY_MSG; @@ -127,26 +201,29 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd); if (ret < 0) { - USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret); + USB_LOG_ERR("query oid:%08x msg send error, ret: %d\r\n", (unsigned int)oid, ret); return ret; } - usbh_rndis_get_notification(rndis_class); + ret = usbh_rndis_parse_resp(rndis_class); + if (ret < 0) { + return ret; + } resp = (rndis_query_cmplt_t *)g_rndis_buf; - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE; - setup->wValue = 0; - setup->wIndex = 0; - setup->wLength = sizeof(g_rndis_buf); - - ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); - if (ret < sizeof(rndis_query_cmplt_t)) { - USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret); + if(resp->MessageType != REMOTE_NDIS_QUERY_CMPLT) { return ret; } + if (query_len != 0 && resp->InformationBufferLength != query_len) { + return -USB_ERR_RANGE; + } + + if (resp->InformationBufferLength > info_max_len) { + return -USB_ERR_NOMEM; + } + memcpy(info, ((uint8_t *)resp + sizeof(rndis_query_cmplt_t)), resp->InformationBufferLength); *info_len = resp->InformationBufferLength; @@ -156,13 +233,17 @@ int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len) { struct usb_setup_packet *setup; - int ret = 0; + int ret; rndis_set_msg_t *cmd; - rndis_set_cmplt_t *resp; if (!rndis_class || !rndis_class->hport) { return -USB_ERR_INVAL; } + + if(info_len > (sizeof(g_rndis_buf) - sizeof(rndis_set_msg_t))) { + return -USB_ERR_NOMEM; + } + setup = rndis_class->hport->setup; cmd = (rndis_set_msg_t *)g_rndis_buf; @@ -188,35 +269,24 @@ static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t return ret; } - usbh_rndis_get_notification(rndis_class); - - resp = (rndis_set_cmplt_t *)g_rndis_buf; - - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE; - setup->wValue = 0; - setup->wIndex = 0; - setup->wLength = sizeof(g_rndis_buf); - - ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); - if (ret < sizeof(rndis_set_cmplt_t)) { - USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret); - return ret; - } - - return ret; + return usbh_rndis_parse_resp(rndis_class); } int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class) { int ret; - uint8_t data[32]; + uint8_t data[4]; uint32_t data_len; - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, sizeof(data), &data_len); if (ret < 0) { return ret; } + + if (ret == sizeof(rndis_indicate_status_t)) { + return 0; + } + if (NDIS_MEDIA_STATE_CONNECTED == data[0]) { rndis_class->connect_status = true; } else { @@ -230,7 +300,6 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class) struct usb_setup_packet *setup; int ret = 0; rndis_keepalive_msg_t *cmd; - rndis_keepalive_cmplt_t *resp; if (!rndis_class || !rndis_class->hport) { return -USB_ERR_INVAL; @@ -255,23 +324,7 @@ int usbh_rndis_keepalive(struct usbh_rndis *rndis_class) return ret; } - usbh_rndis_get_notification(rndis_class); - - resp = (rndis_keepalive_cmplt_t *)g_rndis_buf; - - setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; - setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE; - setup->wValue = 0; - setup->wIndex = 0; - setup->wLength = sizeof(g_rndis_buf); - - ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp); - if (ret < sizeof(rndis_keepalive_cmplt_t)) { - USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret); - return ret; - } - - return ret; + return usbh_rndis_parse_resp(rndis_class); } static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) @@ -283,7 +336,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) uint32_t oid_num = 0; uint32_t data_len; uint8_t tmp_buffer[512]; - uint8_t data[32]; + uint8_t data[6]; struct usbh_rndis *rndis_class = &g_rndis_class; @@ -314,7 +367,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) return ret; } - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_SUPPORTED_LIST, 0, tmp_buffer, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_SUPPORTED_LIST, 0, tmp_buffer, sizeof(tmp_buffer), &data_len); if (ret < 0) { return ret; } @@ -327,19 +380,19 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) oid = oid_support_list[i]; switch (oid) { case OID_GEN_PHYSICAL_MEDIUM: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_PHYSICAL_MEDIUM, 4, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_PHYSICAL_MEDIUM, 4, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } break; case OID_GEN_MAXIMUM_FRAME_SIZE: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MAXIMUM_FRAME_SIZE, 4, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MAXIMUM_FRAME_SIZE, 4, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } break; case OID_GEN_LINK_SPEED: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_LINK_SPEED, 4, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_LINK_SPEED, 4, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } @@ -347,7 +400,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) memcpy(&rndis_class->link_speed, data, 4); break; case OID_GEN_MEDIA_CONNECT_STATUS: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } @@ -358,13 +411,13 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) } break; case OID_802_3_MAXIMUM_LIST_SIZE: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_MAXIMUM_LIST_SIZE, 4, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_MAXIMUM_LIST_SIZE, 4, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } break; case OID_802_3_CURRENT_ADDRESS: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_CURRENT_ADDRESS, 6, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_CURRENT_ADDRESS, 6, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } @@ -374,7 +427,7 @@ static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf) } break; case OID_802_3_PERMANENT_ADDRESS: - ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_PERMANENT_ADDRESS, 6, data, &data_len); + ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_PERMANENT_ADDRESS, 6, data, sizeof(data), &data_len); if (ret < 0) { goto query_errorout; } diff --git a/osal/usb_osal_freertos.c b/osal/usb_osal_freertos.c index f1ebf7fc..ed145291 100644 --- a/osal/usb_osal_freertos.c +++ b/osal/usb_osal_freertos.c @@ -57,11 +57,22 @@ void usb_osal_sem_delete(usb_osal_sem_t sem) int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) { - if (timeout == USB_OSAL_WAITING_FOREVER) { - return (xSemaphoreTake((SemaphoreHandle_t)sem, portMAX_DELAY) == pdPASS) ? 0 : -USB_ERR_TIMEOUT; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + int ret; + + if (xPortIsInsideInterrupt()) { + /* ISR context: only non-blocking take is allowed */ + ret = xSemaphoreTakeFromISR((SemaphoreHandle_t)sem, &xHigherPriorityTaskWoken); + if (ret == pdPASS) { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + } else if (timeout == USB_OSAL_WAITING_FOREVER) { + ret = xSemaphoreTake((SemaphoreHandle_t)sem, portMAX_DELAY); } else { - return (xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -USB_ERR_TIMEOUT; + ret = xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)); } + + return (ret == pdPASS) ? 0 : -USB_ERR_TIMEOUT; } int usb_osal_sem_give(usb_osal_sem_t sem) @@ -206,7 +217,17 @@ void usb_osal_timer_start(struct usb_osal_timer *timer) void usb_osal_timer_stop(struct usb_osal_timer *timer) { - xTimerStop(timer->timer, 0); + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + int ret; + + if (xPortIsInsideInterrupt()) { + ret = xTimerStopFromISR(timer->timer, &xHigherPriorityTaskWoken); + if (ret == pdPASS) { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + } else { + xTimerStop(timer->timer, 0); + } } size_t usb_osal_enter_critical_section(void) diff --git a/port/ch32/ch58x/usb_ch585_usbhs_dc.c b/port/ch32/ch58x/usb_ch585_usbhs_dc.c index 2e6724c2..1f33a36d 100644 --- a/port/ch32/ch58x/usb_ch585_usbhs_dc.c +++ b/port/ch32/ch58x/usb_ch585_usbhs_dc.c @@ -41,7 +41,7 @@ * @brief Endpoint information structure */ typedef struct _usbd_ep_info { - uint8_t mps; /* Maximum packet length of endpoint */ + uint16_t mps; /* Maximum packet length of endpoint */ uint8_t eptype; /* Endpoint Type */ uint8_t ep_enable; /* Endpoint enable */ uint8_t *xfer_buf; @@ -143,7 +143,7 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) return -1; } - uint8_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + uint16_t mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); USB_SET_MAX_LEN(epid, mps); if (USB_EP_DIR_IS_IN(ep->bEndpointAddress)) { @@ -523,4 +523,4 @@ void USB2_DEVICE_IRQHandler(void) { extern void USBD_IRQHandler(uint8_t busid); USBD_IRQHandler(0); -}
\ No newline at end of file +} |
