Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions host/class/uvc/usb_host_uvc/Kconfig
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
menu "USB HOST UVC"
menu "USB-Driver: UVC Host"

config PRINTF_UVC_CONFIGURATION_DESCRIPTOR
config UVC_HOST_PRINT_CONFIG_DESCRIPTOR
bool "Print UVC Configuration Descriptor"
default n
help
Print UVC Configuration Descriptor to console.

config UVC_INTERVAL_ARRAY_SIZE
config UVC_HOST_PRINT_SUPPORTED_FORMATS
bool "Print supported formats"
default n
help
When the stream parameters are unknown, this feature could be enabled to show supported formats by the camera.
When enabled, the driver displays resolution, format and default FPS.

Disabled by default.

config UVC_HOST_INTERVAL_ARRAY_SIZE
int "Size of the interval array in uvc_host_frame_info_t"
default 3
help
Expand Down
6 changes: 5 additions & 1 deletion host/class/uvc/usb_host_uvc/include/usb/uvc_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
#include "usb/usb_host.h"
#include "usb/usb_types_uvc.h"
#include "esp_err.h"
#include "sdkconfig.h"

// Use this macros for opening a UVC stream with any VID or PID
#define UVC_HOST_ANY_VID (0)
#define UVC_HOST_ANY_PID (0)
#define UVC_HOST_ANY_DEV_ADDR (0)

#define UVC_HOST_INTERVAL_ARRAY_SIZE (CONFIG_UVC_HOST_INTERVAL_ARRAY_SIZE)

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -35,6 +38,7 @@ enum uvc_host_stream_format {
UVC_VS_FORMAT_YUY2,
UVC_VS_FORMAT_H264,
UVC_VS_FORMAT_H265,
UVC_VS_FORMAT_MAX
};

/**
Expand All @@ -53,7 +57,7 @@ typedef struct {
uint32_t interval_max; /**< Maximum frame interval */
uint32_t interval_step; /**< Frame interval step */
};
uint32_t interval[CONFIG_UVC_INTERVAL_ARRAY_SIZE]; /**< We must put a fixed size here because of the union type. This is flexible size array though */
uint32_t interval[UVC_HOST_INTERVAL_ARRAY_SIZE]; /**< We must put a fixed size here because of the union type. This is flexible size array though */
};
} uvc_host_frame_info_t;

Expand Down
40 changes: 38 additions & 2 deletions host/class/uvc/usb_host_uvc/uvc_descriptor_parsing.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,33 @@
#include <inttypes.h>
#include <string.h> // strncmp for guid format parsing
#include <math.h> // fabsf for float comparison
#include "esp_log.h"
#include "usb/usb_helpers.h"
#include "usb/uvc_host.h"
#include "uvc_check_priv.h"
#include "uvc_descriptors_priv.h"
#include "sdkconfig.h"

#define UVC_PRINT_SUPPORTED_FORMATS CONFIG_UVC_HOST_PRINT_SUPPORTED_FORMATS

#define FLOAT_EQUAL(a, b) (fabsf(a - b) < 0.0001f) // For comparing float values with acceptable difference (epsilon value)

#if (UVC_PRINT_SUPPORTED_FORMATS)
static const char *format_to_string[UVC_VS_FORMAT_MAX] = {
"Undefined",
"MJPEG",
"YUY2",
"H264",
"H265",
};

static inline uint32_t make_fps(uint32_t frame_interval)
{
return (frame_interval != 0) ? (10000000 / frame_interval) : 0;
}
#endif // UVC_PRINT_SUPPORTED_FORMATS


static const uvc_vs_input_header_desc_t *uvc_desc_get_streaming_input_header(const usb_config_desc_t *cfg_desc, uint8_t bInterfaceNumber)
{
UVC_CHECK(cfg_desc, NULL);
Expand Down Expand Up @@ -365,6 +385,21 @@ esp_err_t uvc_desc_get_streaming_interface_num(
}
*bcdUVC = vc_header_desc->bcdUVC;

#if (UVC_PRINT_SUPPORTED_FORMATS)
uvc_host_frame_info_t frames[20];
size_t size = 20;
for (int iface = 0; iface < vc_header_desc->bInCollection; iface++) {
ESP_ERROR_CHECK(uvc_desc_get_frame_list(cfg_desc, uvc_index, &frames, &size));
ESP_LOGW("UVC", "Supported frame formats:");
for (uint8_t i = 0; i < size; i++) {
ESP_LOGW("UVC", "\t%dx%d, %s, default FPS: %d",
frames[i].h_res, frames[i].v_res,
format_to_string[frames[i].format],
make_fps(frames[i].default_interval));
}
}
#endif // UVC_PRINT_SUPPORTED_FORMATS

// Find video streaming interface that offers the requested format
for (int streaming_if = 0; streaming_if < vc_header_desc->bInCollection; streaming_if++) {
uint8_t current_bInterfaceNumber = vc_header_desc->baInterfaceNr[streaming_if];
Expand All @@ -374,6 +409,7 @@ esp_err_t uvc_desc_get_streaming_interface_num(
break;
}
}

return ret;
}

Expand Down Expand Up @@ -454,7 +490,7 @@ esp_err_t uvc_desc_get_frame_list(const usb_config_desc_t *config_desc, uint8_t
frame_info->interval_max = this_frame->mjpeg_uncompressed.dwMaxFrameInterval;
frame_info->interval_step = this_frame->mjpeg_uncompressed.dwFrameIntervalStep;
} else {
for (int i = 0; i < CONFIG_UVC_INTERVAL_ARRAY_SIZE; i ++) {
for (int i = 0; i < UVC_HOST_INTERVAL_ARRAY_SIZE; i ++) {
frame_info->interval[i] = this_frame->mjpeg_uncompressed.dwFrameInterval[i];
}
}
Expand All @@ -468,7 +504,7 @@ esp_err_t uvc_desc_get_frame_list(const usb_config_desc_t *config_desc, uint8_t
frame_info->interval_max = this_frame->frame_based.dwMaxFrameInterval;
frame_info->interval_step = this_frame->frame_based.dwFrameIntervalStep;
} else {
for (int i = 0; i < CONFIG_UVC_INTERVAL_ARRAY_SIZE; i ++) {
for (int i = 0; i < UVC_HOST_INTERVAL_ARRAY_SIZE; i ++) {
frame_info->interval[i] = this_frame->frame_based.dwFrameInterval[i];
}
}
Expand Down
10 changes: 6 additions & 4 deletions host/class/uvc/usb_host_uvc/uvc_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@
#include "freertos/queue.h"
#include "freertos/event_groups.h"

#include "sdkconfig.h"

static const char *TAG = "uvc";

#define UVC_HOST_PRINT_CONFIG_DESCRIPTOR CONFIG_UVC_HOST_PRINT_CONFIG_DESCRIPTOR

// UVC spinlock
portMUX_TYPE uvc_lock = portMUX_INITIALIZER_UNLOCKED;

Expand Down Expand Up @@ -120,9 +124,9 @@ static esp_err_t uvc_host_device_connected(uint8_t addr)

// Create UAC interfaces list in RAM, connected to the particular USB dev
if (is_uvc_device) {
#ifdef CONFIG_PRINTF_UVC_CONFIGURATION_DESCRIPTOR
#if (UVC_HOST_PRINT_CONFIG_DESCRIPTOR)
usb_print_config_descriptor(config_desc, &uvc_print_desc);
#endif
#endif // UVC_HOST_PRINT_CONFIG_DESCRIPTOR
// Create Interfaces list for a possibility to claim Interface
ESP_RETURN_ON_ERROR(uvc_host_interface_check(addr, config_desc), TAG, "uvc stream interface not found");
} else {
Expand Down Expand Up @@ -356,7 +360,6 @@ static esp_err_t uvc_find_and_open_usb_device(uint8_t dev_addr, uint16_t vid, ui
if ((vid == device_desc->idVendor || vid == UVC_HOST_ANY_VID) &&
(pid == device_desc->idProduct || pid == UVC_HOST_ANY_PID) &&
(dev_addr == dev_info.dev_addr || dev_addr == UVC_HOST_ANY_DEV_ADDR)) {
// Return path 1: t
(*dev)->constant.dev_hdl = uvc_stream->constant.dev_hdl;
return ESP_OK;
}
Expand Down Expand Up @@ -394,7 +397,6 @@ static esp_err_t uvc_find_and_open_usb_device(uint8_t dev_addr, uint16_t vid, ui
if ((vid == device_desc->idVendor || vid == UVC_HOST_ANY_VID) &&
(pid == device_desc->idProduct || pid == UVC_HOST_ANY_PID) &&
(dev_addr == dev_addr_list[i] || dev_addr == UVC_HOST_ANY_DEV_ADDR)) {
// Return path 2:
(*dev)->constant.dev_hdl = current_device;
return ESP_OK;
}
Expand Down
Loading