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
8 changes: 7 additions & 1 deletion device/esp_tinyusb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,17 @@ if(CONFIG_TINYUSB_NET_MODE_NCM)
)
endif() # CONFIG_TINYUSB_NET_MODE_NCM

if(CONFIG_TINYUSB_UVC_ENABLED)
list(APPEND srcs
"tinyusb_uvc.c"
)
endif() # CONFIG_TINYUSB_UVC_ENABLED

idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "include"
PRIV_INCLUDE_DIRS "include_private"
PRIV_REQUIRES ${priv_req}
REQUIRES fatfs vfs
REQUIRES fatfs vfs esp_timer
)

# Determine whether tinyusb is fetched from component registry or from local path
Expand Down
231 changes: 231 additions & 0 deletions device/esp_tinyusb/Kconfig → device/esp_tinyusb/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,237 @@ menu "TinyUSB Stack"
BTH ISO ALT COUNT.
endmenu # "Bluetooth Host Device Class"

menu "USB Video Class (UVC)"
config TINYUSB_UVC_ENABLED
bool "Enable TinyUSB UVC feature"
default n
help
Enable TinyUSB UVC (USB Video Class) feature for webcam devices.

config TINYUSB_DESC_UVC_STRING
depends on TINYUSB_UVC_ENABLED
string "UVC Device String"
default "Espressif UVC Camera"
help
Name of the UVC device.

config TINYUSB_UVC_SUPPORT_TWO_CAM
depends on TINYUSB_UVC_ENABLED
bool "Support two cameras"
default n
help
Enable support for two independent UVC camera interfaces.

config TINYUSB_UVC_CAM1_FRAMERATE
depends on TINYUSB_UVC_ENABLED
int "Camera 1 Frame Rate (fps)"
default 15
range 1 60
help
Frame rate for camera 1 in frames per second.

config TINYUSB_UVC_CAM1_FRAMESIZE_WIDTH
depends on TINYUSB_UVC_ENABLED
int "Camera 1 Frame Width"
default 640
help
Frame width for camera 1 in pixels.

config TINYUSB_UVC_CAM1_FRAMESIZE_HEIGHT
depends on TINYUSB_UVC_ENABLED
int "Camera 1 Frame Height"
default 480
help
Frame height for camera 1 in pixels.

choice TINYUSB_UVC_CAM1_FORMAT
depends on TINYUSB_UVC_ENABLED
prompt "Camera 1 Video Format"
default TINYUSB_UVC_FORMAT_MJPEG_CAM1
help
Select video format for camera 1.

config TINYUSB_UVC_FORMAT_MJPEG_CAM1
bool "MJPEG"
config TINYUSB_UVC_FORMAT_H264_CAM1
bool "H264"
endchoice

config TINYUSB_UVC_CAM1_MULTI_FRAMESIZE
depends on TINYUSB_UVC_ENABLED
bool "Enable multiple frame sizes for Camera 1"
default n
help
Enable support for multiple frame sizes (VGA, HVGA, etc.).

config TINYUSB_UVC_CAM1_BULK_MODE
depends on TINYUSB_UVC_ENABLED
bool "Use Bulk mode for Camera 1"
default n
help
Use Bulk transfer mode instead of Isochronous for Camera 1.

config TINYUSB_UVC_CAM2_FRAMERATE
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
int "Camera 2 Frame Rate (fps)"
default 15
range 1 60
help
Frame rate for camera 2 in frames per second.

config TINYUSB_UVC_CAM2_FRAMESIZE_WIDTH
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
int "Camera 2 Frame Width"
default 640
help
Frame width for camera 2 in pixels.

config TINYUSB_UVC_CAM2_FRAMESIZE_HEIGHT
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
int "Camera 2 Frame Height"
default 480
help
Frame height for camera 2 in pixels.

choice TINYUSB_UVC_CAM2_FORMAT
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
prompt "Camera 2 Video Format"
default TINYUSB_UVC_FORMAT_MJPEG_CAM2
help
Select video format for camera 2.

config TINYUSB_UVC_FORMAT_MJPEG_CAM2
bool "MJPEG"
config TINYUSB_UVC_FORMAT_H264_CAM2
bool "H264"
endchoice

config TINYUSB_UVC_CAM2_MULTI_FRAMESIZE
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
bool "Enable multiple frame sizes for Camera 2"
default n
help
Enable support for multiple frame sizes (VGA, HVGA, etc.).

config TINYUSB_UVC_CAM2_BULK_MODE
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
bool "Use Bulk mode for Camera 2"
default n
help
Use Bulk transfer mode instead of Isochronous for Camera 2.

config TINYUSB_UVC_MULTI_FRAME_WIDTH_1
depends on TINYUSB_UVC_ENABLED
int "Multi-frame Width 1"
default 640
help
Additional frame size width 1.

config TINYUSB_UVC_MULTI_FRAME_HEIGHT_1
depends on TINYUSB_UVC_ENABLED
int "Multi-frame Height 1"
default 480
help
Additional frame size height 1.

config TINYUSB_UVC_MULTI_FRAME_FPS_1
depends on TINYUSB_UVC_ENABLED
int "Multi-frame FPS 1"
default 15
help
Additional frame rate 1.

config TINYUSB_UVC_MULTI_FRAME_WIDTH_2
depends on TINYUSB_UVC_ENABLED
int "Multi-frame Width 2"
default 320
help
Additional frame size width 2.

config TINYUSB_UVC_MULTI_FRAME_HEIGHT_2
depends on TINYUSB_UVC_ENABLED
int "Multi-frame Height 2"
default 240
help
Additional frame size height 2.

config TINYUSB_UVC_MULTI_FRAME_FPS_2
depends on TINYUSB_UVC_ENABLED
int "Multi-frame FPS 2"
default 15
help
Additional frame rate 2.

config TINYUSB_UVC_MULTI_FRAME_WIDTH_3
depends on TINYUSB_UVC_ENABLED
int "Multi-frame Width 3"
default 160
help
Additional frame size width 3.

config TINYUSB_UVC_MULTI_FRAME_HEIGHT_3
depends on TINYUSB_UVC_ENABLED
int "Multi-frame Height 3"
default 120
help
Additional frame size height 3.

config TINYUSB_UVC_MULTI_FRAME_FPS_3
depends on TINYUSB_UVC_ENABLED
int "Multi-frame FPS 3"
default 15
help
Additional frame rate 3.

config TINYUSB_UVC_CAM1_TASK_PRIORITY
depends on TINYUSB_UVC_ENABLED
int "Camera 1 Task Priority"
default 5
range 1 25
help
Priority of the Camera 1 task.

config TINYUSB_UVC_CAM1_TASK_CORE
depends on TINYUSB_UVC_ENABLED
int "Camera 1 Task Core (-1 for any)"
default -1
range -1 1
help
Core affinity for Camera 1 task. -1 for no affinity.

config TINYUSB_UVC_CAM2_TASK_PRIORITY
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
int "Camera 2 Task Priority"
default 5
range 1 25
help
Priority of the Camera 2 task.

config TINYUSB_UVC_CAM2_TASK_CORE
depends on TINYUSB_UVC_ENABLED && TINYUSB_UVC_SUPPORT_TWO_CAM
int "Camera 2 Task Core (-1 for any)"
default -1
range -1 1
help
Core affinity for Camera 2 task. -1 for no affinity.

config TINYUSB_UVC_TINYUSB_TASK_PRIORITY
depends on TINYUSB_UVC_ENABLED
int "TinyUSB Task Priority"
default 5
range 1 25
help
Priority of the TinyUSB task for UVC.

config TINYUSB_UVC_TINYUSB_TASK_CORE
depends on TINYUSB_UVC_ENABLED
int "TinyUSB Task Core (-1 for any)"
default -1
range -1 1
help
Core affinity for TinyUSB task. -1 for no affinity.
endmenu # "USB Video Class (UVC)"

menu "Network driver (ECM/NCM/RNDIS)"
choice TINYUSB_NET_MODE
prompt "Network mode"
Expand Down
8 changes: 4 additions & 4 deletions device/esp_tinyusb/descriptors_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ esp_err_t tinyusb_descriptors_set(tinyusb_port_t port, const tinyusb_desc_config

// Full-speed configuration descriptor
if (config->full_speed_config == NULL) {
#if (CFG_TUD_CDC > 0 || CFG_TUD_MSC > 0 || CFG_TUD_NCM > 0)
// We provide default config descriptors only for CDC, MSC and NCM classes
#if (CFG_TUD_CDC > 0 || CFG_TUD_MSC > 0 || CFG_TUD_NCM > 0 || CFG_TUD_VIDEO > 0)
// We provide default config descriptors only for CDC, MSC, NCM and VIDEO classes
ESP_LOGW(TAG, "No Full-speed configuration descriptor provided, using default.");
s_desc_cfg.fs_cfg = descriptor_fs_cfg_default;
#else
Expand All @@ -208,8 +208,8 @@ esp_err_t tinyusb_descriptors_set(tinyusb_port_t port, const tinyusb_desc_config
if (port == TINYUSB_PORT_HIGH_SPEED_0) {
#if (TUD_OPT_HIGH_SPEED)
if (config->high_speed_config == NULL) {
#if (CFG_TUD_CDC > 0 || CFG_TUD_MSC > 0 || CFG_TUD_NCM > 0)
// We provide default config descriptors only for CDC, MSC and NCM classes
#if (CFG_TUD_CDC > 0 || CFG_TUD_MSC > 0 || CFG_TUD_NCM > 0 || CFG_TUD_VIDEO > 0)
// We provide default config descriptors only for CDC, MSC, NCM and VIDEO classes
ESP_LOGW(TAG, "No High-speed configuration descriptor provided, using default.");
s_desc_cfg.hs_cfg = descriptor_hs_cfg_default;
#else
Expand Down
114 changes: 114 additions & 0 deletions device/esp_tinyusb/include/tinyusb_uvc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
* 2026 Daniel Kampert (DanielKampert@Kampis-Elektroecke.de)
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <esp_err.h>

#include <stdint.h>
#include <stdbool.h>

#include <sdkconfig.h>

#if (CONFIG_TINYUSB_UVC_ENABLED != 1)
#error "TinyUSB UVC driver must be enabled in menuconfig"
#endif

/** @brief UVC camera interfaces available.
*/
typedef enum {
TINYUSB_UVC_ITF_0 = 0,
#if CONFIG_TINYUSB_UVC_SUPPORT_TWO_CAM
TINYUSB_UVC_ITF_1,
#endif
TINYUSB_UVC_ITF_MAX
} tinyusb_uvc_itf_t;

/** @brief Types of UVC events.
*/
typedef enum {
UVC_EVENT_FRAME_START, /*!< Frame transmission started */
UVC_EVENT_FRAME_END, /*!< Frame transmission ended */
UVC_EVENT_STREAMING_START, /*!< Streaming started by host */
UVC_EVENT_STREAMING_STOP, /*!< Streaming stopped by host */
} uvc_event_type_t;

/** @brief Describes an event passing to the input of a callback
*/
typedef struct {
uvc_event_type_t type; /*!< Event type */
} uvc_event_t;

/** @brief UVC callback type
*/
typedef void(*tusb_uvc_callback_t)(int itf, uvc_event_t *event);

/** @brief Callback for frame buffer request.
* @param itf Interface number
* @param buffer Pointer to store the frame buffer address
* @param buffer_size Pointer to store the frame buffer size
* @return true if buffer is available, false otherwise
*/
typedef bool(*tusb_uvc_fb_request_cb_t)(int itf, uint8_t **buffer, size_t *buffer_size);

/** @brief Callback for frame buffer return.
* @param itf Interface number
* @param buffer Frame buffer address
*/
typedef void(*tusb_uvc_fb_return_cb_t)(int itf, uint8_t *buffer);

/** @brief Callback for stop notification.
* @param itf Interface number
*/
typedef void(*tusb_uvc_stop_cb_t)(int itf);

/** @brief Configuration structure for UVC.
*/
typedef struct {
tinyusb_uvc_itf_t uvc_port; /*!< UVC interface number */
tusb_uvc_callback_t callback_streaming_start; /*!< Streaming start callback */
tusb_uvc_callback_t callback_streaming_stop; /*!< Streaming stop callback */
tusb_uvc_fb_request_cb_t fb_request_cb; /*!< Frame buffer request callback */
tusb_uvc_fb_return_cb_t fb_return_cb; /*!< Frame buffer return callback */
tusb_uvc_stop_cb_t stop_cb; /*!< Stop callback */
const uint8_t *uvc_buffer; /*!< UVC working buffer (read-only) */
size_t uvc_buffer_size; /*!< UVC buffer size */
} tinyusb_config_uvc_t;

/** @brief Initialize UVC interface.
* @param cfg Configuration structure
* @return ESP_OK on success
*/
esp_err_t tinyusb_uvc_init(const tinyusb_config_uvc_t *cfg);

/** @brief Deinitialize UVC interface.
* @param itf Interface number
* @return ESP_OK on success
*/
esp_err_t tinyusb_uvc_deinit(tinyusb_uvc_itf_t itf);

/** @brief Check if UVC streaming is active.
* @param itf Interface number
* @return true if streaming is active
*/
bool tinyusb_uvc_streaming_active(tinyusb_uvc_itf_t itf);

/** @brief Transmit a video frame.
* @param itf Interface number
* @param frame Frame buffer
* @param len Frame length
* @return ESP_OK on success
*/
esp_err_t tinyusb_uvc_transmit_frame(tinyusb_uvc_itf_t itf, uint8_t *frame, size_t len);

#ifdef __cplusplus
}
#endif
Loading