summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--class/wireless/usbh_rndis.c225
-rw-r--r--osal/usb_osal_freertos.c29
-rw-r--r--port/ch32/ch58x/usb_ch585_usbhs_dc.c6
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
+}