Skip to content

Commit

Permalink
usb(uvc_stream/usbh_cdc): get fullspeed descriptor by default
Browse files Browse the repository at this point in the history
resolve #146, resolve #152, resolve #156, resolve #157
  • Loading branch information
leeebo committed Mar 7, 2022
1 parent 2ba36c5 commit 0473e9b
Show file tree
Hide file tree
Showing 11 changed files with 530 additions and 277 deletions.
11 changes: 10 additions & 1 deletion components/usb/esp_usbh_cdc/Kconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
menu "USB Host CDC"

config CDC_GET_DEVICE_DESC
bool "Get device descriptor during emum"
default y
config CDC_GET_CONFIG_DESC
bool "Get config descriptor during emum"
default y
config CDC_SEND_DTE_ACTIVE
bool "Set control line state during init"
default y
Expand All @@ -15,6 +20,10 @@ menu "USB Host CDC"
default 5
help
usb task base priority, usb task = base + 2, cdc task = base + 1
config CTRL_TRANSFER_DATA_MAX_BYTES
int "Max control transfer data size (Bytes)"
range 64 2048
default 256
config CDC_BULK_IN_URB_NUM
int "cdc bulk_in urb num"
default 2
Expand Down
104 changes: 100 additions & 4 deletions components/usb/esp_usbh_cdc/esp_usbh_cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "hcd.h"
#include "usb/usb_types_stack.h"
#include "usb_private.h"
#include "usb/usb_helpers.h"
#include "esp_private/usb_phy.h"
#include "esp_usbh_cdc.h"

Expand All @@ -47,12 +48,15 @@ static const char *TAG = "USB_HCDC";

#define USB_PORT_NUM 1 //Default port number
#define USB_DEVICE_ADDR 1 //Default CDC device address
#define USB_ENUM_CONFIG_INDEX 0 //Index of the first configuration of the device
#define USB_ENUM_SHORT_DESC_REQ_LEN 8 //Number of bytes to request when getting a short descriptor (just enough to get bMaxPacketSize0 or wTotalLength)
#define USB_DEVICE_CONFIG 1 //Default CDC device configuration
#define USB_EP_CTRL_DEFAULT_MPS 64 //Default MPS(max payload size) of Endpoint 0
#define CDC_EVENT_QUEUE_LEN 16
#define DATA_EVENT_QUEUE_LEN 32
#define CTRL_TRANSFER_DATA_MAX_BYTES 256 //Just assume that will only IN/OUT 256 bytes in ctrl pipe
#define CTRL_TRANSFER_DATA_MAX_BYTES CONFIG_CTRL_TRANSFER_DATA_MAX_BYTES //Just assume that will only IN/OUT 256 bytes in ctrl pipe
#define TIMEOUT_USB_RINGBUF_MS 200 //Timeout for Ring Buffer push
#define TIMEOUT_USB_CTRL_XFER_MS 5000 //Timeout for USB control transfer

#define USB_TASK_BASE_PRIORITY CONFIG_USB_TASK_BASE_PRIORITY

Expand Down Expand Up @@ -674,6 +678,90 @@ static esp_err_t _default_pipe_event_wait_until(hcd_pipe_handle_t expected_pipe_

/*------------------------------------------------ USB Control Process Code ----------------------------------------------------*/

#ifdef CONFIG_CDC_GET_DEVICE_DESC
static esp_err_t _usb_get_dev_desc(hcd_pipe_handle_t pipe_handle, usb_device_desc_t *device_desc)
{
CDC_CHECK(pipe_handle != NULL, "pipe_handle can't be NULL", ESP_ERR_INVALID_ARG);
//malloc URB for default control
urb_t *urb_ctrl = _usb_urb_alloc(0, sizeof(usb_setup_packet_t) + CTRL_TRANSFER_DATA_MAX_BYTES, NULL);
CDC_CHECK(urb_ctrl != NULL, "alloc urb failed", ESP_ERR_NO_MEM);
urb_t *urb_done = NULL;
ESP_LOGI(TAG, "get device desc");
USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)urb_ctrl->transfer.data_buffer);
urb_ctrl->transfer.num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(sizeof(usb_device_desc_t), USB_EP_CTRL_DEFAULT_MPS);
esp_err_t ret = hcd_urb_enqueue(pipe_handle, urb_ctrl);
CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(TIMEOUT_USB_CTRL_XFER_MS));
CDC_CHECK_GOTO(ESP_OK == ret, "urb event error", flush_urb_);
urb_done = hcd_urb_dequeue(pipe_handle);
CDC_CHECK_GOTO(urb_done == urb_ctrl, "urb status: not same", free_urb_);
CDC_CHECK_GOTO(USB_TRANSFER_STATUS_COMPLETED == urb_done->transfer.status, "urb status: not complete", free_urb_);
CDC_CHECK_GOTO((urb_done->transfer.actual_num_bytes <= sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t)), "urb status: data overflow", free_urb_);
ESP_LOGI(TAG, "get device desc, actual_num_bytes:%d", urb_done->transfer.actual_num_bytes);
usb_device_desc_t *dev_desc = (usb_device_desc_t *)(urb_done->transfer.data_buffer + sizeof(usb_setup_packet_t));
if (device_desc != NULL ) *device_desc = *dev_desc;
usb_print_device_descriptor(dev_desc);
goto free_urb_;

flush_urb_:
_usb_pipe_flush(pipe_handle, 1);
free_urb_:
_usb_urb_free(urb_ctrl);
return ret;
}
#endif

#ifdef CONFIG_CDC_GET_CONFIG_DESC
static esp_err_t _usb_get_config_desc(hcd_pipe_handle_t pipe_handle, usb_config_desc_t **config_desc)
{
(void)config_desc;
CDC_CHECK(pipe_handle != NULL, "pipe_handle can't be NULL", ESP_ERR_INVALID_ARG);
//malloc URB for default control
urb_t *urb_ctrl = _usb_urb_alloc(0, sizeof(usb_setup_packet_t) + CTRL_TRANSFER_DATA_MAX_BYTES, NULL);
CDC_CHECK(urb_ctrl != NULL, "alloc urb failed", ESP_ERR_NO_MEM);
urb_t *urb_done = NULL;
ESP_LOGI(TAG, "get short config desc");
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_ctrl->transfer.data_buffer, USB_ENUM_CONFIG_INDEX, USB_ENUM_SHORT_DESC_REQ_LEN);
urb_ctrl->transfer.num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(sizeof(usb_config_desc_t), USB_EP_CTRL_DEFAULT_MPS);
esp_err_t ret = hcd_urb_enqueue(pipe_handle, urb_ctrl);
CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(TIMEOUT_USB_CTRL_XFER_MS));
CDC_CHECK_GOTO(ESP_OK == ret, "urb event error", flush_urb_);
urb_done = hcd_urb_dequeue(pipe_handle);
CDC_CHECK_GOTO(urb_done == urb_ctrl, "urb status: not same", free_urb_);
CDC_CHECK_GOTO(USB_TRANSFER_STATUS_COMPLETED == urb_done->transfer.status, "urb status: not complete", free_urb_);
CDC_CHECK_GOTO((urb_done->transfer.actual_num_bytes <= sizeof(usb_setup_packet_t) + sizeof(usb_config_desc_t)), "urb status: data overflow", free_urb_);
ESP_LOGI(TAG, "get config desc, actual_num_bytes:%d", urb_done->transfer.actual_num_bytes);
usb_config_desc_t *cfg_desc = (usb_config_desc_t *)(urb_done->transfer.data_buffer + sizeof(usb_setup_packet_t));
uint16_t full_config_length = cfg_desc->wTotalLength;
if (cfg_desc->wTotalLength > CTRL_TRANSFER_DATA_MAX_BYTES) {
ESP_LOGE(TAG, "Configuration descriptor larger than control transfer max length");
goto free_urb_;
}
ESP_LOGI(TAG, "get full config desc");
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_ctrl->transfer.data_buffer, USB_ENUM_CONFIG_INDEX, full_config_length);
urb_ctrl->transfer.num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(full_config_length, USB_EP_CTRL_DEFAULT_MPS);
ret = hcd_urb_enqueue(pipe_handle, urb_ctrl);
CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(TIMEOUT_USB_CTRL_XFER_MS));
CDC_CHECK_GOTO(ESP_OK == ret, "urb event error", flush_urb_);
urb_done = hcd_urb_dequeue(pipe_handle);
CDC_CHECK_GOTO(urb_done == urb_ctrl, "urb status: not same", free_urb_);
CDC_CHECK_GOTO(USB_TRANSFER_STATUS_COMPLETED == urb_done->transfer.status, "urb status: not complete", free_urb_);
CDC_CHECK_GOTO((urb_done->transfer.actual_num_bytes <= sizeof(usb_setup_packet_t) + full_config_length), "urb status: data overflow", free_urb_);
ESP_LOGI(TAG, "get full config desc, actual_num_bytes:%d", urb_done->transfer.actual_num_bytes);
cfg_desc = (usb_config_desc_t *)(urb_done->transfer.data_buffer + sizeof(usb_setup_packet_t));
usb_print_config_descriptor(cfg_desc, NULL);
goto free_urb_;

flush_urb_:
_usb_pipe_flush(pipe_handle, 1);
free_urb_:
_usb_urb_free(urb_ctrl);
return ret;
}
#endif

static esp_err_t _usb_set_device_addr(hcd_pipe_handle_t pipe_handle, uint8_t dev_addr)
{
CDC_CHECK(pipe_handle != NULL, "pipe_handle can't be NULL", ESP_ERR_INVALID_ARG);
Expand All @@ -688,7 +776,7 @@ static esp_err_t _usb_set_device_addr(hcd_pipe_handle_t pipe_handle, uint8_t dev
ESP_LOGI(TAG, "Set Device Addr = %u", dev_addr);
esp_err_t ret = hcd_urb_enqueue(pipe_handle, urb_ctrl);
CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(500));
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(TIMEOUT_USB_CTRL_XFER_MS));
CDC_CHECK_GOTO(ESP_OK == ret, "urb event error", flush_urb_);
urb_t *urb_done = hcd_urb_dequeue(pipe_handle);
CDC_CHECK_GOTO(urb_done == urb_ctrl, "urb status: not same", free_urb_);
Expand Down Expand Up @@ -721,7 +809,7 @@ static esp_err_t _usb_set_device_config(hcd_pipe_handle_t pipe_handle, uint16_t
ESP_LOGI(TAG, "Set Device Configuration = %u", configuration);
esp_err_t ret = hcd_urb_enqueue(pipe_handle, urb_ctrl);
CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(500));
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(TIMEOUT_USB_CTRL_XFER_MS));
CDC_CHECK_GOTO(ESP_OK == ret, "urb event error", flush_urb_);
urb_t *urb_done = hcd_urb_dequeue(pipe_handle);
CDC_CHECK_GOTO(urb_done == urb_ctrl, "urb status: not same", free_urb_);
Expand Down Expand Up @@ -750,7 +838,7 @@ static esp_err_t _usb_set_device_line_state(hcd_pipe_handle_t pipe_handle, bool
ESP_LOGI(TAG, "Set Device Line State: dtr %d, rts %d", dtr, rts);
esp_err_t ret = hcd_urb_enqueue(pipe_handle, urb_ctrl);
CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, portMAX_DELAY);
ret = _default_pipe_event_wait_until(pipe_handle, HCD_PIPE_EVENT_URB_DONE, pdMS_TO_TICKS(TIMEOUT_USB_CTRL_XFER_MS));
CDC_CHECK_GOTO(ESP_OK == ret, "urb event error", flush_urb_);
urb_t *urb_done = hcd_urb_dequeue(pipe_handle);
CDC_CHECK_GOTO(urb_done == urb_ctrl, "urb status: not same", free_urb_);
Expand Down Expand Up @@ -1073,6 +1161,14 @@ static void _usb_processing_task(void *arg)

ret = _usb_set_device_addr(pipe_hdl_dflt, USB_DEVICE_ADDR);
CDC_CHECK_GOTO(ESP_OK == ret, "Set device address failed", usb_driver_reset_);
#ifdef CONFIG_CDC_GET_DEVICE_DESC
ret = _usb_get_dev_desc(pipe_hdl_dflt, NULL);
CDC_CHECK_GOTO(ESP_OK == ret, "Get device descriptor failed", usb_driver_reset_);
#endif
#ifdef CONFIG_CDC_GET_CONFIG_DESC
ret = _usb_get_config_desc(pipe_hdl_dflt, NULL);
CDC_CHECK_GOTO(ESP_OK == ret, "Get config descriptor failed", usb_driver_reset_);
#endif
_update_device_state(CDC_DEVICE_STATE_ADDRESS);
ret = _usb_set_device_config(pipe_hdl_dflt, USB_DEVICE_CONFIG);
CDC_CHECK_GOTO(ESP_OK == ret, "Set device configuration failed", usb_driver_reset_);
Expand Down
2 changes: 1 addition & 1 deletion components/usb/uvc_stream/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ endif()

#ESP-IDF USB component HCD level API default to private now,
#to use uvc_stream, related API must manually set to public.
idf_component_register(SRCS uvc_stream.c
idf_component_register(SRCS uvc_stream.c descriptor.c
INCLUDE_DIRS "include" "${IDF_PATH}/components/usb/private_include"
EMBED_FILES ${embed_files}
REQUIRES usb)
20 changes: 18 additions & 2 deletions components/usb/uvc_stream/Kconfig
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
menu "UVC Stream"

config CTRL_TRANSFER_DATA_MAX_BYTES
int "Max control transfer data size (Bytes)"
range 64 2048
default 600
config UVC_GET_DEVICE_DESC
bool "Get camera device descriptor during emum"
default y
config UVC_GET_CONFIG_DESC
bool "Get camera config descriptor during emum"
default y
config UVC_PRINT_DESC_VERBOSE
bool "Print camera more descriptor info"
default n
config UVC_PRINT_PROBE_RESULT
bool "Print video cur probe result"
default y
config SOURCE_SIMULATE
bool "Enable Simulate Pictures From Flash"
default false
default n

config TRIGGER_PIN
bool "Enable Trigger Pin For Debug"
default false
default n

endmenu
Loading

0 comments on commit 0473e9b

Please sign in to comment.