Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -38,15 +38,14 @@ esp_err_t uvc_desc_get_streaming_interface_num(
/**
* @brief Get Streaming Interface and Endpoint descriptors
*
* We go through all alternate interfaces and pick the one that offers endpoint with MPS that:
* * Is lower than or equal to dwMaxPayloadTransferSize
* * Has as few as possible extra transactions per microframe (HS only)
* Bulk: We expect only one alternate interface with one BULK IN endpoint.
*
* @note The caller is responsible for dwMaxPayloadTransferSize fitting in the IN FIFO
* Isoc: We go through all alternate interfaces and pick the one that offers endpoint with
* interval, MPS and multiplier (HS only) that is best suited for the requested bandwidth.
*
* @param[in] cfg_desc Configuration descriptor
* @param[in] bInterfaceNumber Index of Streaming interface
* @param[in] dwMaxPayloadTransferSize Maximum requested MPS
* @param[in] requested_bandwidth Minimum bandwidth that the endpoint should support (in bytes per second)
* @param[out] intf_desc_ret Interface descriptor
* @param[out] ep_desc_ret Endpoint descriptor
* @return
Expand All @@ -57,7 +56,7 @@ esp_err_t uvc_desc_get_streaming_interface_num(
esp_err_t uvc_desc_get_streaming_intf_and_ep(
const usb_config_desc_t *cfg_desc,
uint8_t bInterfaceNumber,
uint16_t dwMaxPayloadTransferSize,
int requested_bandwidth,
const usb_intf_desc_t **intf_desc_ret,
const usb_ep_desc_t **ep_desc_ret);

Expand Down
7 changes: 5 additions & 2 deletions host/class/uvc/usb_host_uvc/private_include/uvc_frame_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ extern "C" {
/**
* @brief Allocate frame buffers for UVC stream
*
* In case fb_size is 0, format negotiation (probe) must be done before calling this function,
* because the frame size is taken from the negotiated format.
*
* @param[in] uvc_stream UVC stream handle
* @param[in] nb_of_fb Number of frame buffers to allocate
* @param[in] fb_size Size of 1 frame buffer in bytes
* @param[in] fb_caps Memory capabilities of memory for frame buffers
* @param[in] fb_size Size of 1 frame buffer in bytes, can be 0 for default
* @param[in] fb_caps Memory capabilities of memory for frame buffers, can be 0 for MALLOC_CAP_DEFAULT
* @return
* - ESP_OK: Success
* - ESP_ERR_NO_MEM: Not enough memory for frame buffers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

// @todo fix the hard-coded number here: Should be taken from HAL FIFO config in future versions of esp-idf
#if (CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_LINUX)
#define MAX_MPS_IN 4096
#define MAX_MPS_IN 4096 // Theoretically maximum 3 isochronous transaction per microframe, 3072 bytes
#else
// If FIFO is configured for bias IN, we have 608 bytes available.
// However, configuring MPS > 596 causes USB transfer failures,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct uvc_host_stream_s {
uint8_t bInterfaceNumber; // USB Video Streaming interface claimed by this stream. Needed for ISOC Stream start and CTRL transfers
uint8_t bAlternateSetting; // Alternate setting for selected interface. Needed for ISOC Stream start
uint8_t bEndpointAddress; // Streaming endpoint address. Needed for BULK Stream stop
const usb_config_desc_t *cfg_desc; // Configuration descriptor of the device. Cached for faster access

// USB host related members
usb_device_handle_t dev_hdl; // USB device handle
Expand Down
6 changes: 2 additions & 4 deletions host/class/uvc/usb_host_uvc/uvc_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ static esp_err_t uvc_host_stream_control(uvc_host_stream_hdl_t stream_hdl, uvc_v
uvc_stream_t *uvc_stream = (uvc_stream_t *)stream_hdl;
uint8_t bmRequestType, bRequest;
uint16_t wValue, wIndex, wLength;
const usb_config_desc_t *cfg_desc;
ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(uvc_stream->constant.dev_hdl, &cfg_desc));
esp_err_t ret = ESP_OK;
const bool set = (req_code == UVC_SET_CUR) ? true : false;

Expand All @@ -56,7 +54,7 @@ static esp_err_t uvc_host_stream_control(uvc_host_stream_hdl_t stream_hdl, uvc_v
const uvc_frame_desc_t *frame_desc;

ESP_RETURN_ON_ERROR(
uvc_desc_get_frame_format_by_format(cfg_desc, uvc_stream->constant.bInterfaceNumber, vs_format, &format_desc, &frame_desc),
uvc_desc_get_frame_format_by_format(uvc_stream->constant.cfg_desc, uvc_stream->constant.bInterfaceNumber, vs_format, &format_desc, &frame_desc),
TAG, "Could not find format that matches required format");
UVC_CHECK(format_desc && frame_desc, ESP_ERR_NOT_FOUND);

Expand Down Expand Up @@ -92,7 +90,7 @@ static esp_err_t uvc_host_stream_control(uvc_host_stream_hdl_t stream_hdl, uvc_v
const uvc_format_desc_t *format_desc = NULL;
const uvc_frame_desc_t *frame_desc = NULL;
ESP_RETURN_ON_ERROR(
uvc_desc_get_frame_format_by_index(cfg_desc, uvc_stream->constant.bInterfaceNumber, vs_control->bFormatIndex, vs_control->bFrameIndex, &format_desc, &frame_desc),
uvc_desc_get_frame_format_by_index(uvc_stream->constant.cfg_desc, uvc_stream->constant.bInterfaceNumber, vs_control->bFormatIndex, vs_control->bFrameIndex, &format_desc, &frame_desc),
TAG, "Could not find requested frame format");

vs_format->format = uvc_desc_parse_format(format_desc);
Expand Down
9 changes: 7 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 @@ -11,6 +11,7 @@
#include "usb/uvc_host.h"
#include "uvc_check_priv.h"
#include "uvc_descriptors_priv.h"
#include "uvc_idf_version_priv.h"

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

Expand All @@ -36,7 +37,7 @@ static const uvc_vs_input_header_desc_t *uvc_desc_get_streaming_input_header(con
esp_err_t uvc_desc_get_streaming_intf_and_ep(
const usb_config_desc_t *cfg_desc,
uint8_t bInterfaceNumber,
uint16_t dwMaxPayloadTransferSize,
int requested_bandwidth,
const usb_intf_desc_t **intf_desc_ret,
const usb_ep_desc_t **ep_desc_ret)
{
Expand All @@ -50,6 +51,10 @@ esp_err_t uvc_desc_get_streaming_intf_and_ep(
const uint8_t num_of_alternate = usb_parse_interface_number_of_alternate(cfg_desc, bInterfaceNumber);
uint16_t last_mps = 0; // Looking for maximum MPS: init to zero
uint8_t last_mult = UINT8_MAX; // Looking for minimum: init to max

/* Number of alternate interfaces will be 0 for BULK cameras
* that is why in the for loop below we go from 0 to num_of_alternate **inclusive**
*/
for (int i = 0; i <= num_of_alternate; i++) {
// Check Interface desc
intf_desc = usb_parse_interface_descriptor(cfg_desc, bInterfaceNumber, i, &offset);
Expand All @@ -69,7 +74,7 @@ esp_err_t uvc_desc_get_streaming_intf_and_ep(
// and that is not bigger that max. requests MPS
const uint16_t current_mps = USB_EP_DESC_GET_MPS(ep_desc);
const uint8_t current_mult = USB_EP_DESC_GET_MULT(ep_desc);
if (current_mps >= last_mps && current_mult <= last_mult && current_mps <= dwMaxPayloadTransferSize) {
if (current_mps >= last_mps && current_mult <= last_mult && current_mps <= MAX_MPS_IN) {
last_mps = current_mps;
last_mult = current_mult;
*ep_desc_ret = ep_desc;
Expand Down
6 changes: 2 additions & 4 deletions host/class/uvc/usb_host_uvc/uvc_descriptor_printing.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,9 @@ void uvc_host_desc_print(uvc_host_stream_hdl_t stream_hdl)
{
assert(stream_hdl);
uvc_stream_t *uvc_stream = (uvc_stream_t *)stream_hdl;

const usb_device_desc_t *device_desc;
const usb_config_desc_t *config_desc;

ESP_ERROR_CHECK_WITHOUT_ABORT(usb_host_get_device_descriptor(uvc_stream->constant.dev_hdl, &device_desc));
ESP_ERROR_CHECK_WITHOUT_ABORT(usb_host_get_active_config_descriptor(uvc_stream->constant.dev_hdl, &config_desc));
usb_print_device_descriptor(device_desc);
usb_print_config_descriptor(config_desc, &uvc_print_desc);
usb_print_config_descriptor(uvc_stream->constant.cfg_desc, &uvc_print_desc);
}
12 changes: 9 additions & 3 deletions host/class/uvc/usb_host_uvc/uvc_frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "uvc_frame_priv.h"
#include "uvc_types_priv.h"
#include "uvc_check_priv.h"
#include "uvc_critical_priv.h"

#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
Expand All @@ -35,15 +36,20 @@ esp_err_t uvc_frame_allocate(uvc_stream_t *uvc_stream, int nb_of_fb, size_t fb_s
UVC_CHECK(uvc_stream, ESP_ERR_INVALID_ARG);
esp_err_t ret;

// In case the user did not fill the config, set it to default
if (fb_size == 0) {
fb_size = UVC_ATOMIC_LOAD(uvc_stream->dynamic.dwMaxVideoFrameSize);
}
if (fb_caps == 0) {
fb_caps = MALLOC_CAP_DEFAULT;
}

// We will be passing the frame buffers by reference
uvc_stream->constant.empty_fb_queue = xQueueCreate(nb_of_fb, sizeof(uvc_host_frame_t *));
UVC_CHECK(uvc_stream->constant.empty_fb_queue, ESP_ERR_NO_MEM);
for (int i = 0; i < nb_of_fb; i++) {
// Allocate the frame buffer
uvc_host_frame_t *this_fb = malloc(sizeof(uvc_host_frame_t));
if (fb_caps == 0) {
fb_caps = MALLOC_CAP_DEFAULT; // In case the user did not fill the config, set it to default
}
uint8_t *this_data = heap_caps_malloc(fb_size, fb_caps);
if (this_data == NULL || this_fb == NULL) {
free(this_fb);
Expand Down
Loading
Loading