mirror of
https://github.com/MrUnknownDE/OpenIris-ESPIDF.git
synced 2026-04-16 21:13:44 +02:00
Add support for setting a custom device name and per-board serial number for UVC
This commit is contained in:
@@ -3,6 +3,30 @@ constexpr int UVC_MAX_FRAMESIZE_SIZE(75 * 1024);
|
||||
|
||||
static const char *UVC_STREAM_TAG = "[UVC DEVICE]";
|
||||
|
||||
extern "C" {
|
||||
static char serial_number_str[13];
|
||||
|
||||
const char *get_uvc_device_name() {
|
||||
return deviceConfig->getMDNSConfig().hostname.c_str();
|
||||
}
|
||||
|
||||
const char *get_serial_number(void) {
|
||||
if (serial_number_str[0] == '\0') {
|
||||
uint8_t mac_address[6];
|
||||
esp_err_t result = esp_efuse_mac_get_default(mac_address);
|
||||
if (result != ESP_OK) {
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Failed to get MAC address of the board, returning default serial number");
|
||||
return CONFIG_TUSB_SERIAL_NUM;
|
||||
}
|
||||
|
||||
sniprintf(serial_number_str, sizeof(serial_number_str), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]
|
||||
);
|
||||
}
|
||||
return serial_number_str;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t UVCStreamHelpers::camera_start_cb(uvc_format_t format, int width, int height, int rate, void *cb_ctx)
|
||||
{
|
||||
(void)cb_ctx;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifndef UVCSTREAM_HPP
|
||||
#define UVCSTREAM_HPP
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_camera.h"
|
||||
#include <CameraManager.hpp>
|
||||
#include <StateManager.hpp>
|
||||
@@ -13,6 +14,18 @@
|
||||
// we need access to the camera manager
|
||||
// in order to update the frame settings
|
||||
extern std::shared_ptr<CameraManager> cameraHandler;
|
||||
extern std::shared_ptr<ProjectConfig> deviceConfig;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char *get_uvc_device_name();
|
||||
const char *get_serial_number(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// we also need a way to inform the rest of the system of what's happening
|
||||
extern QueueHandle_t eventQueue;
|
||||
|
||||
11
components/usb_device_uvc/CMakeLists.txt
Normal file
11
components/usb_device_uvc/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
idf_component_register(SRCS usb_device_uvc.c
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES usb esp_timer)
|
||||
|
||||
idf_component_get_property(tusb_lib espressif__tinyusb COMPONENT_LIB)
|
||||
|
||||
target_include_directories(${tusb_lib} PUBLIC "${COMPONENT_DIR}/tusb")
|
||||
target_sources(${tusb_lib} PUBLIC "${COMPONENT_DIR}/tusb/usb_descriptors.c")
|
||||
|
||||
include(package_manager)
|
||||
cu_pkg_define_version(${CMAKE_CURRENT_LIST_DIR})
|
||||
265
components/usb_device_uvc/Kconfig
Normal file
265
components/usb_device_uvc/Kconfig
Normal file
@@ -0,0 +1,265 @@
|
||||
menu "USB Device UVC"
|
||||
|
||||
config TUSB_VID
|
||||
hex "USB Device VID"
|
||||
default 0x303A
|
||||
config TUSB_PID
|
||||
hex "USB Device PID"
|
||||
default 0x8000
|
||||
config TUSB_MANUFACTURER
|
||||
string "USB Device Manufacture"
|
||||
default "Espressif"
|
||||
config TUSB_PRODUCT
|
||||
string "Product Name"
|
||||
default "ESP UVC Device"
|
||||
config TUSB_SERIAL_NUM
|
||||
string "Product ID"
|
||||
default "12345678"
|
||||
|
||||
config UVC_SUPPORT_TWO_CAM
|
||||
bool "Support two cameras"
|
||||
default n
|
||||
help
|
||||
If enable, support two cameras
|
||||
|
||||
choice TINYUSB_RHPORT
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
prompt "TinyUSB PHY"
|
||||
default TINYUSB_RHPORT_HS
|
||||
help
|
||||
Allows set the USB PHY Controller for TinyUSB: HS (USB OTG2.0 PHY for HighSpeed)
|
||||
|
||||
config TINYUSB_RHPORT_HS
|
||||
bool "HS"
|
||||
endchoice
|
||||
|
||||
menu "USB Cam1 Config"
|
||||
|
||||
choice UVC_CAM1_FORMAT
|
||||
bool "UVC Cam1 Format"
|
||||
default FORMAT_MJPEG_CAM1
|
||||
config FORMAT_MJPEG_CAM1
|
||||
bool "MJPEG"
|
||||
config FORMAT_H264_CAM1
|
||||
bool "H264"
|
||||
config FORMAT_UNCOMPR_CAM1
|
||||
bool "uncompressed"
|
||||
endchoice
|
||||
|
||||
choice UVC_CAM1_XFER_MODE
|
||||
bool "UVC cam1 transfer mode"
|
||||
default UVC_MODE_ISOC_CAM1
|
||||
config UVC_MODE_ISOC_CAM1
|
||||
bool "Isochronous"
|
||||
config UVC_MODE_BULK_CAM1
|
||||
bool "Bulk"
|
||||
endchoice
|
||||
|
||||
choice UVC_CAM1_FRAMESIZE
|
||||
bool "UVC Default Resolution"
|
||||
default FRAMESIZE_HD
|
||||
config FRAMESIZE_QVGA
|
||||
bool "QVGA 320x240"
|
||||
config FRAMESIZE_HVGA
|
||||
bool "HVGA 480x320"
|
||||
config FRAMESIZE_VGA
|
||||
bool "VGA 640x480"
|
||||
config FRAMESIZE_SVGA
|
||||
bool "SVGA 800x600"
|
||||
config FRAMESIZE_HD
|
||||
bool "HD 1280x720"
|
||||
config FRAMESIZE_FHD
|
||||
bool "FHD 1920x1080"
|
||||
endchoice
|
||||
|
||||
config UVC_CAM1_FRAMERATE
|
||||
int "Frame Rate (FPS)"
|
||||
default 30 if FRAMESIZE_QVGA
|
||||
default 30 if FRAMESIZE_HVGA
|
||||
default 15 if FRAMESIZE_VGA
|
||||
default 15 if FRAMESIZE_SVGA
|
||||
default 15 if FRAMESIZE_HD
|
||||
default 15 if FRAMESIZE_FHD
|
||||
|
||||
config UVC_CAM1_FRAMESIZE_WIDTH
|
||||
int "Cam1 Frame Width"
|
||||
default 320 if FRAMESIZE_QVGA
|
||||
default 480 if FRAMESIZE_HVGA
|
||||
default 640 if FRAMESIZE_VGA
|
||||
default 800 if FRAMESIZE_SVGA
|
||||
default 1280 if FRAMESIZE_HD
|
||||
default 1920 if FRAMESIZE_FHD
|
||||
|
||||
config UVC_CAM1_FRAMESIZE_HEIGT
|
||||
int "Cam1 Frame Height"
|
||||
default 240 if FRAMESIZE_QVGA
|
||||
default 320 if FRAMESIZE_HVGA
|
||||
default 480 if FRAMESIZE_VGA
|
||||
default 600 if FRAMESIZE_SVGA
|
||||
default 720 if FRAMESIZE_HD
|
||||
default 1080 if FRAMESIZE_FHD
|
||||
|
||||
config UVC_CAM1_MULTI_FRAMESIZE
|
||||
bool "Enable cam1 multiple frames sizes"
|
||||
default y
|
||||
help
|
||||
If enable, add VGA and HVGA to list
|
||||
endmenu
|
||||
|
||||
menu "USB Cam2 Config"
|
||||
depends on UVC_SUPPORT_TWO_CAM
|
||||
|
||||
choice UVC_CAM2_FORMAT
|
||||
bool "UVC Cam2 Format"
|
||||
default FORMAT_MJPEG_CAM2
|
||||
config FORMAT_MJPEG_CAM2
|
||||
bool "MJPEG"
|
||||
config FORMAT_H264_CAM2
|
||||
bool "H264"
|
||||
config FORMAT_UNCOMPR_CAM2
|
||||
bool "uncompressed"
|
||||
endchoice
|
||||
|
||||
choice UVC_CAM2_XFER_MODE
|
||||
bool "UVC cam2 transfer mode"
|
||||
default UVC_MODE_ISOC_CAM2
|
||||
config UVC_MODE_ISOC_CAM2
|
||||
bool "Isochronous"
|
||||
config UVC_MODE_BULK_CAM2
|
||||
bool "Bulk"
|
||||
endchoice
|
||||
|
||||
choice UVC_CAM2_FRAMESIZE
|
||||
bool "UVC Default Resolution"
|
||||
default FRAMESIZE_HD_2
|
||||
config FRAMESIZE_QVGA_2
|
||||
bool "QVGA 320x240"
|
||||
config FRAMESIZE_HVGA_2
|
||||
bool "HVGA 480x320"
|
||||
config FRAMESIZE_VGA_2
|
||||
bool "VGA 640x480"
|
||||
config FRAMESIZE_SVGA_2
|
||||
bool "SVGA 800x600"
|
||||
config FRAMESIZE_HD_2
|
||||
bool "HD 1280x720"
|
||||
config FRAMESIZE_FHD_2
|
||||
bool "FHD 1920x1080"
|
||||
endchoice
|
||||
|
||||
config UVC_CAM2_FRAMERATE
|
||||
int "Frame Rate (FPS)"
|
||||
default 30 if FRAMESIZE_QVGA_2
|
||||
default 30 if FRAMESIZE_HVGA_2
|
||||
default 15 if FRAMESIZE_VGA_2
|
||||
default 15 if FRAMESIZE_SVGA_2
|
||||
default 15 if FRAMESIZE_HD_2
|
||||
default 15 if FRAMESIZE_FHD_2
|
||||
|
||||
config UVC_CAM2_FRAMESIZE_WIDTH
|
||||
int "Cam2 Frame Width"
|
||||
default 320 if FRAMESIZE_QVGA_2
|
||||
default 480 if FRAMESIZE_HVGA_2
|
||||
default 640 if FRAMESIZE_VGA_2
|
||||
default 800 if FRAMESIZE_SVGA_2
|
||||
default 1280 if FRAMESIZE_HD_2
|
||||
default 1920 if FRAMESIZE_FHD_2
|
||||
|
||||
config UVC_CAM2_FRAMESIZE_HEIGT
|
||||
int "Cam2 Frame Height"
|
||||
default 240 if FRAMESIZE_QVGA_2
|
||||
default 320 if FRAMESIZE_HVGA_2
|
||||
default 480 if FRAMESIZE_VGA_2
|
||||
default 600 if FRAMESIZE_SVGA_2
|
||||
default 720 if FRAMESIZE_HD_2
|
||||
default 1080 if FRAMESIZE_FHD_2
|
||||
|
||||
|
||||
config UVC_CAM2_MULTI_FRAMESIZE
|
||||
bool "Enable cam2 multiple frames sizes"
|
||||
default y
|
||||
help
|
||||
If enable, add VGA and HVGA to list
|
||||
|
||||
endmenu
|
||||
|
||||
menu "UVC_MULTI_FRAME_CONFIG"
|
||||
|
||||
menu "FRAME_SIZE_1"
|
||||
config UVC_MULTI_FRAME_WIDTH_1
|
||||
int "Enable Multi Frame Size 1"
|
||||
default 640
|
||||
|
||||
config UVC_MULTI_FRAME_HEIGHT_1
|
||||
int "Enable Multi Frame Size 1"
|
||||
default 480
|
||||
|
||||
config UVC_MULTI_FRAME_FPS_1
|
||||
int "Enable Multi Frame Size 1"
|
||||
default 15
|
||||
endmenu
|
||||
|
||||
menu "FRAME_SIZE_2"
|
||||
config UVC_MULTI_FRAME_WIDTH_2
|
||||
int "Enable Multi Frame Size 2"
|
||||
default 480
|
||||
|
||||
config UVC_MULTI_FRAME_HEIGHT_2
|
||||
int "Enable Multi Frame Size 2"
|
||||
default 320
|
||||
|
||||
config UVC_MULTI_FRAME_FPS_2
|
||||
int "Enable Multi Frame Size 2"
|
||||
default 30
|
||||
endmenu
|
||||
|
||||
menu "FRAME_SIZE_3"
|
||||
config UVC_MULTI_FRAME_WIDTH_3
|
||||
int "Enable Multi Frame Size 3"
|
||||
default 320
|
||||
|
||||
config UVC_MULTI_FRAME_HEIGHT_3
|
||||
int "Enable Multi Frame Size 3"
|
||||
default 240
|
||||
|
||||
config UVC_MULTI_FRAME_FPS_3
|
||||
int "Enable Multi Frame Size 3"
|
||||
default 30
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
menu "UVC Task Config"
|
||||
config UVC_TINYUSB_TASK_PRIORITY
|
||||
int "Tinyusb task priority"
|
||||
default 5
|
||||
range 1 15
|
||||
|
||||
config UVC_TINYUSB_TASK_CORE
|
||||
int "Tinyusb task core"
|
||||
default -1
|
||||
range -1 1
|
||||
|
||||
config UVC_CAM1_TASK_PRIORITY
|
||||
int "Cam1 task priority"
|
||||
default 4
|
||||
range 1 15
|
||||
|
||||
config UVC_CAM1_TASK_CORE
|
||||
int "Cam1 task core"
|
||||
default -1
|
||||
range -1 1
|
||||
|
||||
config UVC_CAM2_TASK_PRIORITY
|
||||
int "Cam2 task priority"
|
||||
default 4
|
||||
range 1 15
|
||||
depends on UVC_SUPPORT_TWO_CAM
|
||||
|
||||
config UVC_CAM2_TASK_CORE
|
||||
int "Cam2 task core"
|
||||
default -1
|
||||
range -1 1
|
||||
depends on UVC_SUPPORT_TWO_CAM
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
23
components/usb_device_uvc/README.md
Normal file
23
components/usb_device_uvc/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
[](https://components.espressif.com/components/espressif/usb_device_uvc)
|
||||
# NOTE. This is a modified version of the original esp-idf component, suited to our needs.
|
||||
## USB Device UVC Component
|
||||
|
||||
`usb_device_uvc` is a USB `UVC` device driver for ESP32-S2/ESP32-S3, which supports streaming JPEG frames to the USB Host. User can wrapper the Camera or any devices as a UVC standard device through the callback functions.
|
||||
|
||||
Features:
|
||||
|
||||
1. Support video stream through the UVC Stream interface
|
||||
2. Support both isochronous and bulk mode
|
||||
2. Support multiple resolutions and frame rates
|
||||
|
||||
### Add component to your project
|
||||
|
||||
Please use the component manager command `add-dependency` to add the `usb_device_uvc` to your project's dependency, during the `CMake` step the component will be downloaded automatically
|
||||
|
||||
```
|
||||
idf.py add-dependency "espressif/usb_device_uvc=*"
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
* [USB WebCamera: Make ESP32-S3-EYE as a USB Camera Device](https://github.com/espressif/esp-iot-solution/tree/master/examples/usb/device/usb_webcam)
|
||||
20
components/usb_device_uvc/idf_component.yml
Normal file
20
components/usb_device_uvc/idf_component.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
dependencies:
|
||||
cmake_utilities:
|
||||
version: '*'
|
||||
espressif/tinyusb:
|
||||
version: '>=0.15.0~10'
|
||||
idf:
|
||||
version: '>=5.0'
|
||||
description: USB Device UVC, Streaming Video to Host
|
||||
documentation: https://docs.espressif.com/projects/esp-iot-solution/en/latest/usb/usb_device/usb_device_uvc.html
|
||||
issues: https://github.com/espressif/esp-iot-solution/issues
|
||||
repository: git://github.com/espressif/esp-iot-solution.git
|
||||
repository_info:
|
||||
commit_sha: e2529ce3b0aa6362663b4c53d7e9ba21ff307f49
|
||||
path: components/usb/usb_device_uvc
|
||||
targets:
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
url: https://github.com/espressif/esp-iot-solution/tree/master/components/usb/usb_device_uvc
|
||||
version: 1.1.0
|
||||
100
components/usb_device_uvc/include/usb_device_uvc.h
Normal file
100
components/usb_device_uvc/include/usb_device_uvc.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UVC format
|
||||
*/
|
||||
typedef enum {
|
||||
UVC_FORMAT_JPEG, /*!< JPEG format */
|
||||
UVC_FORMAT_H264, /*!< H264 format */
|
||||
} uvc_format_t;
|
||||
|
||||
/**
|
||||
* @brief Frame buffer structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t *buf; /*!< Pointer to the frame data */
|
||||
size_t len; /*!< Length of the buffer in bytes */
|
||||
size_t width; /*!< Width of the image frame in pixels */
|
||||
size_t height; /*!< Height of the image frame in pixels */
|
||||
uvc_format_t format; /*!< Format of the frame data */
|
||||
struct timeval timestamp; /*!< Timestamp since boot of the frame */
|
||||
} uvc_fb_t;
|
||||
|
||||
/**
|
||||
* @brief type of callback function when host open the UVC device
|
||||
*/
|
||||
typedef esp_err_t (*uvc_input_start_cb_t)(uvc_format_t format, int width, int height, int rate, void *cb_ctx);
|
||||
|
||||
/**
|
||||
* @brief type of callback function when host request a new frame buffer
|
||||
*/
|
||||
typedef uvc_fb_t* (*uvc_input_fb_get_cb_t)(void *cb_ctx);
|
||||
|
||||
/**
|
||||
* @brief type of callback function when the frame buffer is no longer used
|
||||
*/
|
||||
typedef void (*uvc_input_fb_return_cb_t)(uvc_fb_t *fb, void *cb_ctx);
|
||||
|
||||
/**
|
||||
* @brief type of callback function when host close the UVC device
|
||||
*/
|
||||
typedef void (*uvc_input_stop_cb_t)(void *cb_ctx);
|
||||
|
||||
/**
|
||||
* @brief Configuration for the UVC device
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t *uvc_buffer; /*!< UVC transfer buffer */
|
||||
uint32_t uvc_buffer_size; /*!< UVC transfer buffer size, should bigger than one frame size */
|
||||
uvc_input_start_cb_t start_cb; /*!< callback function of host open the UVC device with the specific format and resolution */
|
||||
uvc_input_fb_get_cb_t fb_get_cb; /*!< callback function of host request a new frame buffer */
|
||||
uvc_input_fb_return_cb_t fb_return_cb; /*!< callback function of the frame buffer is no longer used */
|
||||
uvc_input_stop_cb_t stop_cb; /*!< callback function of host close the UVC device */
|
||||
void *cb_ctx; /*!< callback context, for user specific usage */
|
||||
} uvc_device_config_t;
|
||||
|
||||
/**
|
||||
* @brief Configure the UVC device by uvc device number
|
||||
*
|
||||
* @param index UVC device index number [0,1]
|
||||
* @param config Configuration for the UVC device
|
||||
* @return ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG if the configuration is invalid
|
||||
* ESP_FAIL if the UVC device could not be initialized
|
||||
*/
|
||||
esp_err_t uvc_device_config(int index, uvc_device_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Initialize the UVC device, after this function is called, the UVC device will be visible to the host
|
||||
* and the host can open the UVC device with the specific format and resolution.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* ESP_FAIL if the UVC device could not be initialized
|
||||
*/
|
||||
esp_err_t uvc_device_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the UVC device
|
||||
* @note This function is not implemented yet because tinyusb does not support deinitialization
|
||||
* @return ESP_OK on success
|
||||
* ESP_FAIL if the UVC device could not be deinitialized
|
||||
*/
|
||||
//esp_err_t uvc_device_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
202
components/usb_device_uvc/license.txt
Normal file
202
components/usb_device_uvc/license.txt
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
155
components/usb_device_uvc/tusb/tusb_config.h
Normal file
155
components/usb_device_uvc/tusb/tusb_config.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#include "uvc_frame_config.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board Specific Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifdef CONFIG_TINYUSB_RHPORT_HS
|
||||
# define CFG_TUSB_RHPORT1_MODE OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
# define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
#define ESP_PLATFORM 1
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4)
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
// Enable Device stack
|
||||
#define CFG_TUD_ENABLED 1
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
* into those specific section.
|
||||
* e.g
|
||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||
*/
|
||||
#ifndef CFG_TUSB_MEM_SECTION
|
||||
#define CFG_TUSB_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
|
||||
// The number of video control interfaces
|
||||
// The number of video streaming interfaces
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#define CFG_TUD_VIDEO 2
|
||||
#define CFG_TUD_VIDEO_STREAMING 2
|
||||
#else
|
||||
#define CFG_TUD_VIDEO 1
|
||||
#define CFG_TUD_VIDEO_STREAMING 1
|
||||
#endif
|
||||
|
||||
// video streaming endpoint size
|
||||
#ifdef UVC_CAM1_BULK_MODE
|
||||
#if CONFIG_TINYUSB_RHPORT_HS
|
||||
#define CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE 512
|
||||
#else
|
||||
#define CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE 64
|
||||
#endif
|
||||
#define CFG_TUD_CAM1_VIDEO_STREAMING_BULK 1
|
||||
#else
|
||||
#define CFG_TUD_CAM1_VIDEO_STREAMING_BULK 0
|
||||
#if CONFIG_TINYUSB_RHPORT_HS
|
||||
#define CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE 1023
|
||||
#else
|
||||
#define CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE 512
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG (!FORMAT_MJPEG)
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#ifdef UVC_CAM2_BULK_MODE
|
||||
#if CONFIG_TINYUSB_RHPORT_HS
|
||||
#define CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE 512
|
||||
#else
|
||||
#define CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE 64
|
||||
#endif
|
||||
#define CFG_TUD_CAM2_VIDEO_STREAMING_BULK 1
|
||||
#else
|
||||
#define CFG_TUD_CAM2_VIDEO_STREAMING_BULK 0
|
||||
#if CONFIG_TINYUSB_RHPORT_HS
|
||||
#define CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE 1023
|
||||
#else
|
||||
#define CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE 512
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE (CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE > CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE?CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE:CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE)
|
||||
#else
|
||||
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
343
components/usb_device_uvc/tusb/usb_descriptors.c
Normal file
343
components/usb_device_uvc/tusb/usb_descriptors.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
* Copyright (c) 2023 Espressif
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for Video
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = CONFIG_TUSB_VID,
|
||||
.idProduct = CONFIG_TUSB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const *tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *)&desc_device;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
#if CFG_TUD_CAM1_VIDEO_STREAMING_BULK
|
||||
|
||||
#if CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_MJPEG_BULK_LEN(4))
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_FRAME_BASED_BULK_LEN(4))
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN)
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_FRAME_BASED_BULK_LEN)
|
||||
#else
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN)
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
|
||||
#else
|
||||
|
||||
#if CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_MJPEG_LEN(4))
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_FRAME_BASED_LEN(4))
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN)
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_FRAME_BASED_LEN)
|
||||
#else
|
||||
#define TUD_CAM1_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN)
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
|
||||
#endif // CFG_TUD_CAM1_VIDEO_STREAMING_BULK
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#if CFG_TUD_CAM2_VIDEO_STREAMING_BULK
|
||||
|
||||
#if CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_MJPEG_BULK_LEN(4))
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_FRAME_BASED_BULK_LEN(4))
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN)
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_FRAME_BASED_BULK_LEN)
|
||||
#else
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN)
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
|
||||
#else
|
||||
|
||||
#if CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_MJPEG_LEN(4))
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MULTI_FRAME_BASED_LEN(4))
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN)
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_FRAME_BASED_LEN)
|
||||
#else
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN (TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN)
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
|
||||
#endif // CFG_TUD_CAM2_VIDEO_STREAMING_BULK
|
||||
#else
|
||||
#define TUD_CAM2_VIDEO_CAPTURE_DESC_LEN 0
|
||||
#endif
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CAM1_VIDEO_CAPTURE_DESC_LEN + TUD_CAM2_VIDEO_CAPTURE_DESC_LEN)
|
||||
#define EPNUM_CAM1_VIDEO_IN 0x81
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#define EPNUM_CAM2_VIDEO_IN 0x82
|
||||
#endif
|
||||
|
||||
uint8_t const desc_fs_configuration[] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500),
|
||||
// IAD for Video Control
|
||||
#if CFG_TUD_CAM1_VIDEO_STREAMING_BULK
|
||||
#if CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_MJPEG_BULK(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN, CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_H264_BULK(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN, CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN,
|
||||
UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE,
|
||||
CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_H264_BULK(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN,
|
||||
UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE,
|
||||
CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#else
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN,
|
||||
UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE,
|
||||
CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
#else
|
||||
#if CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_MJPEG(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN, CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_H264(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN, CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN,
|
||||
UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE,
|
||||
CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM1
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_H264(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN,
|
||||
UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE,
|
||||
CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#else
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM1_VIDEO_IN,
|
||||
UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE,
|
||||
CFG_TUD_CAM1_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
#endif // CFG_TUD_CAM1_VIDEO_STREAMING_BULK
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#if CFG_TUD_CAM2_VIDEO_STREAMING_BULK
|
||||
#if CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_MJPEG_BULK(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN, CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_H264_BULK(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN, CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN,
|
||||
UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE,
|
||||
CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_H264_BULK(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN,
|
||||
UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE,
|
||||
CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#else
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN,
|
||||
UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE,
|
||||
CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
#else
|
||||
#if CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_MJPEG(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN, CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_H264(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN, CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#else
|
||||
#if CONFIG_FORMAT_MJPEG_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN,
|
||||
UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE,
|
||||
CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#elif CONFIG_FORMAT_H264_CAM2
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_H264(4, ITF_NUM_VIDEO_CONTROL_2, EPNUM_CAM2_VIDEO_IN,
|
||||
UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE,
|
||||
CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#else
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, ITF_NUM_VIDEO_CONTROL, EPNUM_CAM2_VIDEO_IN,
|
||||
UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE,
|
||||
CFG_TUD_CAM2_VIDEO_STREAMING_EP_BUFSIZE),
|
||||
#endif
|
||||
#endif // CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
#endif // CFG_TUD_CAM2_VIDEO_STREAMING_BULK
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void)index; // for multiple configurations
|
||||
|
||||
return desc_fs_configuration;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// String Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const *string_desc_arr[] = {
|
||||
(const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
|
||||
CONFIG_TUSB_MANUFACTURER, // 1: Manufacturer
|
||||
CONFIG_TUSB_PRODUCT, // 2: Product
|
||||
CONFIG_TUSB_SERIAL_NUM, // 3: Serials, should use chip ID, overridden with get_serial_number()
|
||||
"UVC CAM1", // 4: UVC Interface, default, because we're overriding it get_uvc_device_name(), but we still have to keep the structure
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
"UVC CAM2", // 5: UVC Interface
|
||||
#endif
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
__attribute__((weak)) const char *get_uvc_device_name(void)
|
||||
{
|
||||
// ETVR Override, by default we're reporting ourselves as this, users can override it
|
||||
return "UVC OpenIris Camera";
|
||||
}
|
||||
|
||||
__attribute__((weak)) const char *get_serial_number(void)
|
||||
{
|
||||
// ETVR Override, by default we're reporting ourselves as the predefined serial number
|
||||
// this should get overwritten with a better implementation
|
||||
return CONFIG_TUSB_SERIAL_NUM;
|
||||
}
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
printf("am I being asked for this?");
|
||||
(void)langid;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||
|
||||
if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *str = string_desc_arr[index];
|
||||
if (index == 3)
|
||||
str = get_serial_number();
|
||||
if (index == 4)
|
||||
str = get_uvc_device_name();
|
||||
if (str == NULL)
|
||||
str = string_desc_arr[index];
|
||||
|
||||
// Cap at max char
|
||||
chr_count = (uint8_t)strlen(str);
|
||||
if (chr_count > 31)
|
||||
{
|
||||
chr_count = 31;
|
||||
}
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
for (uint8_t i = 0; i < chr_count; i++)
|
||||
{
|
||||
_desc_str[1 + i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
620
components/usb_device_uvc/tusb/usb_descriptors.h
Normal file
620
components/usb_device_uvc/tusb/usb_descriptors.h
Normal file
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Jerzy Kasenbreg
|
||||
* Copyright (c) 2021 Koji KITAYAMA
|
||||
* Copyright (c) 2023 Espressif
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _USB_DESCRIPTORS_H_
|
||||
#define _USB_DESCRIPTORS_H_
|
||||
|
||||
#include "uvc_frame_config.h"
|
||||
/* Time stamp base clock. It is a deprecated parameter. */
|
||||
#define UVC_CLOCK_FREQUENCY 27000000
|
||||
/* video capture path */
|
||||
#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01
|
||||
#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02
|
||||
|
||||
enum {
|
||||
#if (CFG_TUD_VIDEO)
|
||||
ITF_NUM_VIDEO_CONTROL,
|
||||
ITF_NUM_VIDEO_STREAMING,
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
ITF_NUM_VIDEO_CONTROL_2,
|
||||
ITF_NUM_VIDEO_STREAMING_2,
|
||||
#endif
|
||||
#endif
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#if (CFG_TUD_VIDEO)
|
||||
#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
/* Interface 1, Alternate 1 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
/* Interface 1, Alternate 1 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_MULTI_MJPEG_LEN(n) (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ (n*TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
/* Interface 1, Alternate 1 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_MULTI_MJPEG_BULK_LEN(n) (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ (n*TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_MULTI_FRAME_BASED_BULK_LEN(n) (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ (n*TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_FRAME_BASED_BULK_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_FRAME_BASED_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
/* Interface 1, Alternate 1 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESC_MULTI_FRAME_BASED_LEN(n) (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ (n*TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
/* Interface 1, Alternate 1 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
||||
|
||||
/* Windows support YUY2 and NV12
|
||||
* https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */
|
||||
|
||||
#define TUD_VIDEO_DESC_CS_VS_FMT_YUY2(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_YUY2, 16, _frmidx, _asrx, _asry, _interlace, _cp)
|
||||
#define TUD_VIDEO_DESC_CS_VS_FMT_NV12(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_NV12, 12, _frmidx, _asrx, _asry, _interlace, _cp)
|
||||
#define TUD_VIDEO_DESC_CS_VS_FMT_M420(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_M420, 12, _frmidx, _asrx, _asry, _interlace, _cp)
|
||||
#define TUD_VIDEO_DESC_CS_VS_FMT_I420(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_I420, 12, _frmidx, _asrx, _asry, _interlace, _cp)
|
||||
|
||||
#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(bCamIndex ,bFrameIndex) \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(bFrameIndex, 0, UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width, UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height, \
|
||||
UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height * 16, UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height * 16 * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate, \
|
||||
UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height * 16 / 8, \
|
||||
(10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate), (10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate), (10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate), (10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate))
|
||||
|
||||
#define TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(bCamIndex ,bFrameIndex) \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT(bFrameIndex, 0, UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width, UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height, \
|
||||
UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height * 16, UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].width * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].height * 16 * UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate, \
|
||||
(10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate), /*bytesPreLine*/ 0, (10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate), (10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate), (10000000/UVC_FRAMES_INFO[bCamIndex][bFrameIndex-1].rate))
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _itf,_epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 0, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
_width * _height * 16, \
|
||||
(10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* VS alt 1 */\
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 1, 1, _stridx), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(_stridx, _itf, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 0, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
_width * _height * 16 / 8, \
|
||||
(10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* VS alt 1 */\
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 1, 1, _stridx), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_MJPEG(_stridx, _itf, _epin, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 0, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ (UVC_FRAME_NUM*TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/UVC_FRAME_NUM, \
|
||||
/*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 1), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 2), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 3), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 4), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* VS alt 1 */\
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 1, 1, _stridx), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(_stridx, _itf, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 1, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
_width * _height * 16, \
|
||||
(10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(_stridx, _itf, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 1, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
_width * _height * 16 / 8, \
|
||||
(10000000/_fps), (10000000/_fps), (10000000/_fps), (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_MJPEG_BULK(_stridx, _itf, _epin, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 1, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\
|
||||
+ (UVC_FRAME_NUM*TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/UVC_FRAME_NUM, \
|
||||
/*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 1), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 2), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 3), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_TEMPLATE(_itf/2, 4), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_H264(_stridx, _itf, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 0, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*guid*/TUD_VIDEO_GUID_H264, /*bitsPerPix*/16, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0, /*variableSize*/1), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
(10000000/_fps), /*bytesPreLine*/ 0, \
|
||||
(10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* VS alt 1 */\
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 1, 1, _stridx), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_H264_BULK(_stridx, _itf, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 1, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*guid*/TUD_VIDEO_GUID_H264, /*bitsPerPix*/16, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0, /*variableSize*/1), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
(10000000/_fps), /*bytesPreLine*/ 0, \
|
||||
(10000000/_fps), (10000000/_fps), (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_H264(_stridx, _itf, _epin, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 0, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ (UVC_FRAME_NUM*TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED(/*bFormatIndex*/1, /*bNumFrameDescriptors*/UVC_FRAME_NUM, \
|
||||
/*guid*/TUD_VIDEO_GUID_H264, /*bitsPerPix*/16, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0, /*variableSize*/1), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 1), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 2), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 3), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 4), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* VS alt 1 */\
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 1, 1, _stridx), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MULTI_H264_BULK(_stridx, _itf, _epin, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(_itf, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(_itf, 0, _stridx), \
|
||||
TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \
|
||||
/* wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \
|
||||
UVC_CLOCK_FREQUENCY, _itf + 1), \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\
|
||||
/*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\
|
||||
/*wObjectiveFocalLength*/0, /*bmControls*/0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(_itf + 1, 0, 1, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */\
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED_LEN\
|
||||
+ (UVC_FRAME_NUM*TUD_VIDEO_DESC_CS_VS_FRM_FRAME_BASED_CONT_LEN)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_FRAME_BASED(/*bFormatIndex*/1, /*bNumFrameDescriptors*/UVC_FRAME_NUM, \
|
||||
/*guid*/TUD_VIDEO_GUID_H264, /*bitsPerPix*/16, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0, /*variableSize*/1), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 1), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 2), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 3), \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_H264_CONT_TEMPLATE(_itf/2, 4), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1)
|
||||
|
||||
#endif //CFG_TUD_VIDEO
|
||||
|
||||
/**
|
||||
* ETVR Custom implementation
|
||||
*
|
||||
* @brief get_uvc_device_name() is hacky, way for us to let users specify
|
||||
* a custom device name right after flashing their boards with a way to update it
|
||||
*/
|
||||
const char *get_uvc_device_name();
|
||||
|
||||
/**
|
||||
* ETVR Custom implementation
|
||||
*
|
||||
* @brief get_serial_number() is a way for us to specify a per-board serial number
|
||||
*/
|
||||
const char *get_serial_number();
|
||||
|
||||
#endif
|
||||
76
components/usb_device_uvc/tusb/uvc_frame_config.h
Normal file
76
components/usb_device_uvc/tusb/uvc_frame_config.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_FORMAT_MJPEG_CAM1
|
||||
#define FORMAT_MJPEG_CAM1 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UVC_CAM1_MULTI_FRAMESIZE
|
||||
//If enable, add VGA and HVGA to list
|
||||
#define UVC_CAM1_FRAME_MULTI 1
|
||||
#endif
|
||||
|
||||
#define UVC_CAM1_FRAME_WIDTH CONFIG_UVC_CAM1_FRAMESIZE_WIDTH
|
||||
#define UVC_CAM1_FRAME_HEIGHT CONFIG_UVC_CAM1_FRAMESIZE_HEIGT
|
||||
#define UVC_CAM1_FRAME_RATE CONFIG_UVC_CAM1_FRAMERATE
|
||||
|
||||
#ifdef CONFIG_UVC_MODE_BULK_CAM1
|
||||
#define UVC_CAM1_BULK_MODE
|
||||
#endif
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#ifdef CONFIG_FORMAT_MJPEG_CAM2
|
||||
#define FORMAT_MJPEG_CAM2 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UVC_CAM2_MULTI_FRAMESIZE
|
||||
//If enable, add VGA and HVGA to list
|
||||
#define UVC_CAM2_FRAME_MULTI 1
|
||||
#endif
|
||||
|
||||
#define UVC_CAM2_FRAME_WIDTH CONFIG_UVC_CAM2_FRAMESIZE_WIDTH
|
||||
#define UVC_CAM2_FRAME_HEIGHT CONFIG_UVC_CAM2_FRAMESIZE_HEIGT
|
||||
#define UVC_CAM2_FRAME_RATE CONFIG_UVC_CAM2_FRAMERATE
|
||||
|
||||
#ifdef CONFIG_UVC_MODE_BULK_CAM2
|
||||
#define UVC_CAM2_BULK_MODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UVC_CAM2_FRAME_WIDTH
|
||||
#define UVC_CAM2_FRAME_WIDTH UVC_CAM1_FRAME_WIDTH
|
||||
#endif
|
||||
|
||||
#ifndef UVC_CAM2_FRAME_HEIGHT
|
||||
#define UVC_CAM2_FRAME_HEIGHT UVC_CAM1_FRAME_HEIGHT
|
||||
#endif
|
||||
|
||||
#ifndef UVC_CAM2_FRAME_RATE
|
||||
#define UVC_CAM2_FRAME_RATE UVC_CAM1_FRAME_RATE
|
||||
#endif
|
||||
|
||||
static const struct {
|
||||
int width;
|
||||
int height;
|
||||
int rate;
|
||||
} UVC_FRAMES_INFO[][4] = {{
|
||||
{UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE},
|
||||
{CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1},
|
||||
{CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2},
|
||||
{CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3},
|
||||
}, {
|
||||
{UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE},
|
||||
{CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1},
|
||||
{CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2},
|
||||
{CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3},
|
||||
}
|
||||
};
|
||||
|
||||
#define UVC_FRAME_NUM (sizeof(UVC_FRAMES_INFO[0]) / sizeof(UVC_FRAMES_INFO[0][0]))
|
||||
_Static_assert(UVC_FRAME_NUM == 4, "UVC_FRAME_NUM must be 4");
|
||||
345
components/usb_device_uvc/usb_device_uvc.c
Normal file
345
components/usb_device_uvc/usb_device_uvc.c
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_check.h"
|
||||
#if CONFIG_TINYUSB_RHPORT_HS
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "soc/hp_system_reg.h"
|
||||
#else
|
||||
#include "esp_private/usb_phy.h"
|
||||
#endif
|
||||
#include "tusb.h"
|
||||
#include "usb_device_uvc.h"
|
||||
|
||||
static const char *TAG = "usbd_uvc";
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#define UVC_CAM_NUM 2
|
||||
#else
|
||||
#define UVC_CAM_NUM 1
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if !CONFIG_TINYUSB_RHPORT_HS
|
||||
usb_phy_handle_t phy_hdl;
|
||||
#endif
|
||||
bool uvc_init[UVC_CAM_NUM];
|
||||
uvc_format_t format[UVC_CAM_NUM];
|
||||
uvc_device_config_t user_config[UVC_CAM_NUM];
|
||||
TaskHandle_t uvc_task_hdl[UVC_CAM_NUM];
|
||||
uint32_t interval_ms[UVC_CAM_NUM];
|
||||
} uvc_device_t;
|
||||
|
||||
static uvc_device_t s_uvc_device;
|
||||
|
||||
static void usb_phy_init(void)
|
||||
{
|
||||
#if !CONFIG_TINYUSB_RHPORT_HS
|
||||
// Configure USB PHY
|
||||
usb_phy_config_t phy_conf = {
|
||||
.controller = USB_PHY_CTRL_OTG,
|
||||
.otg_mode = USB_OTG_MODE_DEVICE,
|
||||
.target = USB_PHY_TARGET_INT,
|
||||
};
|
||||
usb_new_phy(&phy_conf, &s_uvc_device.phy_hdl);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t get_time_millis(void)
|
||||
{
|
||||
return (uint32_t)(esp_timer_get_time() / 1000);
|
||||
}
|
||||
|
||||
static void tusb_device_task(void *arg)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
tud_task();
|
||||
}
|
||||
}
|
||||
|
||||
void tud_mount_cb(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Mount");
|
||||
}
|
||||
|
||||
// Invoked when device is unmounted
|
||||
void tud_umount_cb(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "UN-Mount");
|
||||
}
|
||||
|
||||
void tud_suspend_cb(bool remote_wakeup_en)
|
||||
{
|
||||
(void)remote_wakeup_en;
|
||||
|
||||
if (s_uvc_device.user_config[0].stop_cb)
|
||||
{
|
||||
s_uvc_device.user_config[0].stop_cb(s_uvc_device.user_config[0].cb_ctx);
|
||||
}
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
if (s_uvc_device.user_config[1].stop_cb)
|
||||
{
|
||||
s_uvc_device.user_config[1].stop_cb(s_uvc_device.user_config[1].cb_ctx);
|
||||
}
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Suspend");
|
||||
}
|
||||
|
||||
// Invoked when usb bus is resumed
|
||||
void tud_resume_cb(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Resume");
|
||||
}
|
||||
|
||||
#if (CFG_TUD_VIDEO)
|
||||
//--------------------------------------------------------------------+
|
||||
// USB Video
|
||||
//--------------------------------------------------------------------+
|
||||
static void video_task(void *arg)
|
||||
{
|
||||
uint32_t start_ms = 0;
|
||||
uint32_t frame_num = 0;
|
||||
uint32_t frame_len = 0;
|
||||
uint32_t already_start = 0;
|
||||
uint32_t tx_busy = 0;
|
||||
uint8_t *uvc_buffer = s_uvc_device.user_config[0].uvc_buffer;
|
||||
uint32_t uvc_buffer_size = s_uvc_device.user_config[0].uvc_buffer_size;
|
||||
uvc_fb_t *pic = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!tud_video_n_streaming(0, 0))
|
||||
{
|
||||
already_start = 0;
|
||||
frame_num = 0;
|
||||
tx_busy = 0;
|
||||
vTaskDelay(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!already_start)
|
||||
{
|
||||
already_start = 1;
|
||||
start_ms = get_time_millis();
|
||||
}
|
||||
|
||||
uint32_t cur = get_time_millis();
|
||||
if (cur - start_ms < s_uvc_device.interval_ms[0])
|
||||
{
|
||||
vTaskDelay(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tx_busy)
|
||||
{
|
||||
uint32_t xfer_done = ulTaskNotifyTake(pdTRUE, 1);
|
||||
if (xfer_done == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
++frame_num;
|
||||
tx_busy = 0;
|
||||
}
|
||||
|
||||
start_ms += s_uvc_device.interval_ms[0];
|
||||
ESP_LOGD(TAG, "frame %" PRIu32 " taking picture...", frame_num);
|
||||
pic = s_uvc_device.user_config[0].fb_get_cb(s_uvc_device.user_config[0].cb_ctx);
|
||||
if (pic)
|
||||
{
|
||||
ESP_LOGD(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to capture picture");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pic->len > uvc_buffer_size)
|
||||
{
|
||||
ESP_LOGW(TAG, "frame size is too big, dropping frame");
|
||||
s_uvc_device.user_config[0].fb_return_cb(pic, s_uvc_device.user_config[0].cb_ctx);
|
||||
continue;
|
||||
}
|
||||
frame_len = pic->len;
|
||||
memcpy(uvc_buffer, pic->buf, frame_len);
|
||||
s_uvc_device.user_config[0].fb_return_cb(pic, s_uvc_device.user_config[0].cb_ctx);
|
||||
tx_busy = 1;
|
||||
tud_video_n_frame_xfer(0, 0, (void *)uvc_buffer, frame_len);
|
||||
ESP_LOGD(TAG, "frame %" PRIu32 " transfer start, size %" PRIu32, frame_num, frame_len);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
static void video_task2(void *arg)
|
||||
{
|
||||
uint32_t start_ms = 0;
|
||||
uint32_t frame_num = 0;
|
||||
uint32_t frame_len = 0;
|
||||
uint32_t already_start = 0;
|
||||
uint32_t tx_busy = 0;
|
||||
uint8_t *uvc_buffer = s_uvc_device.user_config[1].uvc_buffer;
|
||||
uint32_t uvc_buffer_size = s_uvc_device.user_config[1].uvc_buffer_size;
|
||||
uvc_fb_t *pic = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!tud_video_n_streaming(1, 0))
|
||||
{
|
||||
already_start = 0;
|
||||
frame_num = 0;
|
||||
tx_busy = 0;
|
||||
vTaskDelay(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!already_start)
|
||||
{
|
||||
already_start = 1;
|
||||
start_ms = get_time_millis();
|
||||
}
|
||||
|
||||
uint32_t cur = get_time_millis();
|
||||
if (cur - start_ms < s_uvc_device.interval_ms[1])
|
||||
{
|
||||
vTaskDelay(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tx_busy)
|
||||
{
|
||||
uint32_t xfer_done = ulTaskNotifyTake(pdTRUE, 1);
|
||||
if (xfer_done == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
++frame_num;
|
||||
tx_busy = 0;
|
||||
}
|
||||
|
||||
start_ms += s_uvc_device.interval_ms[1];
|
||||
ESP_LOGD(TAG, "frame %" PRIu32 " taking picture...", frame_num);
|
||||
pic = s_uvc_device.user_config[1].fb_get_cb(s_uvc_device.user_config[1].cb_ctx);
|
||||
if (pic)
|
||||
{
|
||||
ESP_LOGD(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to capture picture");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pic->len > uvc_buffer_size)
|
||||
{
|
||||
ESP_LOGW(TAG, "frame size is too big, dropping frame");
|
||||
s_uvc_device.user_config[1].fb_return_cb(pic, s_uvc_device.user_config[1].cb_ctx);
|
||||
continue;
|
||||
}
|
||||
frame_len = pic->len;
|
||||
memcpy(uvc_buffer, pic->buf, frame_len);
|
||||
s_uvc_device.user_config[1].fb_return_cb(pic, s_uvc_device.user_config[1].cb_ctx);
|
||||
tx_busy = 1;
|
||||
tud_video_n_frame_xfer(1, 0, (void *)uvc_buffer, frame_len);
|
||||
ESP_LOGD(TAG, "frame %" PRIu32 " transfer start, size %" PRIu32, frame_num, frame_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
|
||||
{
|
||||
(void)ctl_idx;
|
||||
(void)stm_idx;
|
||||
xTaskNotifyGive(s_uvc_device.uvc_task_hdl[ctl_idx]);
|
||||
}
|
||||
|
||||
int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx,
|
||||
video_probe_and_commit_control_t const *parameters)
|
||||
{
|
||||
(void)ctl_idx;
|
||||
(void)stm_idx;
|
||||
/* convert unit to ms from 100 ns */
|
||||
ESP_LOGI(TAG, "bFrameIndex: %u", parameters->bFrameIndex);
|
||||
ESP_LOGI(TAG, "dwFrameInterval: %" PRIu32 "", parameters->dwFrameInterval);
|
||||
if (parameters->bFrameIndex > UVC_FRAME_NUM)
|
||||
{
|
||||
return VIDEO_ERROR_OUT_OF_RANGE;
|
||||
}
|
||||
s_uvc_device.interval_ms[ctl_idx] = parameters->dwFrameInterval / 10000;
|
||||
int frame_index = parameters->bFrameIndex - 1;
|
||||
esp_err_t ret = s_uvc_device.user_config[ctl_idx].start_cb(s_uvc_device.format[ctl_idx], UVC_FRAMES_INFO[ctl_idx][frame_index].width,
|
||||
UVC_FRAMES_INFO[ctl_idx][frame_index].height, UVC_FRAMES_INFO[ctl_idx][frame_index].rate, s_uvc_device.user_config[ctl_idx].cb_ctx);
|
||||
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "camera init failed");
|
||||
return VIDEO_ERROR_OUT_OF_RANGE;
|
||||
}
|
||||
return VIDEO_ERROR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t uvc_device_config(int index, uvc_device_config_t *config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(index < UVC_CAM_NUM, ESP_ERR_INVALID_ARG, TAG, "index is invalid");
|
||||
ESP_RETURN_ON_FALSE(config != NULL, ESP_ERR_INVALID_ARG, TAG, "config is NULL");
|
||||
ESP_RETURN_ON_FALSE(config->start_cb != NULL, ESP_ERR_INVALID_ARG, TAG, "start_cb is NULL");
|
||||
ESP_RETURN_ON_FALSE(config->fb_get_cb != NULL, ESP_ERR_INVALID_ARG, TAG, "fb_get_cb is NULL");
|
||||
ESP_RETURN_ON_FALSE(config->fb_return_cb != NULL, ESP_ERR_INVALID_ARG, TAG, "fb_return_cb is NULL");
|
||||
ESP_RETURN_ON_FALSE(config->stop_cb != NULL, ESP_ERR_INVALID_ARG, TAG, "stop_cb is NULL");
|
||||
ESP_RETURN_ON_FALSE(config->uvc_buffer != NULL, ESP_ERR_INVALID_ARG, TAG, "uvc_buffer is NULL");
|
||||
ESP_RETURN_ON_FALSE(config->uvc_buffer_size > 0, ESP_ERR_INVALID_ARG, TAG, "uvc_buffer_size is 0");
|
||||
|
||||
s_uvc_device.user_config[index] = *config;
|
||||
s_uvc_device.interval_ms[index] = 1000 / (index == 0 ? UVC_CAM1_FRAME_RATE : UVC_CAM2_FRAME_RATE);
|
||||
s_uvc_device.uvc_init[index] = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t uvc_device_init(void)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(s_uvc_device.uvc_init[0], ESP_ERR_INVALID_STATE, TAG, "uvc device 0 not init");
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
ESP_RETURN_ON_FALSE(s_uvc_device.uvc_init[1], ESP_ERR_INVALID_STATE, TAG, "uvc device 1 not init, if not use, please disable CONFIG_UVC_SUPPORT_TWO_CAM");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FORMAT_MJPEG_CAM1
|
||||
s_uvc_device.format[0] = UVC_FORMAT_JPEG;
|
||||
#endif
|
||||
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
#ifdef CONFIG_FORMAT_MJPEG_CAM2
|
||||
s_uvc_device.format[1] = UVC_FORMAT_JPEG;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// init device stack on configured roothub port
|
||||
usb_phy_init();
|
||||
bool usb_init = tusb_init();
|
||||
if (!usb_init)
|
||||
{
|
||||
ESP_LOGE(TAG, "USB Device Stack Init Fail");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
BaseType_t core_id = (CONFIG_UVC_TINYUSB_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_TINYUSB_TASK_CORE;
|
||||
xTaskCreatePinnedToCore(tusb_device_task, "TinyUSB", 4096, NULL, CONFIG_UVC_TINYUSB_TASK_PRIORITY, NULL, core_id);
|
||||
#if (CFG_TUD_VIDEO)
|
||||
core_id = (CONFIG_UVC_CAM1_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_CAM1_TASK_CORE;
|
||||
xTaskCreatePinnedToCore(video_task, "UVC", 4096, NULL, CONFIG_UVC_CAM1_TASK_PRIORITY, &s_uvc_device.uvc_task_hdl[0], core_id);
|
||||
#if CONFIG_UVC_SUPPORT_TWO_CAM
|
||||
core_id = (CONFIG_UVC_CAM2_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_CAM2_TASK_CORE;
|
||||
xTaskCreatePinnedToCore(video_task2, "UVC2", 4096, NULL, CONFIG_UVC_CAM2_TASK_PRIORITY, &s_uvc_device.uvc_task_hdl[1], core_id);
|
||||
#endif
|
||||
#endif
|
||||
ESP_LOGI(TAG, "UVC Device Start, Version: %d.%d.%d", USB_DEVICE_UVC_VER_MAJOR, USB_DEVICE_UVC_VER_MINOR, USB_DEVICE_UVC_VER_PATCH);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies:
|
||||
espressif/cmake_utilities:
|
||||
component_hash: 7e20811092150b668a710cfbf43164721b23bac766811f4e68036450a3265fba
|
||||
component_hash: 05165f30922b422b4b90c08845e6d449329b97370fbd06309803d8cb539d79e3
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
@@ -8,7 +8,7 @@ dependencies:
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
version: 1.1.1
|
||||
espressif/esp32-camera:
|
||||
component_hash: a82de4ee0b383bd34695935385c6a6c720129084580c2bbb55dce76eb2a3788f
|
||||
dependencies: []
|
||||
@@ -20,7 +20,6 @@ dependencies:
|
||||
component_hash: 28c6509a727ef74925b372ed404772aeedf11cce10b78c3f69b3c66799095e2d
|
||||
dependencies:
|
||||
- name: idf
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
@@ -38,7 +37,7 @@ dependencies:
|
||||
type: service
|
||||
version: 1.4.0
|
||||
espressif/tinyusb:
|
||||
component_hash: 214989d502fc168241a4a4f83b097d8ac44a93cd6f1787b4ac10069a8b3bebd3
|
||||
component_hash: 10703da2c3cd39a944711ee3d320c6dda54debabf13b4b933a7c90daf102372b
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
@@ -50,40 +49,18 @@ dependencies:
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
version: 0.15.0~10
|
||||
espressif/usb_device_uvc:
|
||||
component_hash: f86ee44e64f3914474919a14ac4d47082d6a2888a62c239e6e9dc58c32da4682
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com/
|
||||
require: private
|
||||
version: '*'
|
||||
- name: espressif/tinyusb
|
||||
registry_url: https://components.espressif.com/
|
||||
require: private
|
||||
version: '>=0.15.0~10'
|
||||
- name: idf
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
version: 1.1.0
|
||||
version: 0.18.0~2
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.3.2
|
||||
direct_dependencies:
|
||||
- espressif/cmake_utilities
|
||||
- espressif/esp32-camera
|
||||
- espressif/led_strip
|
||||
- espressif/mdns
|
||||
- espressif/usb_device_uvc
|
||||
- espressif/tinyusb
|
||||
- idf
|
||||
manifest_hash: dfe29d524d2f5acb426e21118042ac1c021e44e8e7072b700d872ac75499cd6c
|
||||
manifest_hash: 1f812e7723bfe7dc357c54a3f01b77580502ba368553b7d186d3a0fbc2a82bab
|
||||
target: esp32s3
|
||||
version: 2.0.0
|
||||
|
||||
@@ -3,4 +3,5 @@ dependencies:
|
||||
espressif/led_strip: "^2.4.1"
|
||||
idf: "^5.0"
|
||||
espressif/esp32-camera: "^2.0.0"
|
||||
espressif/usb_device_uvc: "1.1.0"
|
||||
# disabled on purpose, we've overwritten some components
|
||||
# espressif/usb_device_uvc: "1.1.0"
|
||||
|
||||
@@ -39,7 +39,7 @@ auto commandManager = std::make_shared<CommandManager>(dependencyRegistry);
|
||||
WebSocketLogger webSocketLogger;
|
||||
Preferences preferences;
|
||||
|
||||
auto deviceConfig = std::make_shared<ProjectConfig>(&preferences);
|
||||
std::shared_ptr<ProjectConfig> deviceConfig = std::make_shared<ProjectConfig>(&preferences);
|
||||
WiFiManager wifiManager(deviceConfig, eventQueue, stateManager);
|
||||
MDNSManager mdnsManager(deviceConfig, eventQueue);
|
||||
|
||||
@@ -55,25 +55,21 @@ UVCStreamManager uvcStream;
|
||||
auto *ledManager = new LEDManager(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue);
|
||||
auto *serialManager = new SerialManager(commandManager, &timerHandle);
|
||||
|
||||
static void initNVSStorage()
|
||||
{
|
||||
static void initNVSStorage() {
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
{
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
int test_log(const char *format, va_list args)
|
||||
{
|
||||
int test_log(const char *format, va_list args) {
|
||||
webSocketLogger.log_message(format, args);
|
||||
return vprintf(format, args);
|
||||
}
|
||||
|
||||
void disable_serial_manager_task(TaskHandle_t serialManagerHandle)
|
||||
{
|
||||
void disable_serial_manager_task(TaskHandle_t serialManagerHandle) {
|
||||
vTaskDelete(serialManagerHandle);
|
||||
}
|
||||
|
||||
@@ -84,8 +80,7 @@ void disable_serial_manager_task(TaskHandle_t serialManagerHandle)
|
||||
//
|
||||
// todo: check the initial PR by Summer and port the device mode from that, should be useful
|
||||
// but we'll have to rethink it
|
||||
void start_video_streaming(void *arg)
|
||||
{
|
||||
void start_video_streaming(void *arg) {
|
||||
if (!deviceConfig->getWifiConfigs().empty() || strcmp(CONFIG_WIFI_SSID, "") != 0) {
|
||||
// make sure the server runs on a separate core
|
||||
ESP_LOGI("[MAIN]", "WiFi setup detected, starting WiFi streaming.");
|
||||
@@ -104,24 +99,22 @@ void start_video_streaming(void *arg)
|
||||
disable_serial_manager_task(serialTaskHandle);
|
||||
}
|
||||
|
||||
esp_timer_handle_t createStartVideoStreamingTimer(void *pvParameter)
|
||||
{
|
||||
esp_timer_handle_t createStartVideoStreamingTimer(void *pvParameter) {
|
||||
esp_timer_handle_t handle;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = &start_video_streaming,
|
||||
.arg = pvParameter,
|
||||
.name = "startVideoStreaming"};
|
||||
.name = "startVideoStreaming"
|
||||
};
|
||||
|
||||
if (const auto result = esp_timer_create(&args, &handle); result != ESP_OK)
|
||||
{
|
||||
if (const auto result = esp_timer_create(&args, &handle); result != ESP_OK) {
|
||||
ESP_LOGE("[MAIN]", "Failed to create timer: %s", esp_err_to_name(result));
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
extern "C" void app_main(void) {
|
||||
TaskHandle_t *serialManagerHandle = nullptr;
|
||||
dependencyRegistry->registerService<ProjectConfig>(DependencyType::project_config, deviceConfig);
|
||||
dependencyRegistry->registerService<CameraManager>(DependencyType::camera_manager, cameraHandler);
|
||||
@@ -219,8 +212,7 @@ extern "C" void app_main(void)
|
||||
nullptr);
|
||||
|
||||
timerHandle = createStartVideoStreamingTimer(serialManagerHandle);
|
||||
if (timerHandle != nullptr)
|
||||
{
|
||||
if (timerHandle != nullptr) {
|
||||
esp_timer_start_once(timerHandle, 30000000); // 30s
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user