commit
27ae871a8b
8 changed files with 599 additions and 353 deletions
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Jerzy Kasenbreg
|
||||
* Copyright (c) 2021 Koji KITAYAMA
|
||||
*
|
||||
* 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_
|
||||
|
||||
/* 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 {
|
||||
ITF_NUM_VIDEO_CONTROL,
|
||||
ITF_NUM_VIDEO_STREAMING,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#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_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 */\
|
||||
)
|
||||
|
||||
/* 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_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \
|
||||
/* Header: UVC 1.5, wTotalLength - bLength */ \
|
||||
TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \
|
||||
/* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 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_NUM_VIDEO_STREAMING, 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)
|
||||
|
||||
#endif
|
||||
|
|
@ -10,20 +10,100 @@
|
|||
*********************************************************************/
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
// Video descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* Time stamp base clock. It is a deprecated parameter. */
|
||||
#define FRAME_WIDTH 128
|
||||
#define FRAME_HEIGHT 96
|
||||
#define FRAME_RATE 30
|
||||
|
||||
uint8_t const desc_video[] = {
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(0, 0x80, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, 64)
|
||||
/* video capture path
|
||||
*
|
||||
* | Camera Terminal (0x01) | ----> | Output Terminal (0x02 Streaming) |
|
||||
* */
|
||||
#define TERMID_CAMERA 0x01
|
||||
#define TERMID_OUTPUT 0x02
|
||||
|
||||
tusb_desc_video_control_camera_terminal_t const desc_camera_terminal = {
|
||||
.bLength = sizeof(tusb_desc_video_control_camera_terminal_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL,
|
||||
|
||||
.bTerminalID = TERMID_CAMERA,
|
||||
.wTerminalType = VIDEO_ITT_CAMERA,
|
||||
.bAssocTerminal = 0,
|
||||
.iTerminal = 0,
|
||||
.wObjectiveFocalLengthMin = 0,
|
||||
.wObjectiveFocalLengthMax = 0,
|
||||
.wOcularFocalLength = 0,
|
||||
.bControlSize = 3,
|
||||
.bmControls = { 0, 0, 0 }
|
||||
};
|
||||
|
||||
Adafruit_USBD_Video usb_video(desc_video, sizeof(desc_video));
|
||||
tusb_desc_video_control_output_terminal_t const desc_output_terminal = {
|
||||
.bLength = sizeof(tusb_desc_video_control_output_terminal_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL,
|
||||
|
||||
.bTerminalID = TERMID_OUTPUT,
|
||||
.wTerminalType = VIDEO_TT_STREAMING,
|
||||
.bAssocTerminal = 0,
|
||||
.bSourceID = TERMID_CAMERA,
|
||||
.iTerminal = 0
|
||||
};
|
||||
|
||||
tusb_desc_video_format_uncompressed_t const desc_format = {
|
||||
.bLength = sizeof(tusb_desc_video_format_uncompressed_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED,
|
||||
.bFormatIndex = 1, // 1-based index
|
||||
.bNumFrameDescriptors = 1,
|
||||
.guidFormat = { TUD_VIDEO_GUID_YUY2 },
|
||||
.bBitsPerPixel = 16,
|
||||
.bDefaultFrameIndex = 1,
|
||||
.bAspectRatioX = 0,
|
||||
.bAspectRatioY = 0,
|
||||
.bmInterlaceFlags = 0,
|
||||
.bCopyProtect = 0
|
||||
};
|
||||
|
||||
tusb_desc_video_frame_uncompressed_continuous_t desc_frame = {
|
||||
.bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED,
|
||||
.bFrameIndex = 1, // 1-based index
|
||||
.bmCapabilities = 0,
|
||||
.wWidth = FRAME_WIDTH,
|
||||
.wHeight = FRAME_HEIGHT,
|
||||
.dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1,
|
||||
.dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE,
|
||||
.dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8,
|
||||
.dwDefaultFrameInterval = 10000000 / FRAME_RATE,
|
||||
.bFrameIntervalType = 0, // continuous
|
||||
.dwFrameInterval = {
|
||||
10000000 / FRAME_RATE, // min
|
||||
10000000, // max
|
||||
10000000 / FRAME_RATE // step
|
||||
}
|
||||
};
|
||||
|
||||
tusb_desc_video_streaming_color_matching_t desc_color = {
|
||||
.bLength = sizeof(tusb_desc_video_streaming_color_matching_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT,
|
||||
|
||||
.bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709,
|
||||
.bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709,
|
||||
.bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Video and frame buffer
|
||||
//--------------------------------------------------------------------+
|
||||
Adafruit_USBD_Video usb_video;
|
||||
|
||||
// YUY2 frame buffer
|
||||
static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8];
|
||||
|
|
@ -41,6 +121,13 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position);
|
|||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
usb_video.addTerminal(&desc_camera_terminal);
|
||||
usb_video.addTerminal(&desc_output_terminal);
|
||||
usb_video.addFormat(&desc_format);
|
||||
usb_video.addFrame(&desc_frame);
|
||||
usb_video.addColorMatching(&desc_color);
|
||||
|
||||
usb_video.begin();
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +140,7 @@ void loop() {
|
|||
|
||||
if (!already_sent) {
|
||||
already_sent = 1;
|
||||
tx_busy = 1;
|
||||
start_ms = millis();
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
|
|
@ -62,6 +150,7 @@ void loop() {
|
|||
if (cur - start_ms < interval_ms) return; // not enough time
|
||||
if (tx_busy) return;
|
||||
start_ms += interval_ms;
|
||||
tx_busy = 1;
|
||||
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,80 @@
|
|||
|
||||
#include "Adafruit_USBD_Video.h"
|
||||
|
||||
Adafruit_USBD_Video::Adafruit_USBD_Video(uint8_t const *desc_itf,
|
||||
size_t desc_len) {
|
||||
_desc_itf = desc_itf;
|
||||
_desc_len = desc_len;
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
// static uint16_t hid_load_descriptor(uint8_t *dst, uint8_t *itf) {}
|
||||
#endif
|
||||
|
||||
Adafruit_USBD_Video::Adafruit_USBD_Video(void) {
|
||||
_vc_id = 0;
|
||||
memset(&_camera_terminal, 0, sizeof(_camera_terminal));
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
// tinyusb_enable_interface(USB_INTERFACE_HID, desc_len, hid_load_descriptor);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Adafruit_USBD_Video::addTerminal(
|
||||
tusb_desc_video_control_camera_terminal_t const *camera_terminal) {
|
||||
_camera_terminal = *camera_terminal;
|
||||
|
||||
// override constants
|
||||
_camera_terminal.bLength = sizeof(tusb_desc_video_control_camera_terminal_t);
|
||||
_camera_terminal.bDescriptorType = TUSB_DESC_CS_INTERFACE;
|
||||
_camera_terminal.bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL;
|
||||
|
||||
_camera_terminal.bControlSize = 3;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Adafruit_USBD_Video::addTerminal(
|
||||
tusb_desc_video_control_output_terminal_t const *output_terminal) {
|
||||
_output_terminal = *output_terminal;
|
||||
|
||||
// override constants
|
||||
_output_terminal.bLength = sizeof(tusb_desc_video_control_output_terminal_t);
|
||||
_output_terminal.bDescriptorType = TUSB_DESC_CS_INTERFACE;
|
||||
_output_terminal.bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Adafruit_USBD_Video::addFormat(
|
||||
tusb_desc_video_format_uncompressed_t const *format) {
|
||||
_format.uncompressed = *format;
|
||||
|
||||
// override constants
|
||||
_format.uncompressed.bLength = sizeof(tusb_desc_video_format_uncompressed_t);
|
||||
_format.uncompressed.bDescriptorType = TUSB_DESC_CS_INTERFACE;
|
||||
_format.uncompressed.bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Adafruit_USBD_Video::addFrame(
|
||||
tusb_desc_video_frame_uncompressed_continuous_t const *frame) {
|
||||
_frame.uncompressed_cont = *frame;
|
||||
|
||||
// override constants
|
||||
_frame.uncompressed_cont.bLength =
|
||||
sizeof(tusb_desc_video_frame_uncompressed_continuous_t);
|
||||
_frame.uncompressed_cont.bDescriptorType = TUSB_DESC_CS_INTERFACE;
|
||||
_frame.uncompressed_cont.bDescriptorSubType =
|
||||
VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED;
|
||||
_frame.uncompressed_cont.bFrameIntervalType = 0; // continuous
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Adafruit_USBD_Video::addColorMatching(
|
||||
tusb_desc_video_streaming_color_matching_t const *color) {
|
||||
_color_matching = *color;
|
||||
|
||||
// override constants
|
||||
_color_matching.bLength = sizeof(tusb_desc_video_streaming_color_matching_t);
|
||||
_color_matching.bDescriptorType = TUSB_DESC_CS_INTERFACE;
|
||||
_color_matching.bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT;
|
||||
}
|
||||
|
||||
bool Adafruit_USBD_Video::begin() {
|
||||
|
|
@ -45,17 +114,154 @@ bool Adafruit_USBD_Video::begin() {
|
|||
return true;
|
||||
}
|
||||
|
||||
uint16_t Adafruit_USBD_Video::getInterfaceDescriptor(uint8_t itfnum,
|
||||
uint16_t Adafruit_USBD_Video::getInterfaceDescriptor(uint8_t itfnum_deprecated,
|
||||
uint8_t *buf,
|
||||
uint16_t bufsize) {
|
||||
(void)itfnum;
|
||||
(void)itfnum_deprecated;
|
||||
|
||||
if (!buf || bufsize < _desc_len) {
|
||||
return false;
|
||||
uint8_t itfnum = 0;
|
||||
uint8_t ep_in = 0;
|
||||
|
||||
// check if necessary descriptors are added
|
||||
if (!(_camera_terminal.bLength && _output_terminal.bLength &&
|
||||
_format.uncompressed.bLength && _frame.uncompressed_cont.bLength &&
|
||||
_color_matching.bLength)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, _desc_itf, _desc_len);
|
||||
return _desc_len;
|
||||
// Null buf is for length only
|
||||
if (buf) {
|
||||
itfnum = TinyUSBDevice.allocInterface(2);
|
||||
ep_in = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
|
||||
}
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
tusb_desc_interface_t itf;
|
||||
tusb_desc_video_control_header_1itf_t header;
|
||||
tusb_desc_video_control_camera_terminal_t camera_terminal;
|
||||
tusb_desc_video_control_output_terminal_t output_terminal;
|
||||
} uvc_control_desc_t;
|
||||
|
||||
// hard code for now
|
||||
#define UVC_CLOCK_FREQUENCY 27000000
|
||||
|
||||
/* Windows support YUY2 and NV12
|
||||
* https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview
|
||||
*/
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
tusb_desc_interface_t itf;
|
||||
tusb_desc_video_streaming_input_header_1byte_t header;
|
||||
tusb_desc_video_format_uncompressed_t format;
|
||||
tusb_desc_video_frame_uncompressed_continuous_t frame;
|
||||
tusb_desc_video_streaming_color_matching_t color;
|
||||
|
||||
// #if USE_ISO_STREAMING
|
||||
// // For ISO streaming, USB spec requires to alternate interface
|
||||
// tusb_desc_interface_t itf_alt;
|
||||
// #endif
|
||||
|
||||
tusb_desc_endpoint_t ep;
|
||||
} uvc_streaming_desc_t;
|
||||
|
||||
const tusb_desc_interface_assoc_t desc_iad = {
|
||||
.bLength = sizeof(tusb_desc_interface_assoc_t),
|
||||
.bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION,
|
||||
|
||||
.bFirstInterface = itfnum,
|
||||
.bInterfaceCount = 2,
|
||||
.bFunctionClass = TUSB_CLASS_VIDEO,
|
||||
.bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION,
|
||||
.bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED,
|
||||
.iFunction = 0};
|
||||
|
||||
uvc_control_desc_t desc_video_control{
|
||||
.itf = {.bLength = sizeof(tusb_desc_interface_t),
|
||||
.bDescriptorType = TUSB_DESC_INTERFACE,
|
||||
|
||||
.bInterfaceNumber = itfnum,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 0,
|
||||
.bInterfaceClass = TUSB_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL,
|
||||
.bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15,
|
||||
.iInterface = _strid},
|
||||
.header = {.bLength = sizeof(tusb_desc_video_control_header_1itf_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER,
|
||||
|
||||
.bcdUVC = VIDEO_BCD_1_50,
|
||||
.wTotalLength =
|
||||
sizeof(uvc_control_desc_t) -
|
||||
sizeof(tusb_desc_interface_t), // CS VC descriptors only
|
||||
.dwClockFrequency = UVC_CLOCK_FREQUENCY,
|
||||
.bInCollection = 1,
|
||||
.baInterfaceNr = {(uint8_t)(itfnum + 1)}},
|
||||
.camera_terminal = _camera_terminal,
|
||||
.output_terminal = _output_terminal};
|
||||
|
||||
uvc_streaming_desc_t desc_video_streaming = {
|
||||
.itf =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_interface_t),
|
||||
.bDescriptorType = TUSB_DESC_INTERFACE,
|
||||
|
||||
.bInterfaceNumber = (uint8_t)(itfnum + 1),
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1, // bulk 1, iso 0
|
||||
.bInterfaceClass = TUSB_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING,
|
||||
.bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15,
|
||||
.iInterface = _strid,
|
||||
},
|
||||
.header = {.bLength =
|
||||
sizeof(tusb_desc_video_streaming_input_header_1byte_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER,
|
||||
|
||||
.bNumFormats = 1,
|
||||
.wTotalLength =
|
||||
sizeof(uvc_streaming_desc_t) -
|
||||
sizeof(tusb_desc_interface_t) -
|
||||
sizeof(tusb_desc_endpoint_t), // CS VS descriptors only
|
||||
.bEndpointAddress = ep_in,
|
||||
.bmInfo = 0,
|
||||
.bTerminalLink = _output_terminal.bTerminalID,
|
||||
.bStillCaptureMethod = 0,
|
||||
.bTriggerSupport = 0,
|
||||
.bTriggerUsage = 0,
|
||||
.bControlSize = 1,
|
||||
.bmaControls = {0}},
|
||||
.format = _format.uncompressed,
|
||||
.frame = _frame.uncompressed_cont,
|
||||
.color = _color_matching,
|
||||
.ep = {.bLength = sizeof(tusb_desc_endpoint_t),
|
||||
.bDescriptorType = TUSB_DESC_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = ep_in,
|
||||
.bmAttributes = {.xfer = TUSB_XFER_BULK, .sync = 0},
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1}};
|
||||
|
||||
uint16_t const len_iad = sizeof(desc_iad);
|
||||
uint16_t const len_vc = sizeof(desc_video_control);
|
||||
uint16_t const len_vs = sizeof(desc_video_streaming);
|
||||
uint16_t const len_total = len_iad + len_vc + len_vs;
|
||||
|
||||
if (buf) {
|
||||
if (bufsize < len_total) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, &desc_iad, len_iad);
|
||||
buf += len_iad;
|
||||
|
||||
memcpy(buf, &desc_video_control, len_vc);
|
||||
buf += len_vc;
|
||||
|
||||
memcpy(buf, &desc_video_streaming, len_vs);
|
||||
}
|
||||
|
||||
return len_total;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -31,21 +31,48 @@
|
|||
|
||||
class Adafruit_USBD_Video : public Adafruit_USBD_Interface {
|
||||
public:
|
||||
Adafruit_USBD_Video(uint8_t const *desc_itf, size_t desc_len);
|
||||
Adafruit_USBD_Video(void);
|
||||
|
||||
bool begin();
|
||||
|
||||
//------------- API -------------//
|
||||
//------------- Video Control -------------//
|
||||
// bool isStreaming(uint8_t stream_idx);
|
||||
bool
|
||||
addTerminal(tusb_desc_video_control_camera_terminal_t const *camera_terminal);
|
||||
bool
|
||||
addTerminal(tusb_desc_video_control_output_terminal_t const *output_terminal);
|
||||
|
||||
//------------- Video Streaming -------------//
|
||||
// bool setIsochronousStreaming(bool enabled);
|
||||
|
||||
// Add format descriptor, return format index
|
||||
bool addFormat(tusb_desc_video_format_uncompressed_t const *format);
|
||||
bool addFrame(tusb_desc_video_frame_uncompressed_continuous_t const *frame);
|
||||
void
|
||||
addColorMatching(tusb_desc_video_streaming_color_matching_t const *color);
|
||||
|
||||
// from Adafruit_USBD_Interface
|
||||
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum_deprecated,
|
||||
uint8_t *buf, uint16_t bufsize);
|
||||
|
||||
private:
|
||||
uint8_t const *_desc_itf;
|
||||
size_t _desc_len;
|
||||
uint8_t _vc_id;
|
||||
|
||||
tusb_desc_video_control_camera_terminal_t _camera_terminal;
|
||||
tusb_desc_video_control_output_terminal_t _output_terminal;
|
||||
|
||||
// currently only support 1 format
|
||||
union {
|
||||
tusb_desc_video_format_uncompressed_t uncompressed;
|
||||
tusb_desc_video_format_mjpeg_t mjpeg;
|
||||
} _format;
|
||||
|
||||
union {
|
||||
tusb_desc_video_frame_uncompressed_continuous_t uncompressed_cont;
|
||||
tusb_desc_video_frame_mjpeg_continuous_t mjpeg;
|
||||
} _frame;
|
||||
|
||||
tusb_desc_video_streaming_color_matching_t _color_matching;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -85,12 +85,13 @@ typedef struct {
|
|||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
|
||||
uint8_t serial_drid; // Serial Driver ID
|
||||
cdc_acm_capability_t acm_capability;
|
||||
uint8_t ep_notif;
|
||||
uint8_t serial_drid; // Serial Driver ID
|
||||
bool mounted; // Enumeration is complete
|
||||
cdc_acm_capability_t acm_capability;
|
||||
|
||||
uint8_t line_state; // DTR (bit0), RTS (bit1)
|
||||
TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width
|
||||
uint8_t line_state; // DTR (bit0), RTS (bit1)
|
||||
|
||||
#if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X
|
||||
cdc_line_coding_t requested_line_coding;
|
||||
|
|
@ -337,7 +338,8 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) {
|
|||
|
||||
bool tuh_cdc_mounted(uint8_t idx) {
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
return p_cdc != NULL;
|
||||
TU_VERIFY(p_cdc);
|
||||
return p_cdc->mounted;
|
||||
}
|
||||
|
||||
bool tuh_cdc_get_dtr(uint8_t idx) {
|
||||
|
|
@ -676,9 +678,9 @@ void cdch_close(uint8_t daddr) {
|
|||
// Invoke application callback
|
||||
if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx);
|
||||
|
||||
//tu_memclr(p_cdc, sizeof(cdch_interface_t));
|
||||
p_cdc->daddr = 0;
|
||||
p_cdc->bInterfaceNumber = 0;
|
||||
p_cdc->mounted = false;
|
||||
tu_edpt_stream_close(&p_cdc->stream.tx);
|
||||
tu_edpt_stream_close(&p_cdc->stream.rx);
|
||||
}
|
||||
|
|
@ -779,6 +781,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d
|
|||
|
||||
static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) {
|
||||
TU_LOG_DRV("CDCh Set Configure complete\r\n");
|
||||
p_cdc->mounted = true;
|
||||
if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx);
|
||||
|
||||
// Prepare for incoming data
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@
|
|||
|
||||
#include "common/tusb_common.h"
|
||||
|
||||
enum {
|
||||
VIDEO_BCD_1_50 = 0x0150,
|
||||
};
|
||||
|
||||
// Table 3-19 Color Matching Descriptor
|
||||
typedef enum {
|
||||
VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00,
|
||||
|
|
@ -198,55 +202,98 @@ typedef enum {
|
|||
} video_terminal_type_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Descriptors
|
||||
// Video Control (VC) Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* 2.3.4.2 */
|
||||
#define tusb_desc_video_control_header_nitf_t(_nitf) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t bLength; \
|
||||
uint8_t bDescriptorType; \
|
||||
uint8_t bDescriptorSubType; \
|
||||
uint16_t bcdUVC; \
|
||||
uint16_t wTotalLength; \
|
||||
uint32_t dwClockFrequency; /* deprecated */ \
|
||||
uint8_t bInCollection; \
|
||||
uint8_t baInterfaceNr[_nitf]; \
|
||||
}
|
||||
|
||||
typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t;
|
||||
typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t;
|
||||
typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t;
|
||||
typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t;
|
||||
typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint16_t bcdUVC;
|
||||
uint16_t wTotalLength;
|
||||
uint32_t dwClockFrequency;
|
||||
uint8_t bInCollection;
|
||||
uint8_t baInterfaceNr[];
|
||||
} tusb_desc_cs_video_ctl_itf_hdr_t;
|
||||
uint8_t bTerminalID;
|
||||
uint16_t wTerminalType;
|
||||
uint8_t bAssocTerminal;
|
||||
uint8_t iTerminal;
|
||||
} tusb_desc_video_control_input_terminal_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_input_terminal_t) == 8, "size is not correct");
|
||||
|
||||
/* 2.4.3.3 */
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bHeaderLength;
|
||||
union {
|
||||
uint8_t bmHeaderInfo;
|
||||
struct {
|
||||
uint8_t FrameID: 1;
|
||||
uint8_t EndOfFrame: 1;
|
||||
uint8_t PresentationTime: 1;
|
||||
uint8_t SourceClockReference: 1;
|
||||
uint8_t PayloadSpecific: 1;
|
||||
uint8_t StillImage: 1;
|
||||
uint8_t Error: 1;
|
||||
uint8_t EndOfHeader: 1;
|
||||
};
|
||||
};
|
||||
} tusb_video_payload_header_t;
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bTerminalID;
|
||||
uint16_t wTerminalType;
|
||||
uint8_t bAssocTerminal;
|
||||
uint8_t bSourceID;
|
||||
uint8_t iTerminal;
|
||||
} tusb_desc_video_control_output_terminal_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_output_terminal_t) == 9, "size is not correct");
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bTerminalID;
|
||||
uint16_t wTerminalType;
|
||||
uint8_t bAssocTerminal;
|
||||
uint8_t iTerminal;
|
||||
|
||||
uint16_t wObjectiveFocalLengthMin;
|
||||
uint16_t wObjectiveFocalLengthMax;
|
||||
uint16_t wOcularFocalLength;
|
||||
uint8_t bControlSize;
|
||||
uint8_t bmControls[3];
|
||||
} tusb_desc_video_control_camera_terminal_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_camera_terminal_t) == 18, "size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Video Streaming (VS) Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* 3.9.2.1 */
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bNumFormats;
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmInfo;
|
||||
uint8_t bTerminalLink;
|
||||
uint8_t bStillCaptureMethod;
|
||||
uint8_t bTriggerSupport;
|
||||
uint8_t bTriggerUsage;
|
||||
uint8_t bControlSize;
|
||||
uint8_t bmaControls[];
|
||||
} tusb_desc_cs_video_stm_itf_in_hdr_t;
|
||||
#define tusb_desc_video_streaming_input_header_nbyte_t(_nb) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t bLength; \
|
||||
uint8_t bDescriptorType; \
|
||||
uint8_t bDescriptorSubType; \
|
||||
uint8_t bNumFormats; /* Number of video payload Format descriptors for this interface */ \
|
||||
uint16_t wTotalLength; \
|
||||
uint8_t bEndpointAddress; \
|
||||
uint8_t bmInfo; /* Bit 0: dynamic format change supported */ \
|
||||
uint8_t bTerminalLink; \
|
||||
uint8_t bStillCaptureMethod; \
|
||||
uint8_t bTriggerSupport; /* Hardware trigger supported */ \
|
||||
uint8_t bTriggerUsage; \
|
||||
uint8_t bControlSize; /* sizeof of each control item */ \
|
||||
uint8_t bmaControls[_nb]; \
|
||||
}
|
||||
|
||||
typedef tusb_desc_video_streaming_input_header_nbyte_t() tusb_desc_video_streaming_input_header_t;
|
||||
typedef tusb_desc_video_streaming_input_header_nbyte_t(1) tusb_desc_video_streaming_input_header_1byte_t;
|
||||
typedef tusb_desc_video_streaming_input_header_nbyte_t(2) tusb_desc_video_streaming_input_header_2byte_t;
|
||||
typedef tusb_desc_video_streaming_input_header_nbyte_t(3) tusb_desc_video_streaming_input_header_3byte_t;
|
||||
typedef tusb_desc_video_streaming_input_header_nbyte_t(4) tusb_desc_video_streaming_input_header_4byte_t;
|
||||
|
||||
/* 3.9.2.2 */
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
|
|
@ -259,7 +306,7 @@ typedef struct TU_ATTR_PACKED {
|
|||
uint8_t bTerminalLink;
|
||||
uint8_t bControlSize;
|
||||
uint8_t bmaControls[];
|
||||
} tusb_desc_cs_video_stm_itf_out_hdr_t;
|
||||
} tusb_desc_video_streaming_output_header_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
|
|
@ -285,37 +332,99 @@ typedef struct TU_ATTR_PACKED {
|
|||
uint8_t bmaControls[];
|
||||
} output;
|
||||
};
|
||||
} tusb_desc_cs_video_stm_itf_hdr_t;
|
||||
} tusb_desc_video_streaming_inout_header_t;
|
||||
|
||||
// 3.9.2.6 Color Matching Descriptor
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bColorPrimaries;
|
||||
uint8_t bTransferCharacteristics;
|
||||
uint8_t bMatrixCoefficients;
|
||||
} tusb_desc_video_streaming_color_matching_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(tusb_desc_video_streaming_color_matching_t) == 6, "size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Format and Frame Descriptor
|
||||
// Note: bFormatIndex & bFrameIndex are 1-based index
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//------------- Uncompressed -------------//
|
||||
// Uncompressed payload specs: 3.1.1 format descriptor
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFormatIndex;
|
||||
uint8_t bNumFrameDescriptors;
|
||||
uint8_t bNumFrameDescriptors; // Number of frame descriptors for this format
|
||||
uint8_t guidFormat[16];
|
||||
uint8_t bBitsPerPixel;
|
||||
uint8_t bDefaultFrameIndex;
|
||||
uint8_t bDefaultFrameIndex; //
|
||||
uint8_t bAspectRatioX;
|
||||
uint8_t bAspectRatioY;
|
||||
uint8_t bmInterlaceFlags;
|
||||
uint8_t bCopyProtect;
|
||||
} tusb_desc_cs_video_fmt_uncompressed_t;
|
||||
} tusb_desc_video_format_uncompressed_t;
|
||||
|
||||
// Uncompressed payload specs: 3.1.2 frame descriptor
|
||||
#define tusb_desc_video_frame_uncompressed_nint_t(_nint) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t bLength; \
|
||||
uint8_t bDescriptorType; \
|
||||
uint8_t bDescriptorSubType; \
|
||||
uint8_t bFrameIndex; \
|
||||
uint8_t bmCapabilities; \
|
||||
uint16_t wWidth; \
|
||||
uint16_t wHeight; \
|
||||
uint32_t dwMinBitRate; \
|
||||
uint32_t dwMaxBitRate; \
|
||||
uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \
|
||||
uint32_t dwDefaultFrameInterval; \
|
||||
uint8_t bFrameIntervalType; \
|
||||
uint32_t dwFrameInterval[_nint]; \
|
||||
}
|
||||
|
||||
typedef tusb_desc_video_frame_uncompressed_nint_t() tusb_desc_video_frame_uncompressed_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_nint_t(1) tusb_desc_video_frame_uncompressed_1int_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_nint_t(2) tusb_desc_video_frame_uncompressed_2int_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_nint_t(3) tusb_desc_video_frame_uncompressed_3int_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_nint_t(4) tusb_desc_video_frame_uncompressed_4int_t;
|
||||
|
||||
// continuous = 3 intervals: min, max, step
|
||||
typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_uncompressed_continuous_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(tusb_desc_video_frame_uncompressed_continuous_t) == 38, "size is not correct");
|
||||
|
||||
//------------- MJPEG -------------//
|
||||
// MJPEG payload specs: 3.1.1 format descriptor
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFormatIndex;
|
||||
uint8_t bNumFrameDescriptors;
|
||||
uint8_t bmFlags;
|
||||
uint8_t bmFlags; // Bit 0: fixed size samples (1 = yes)
|
||||
uint8_t bDefaultFrameIndex;
|
||||
uint8_t bAspectRatioX;
|
||||
uint8_t bAspectRatioY;
|
||||
uint8_t bmInterlaceFlags;
|
||||
uint8_t bCopyProtect;
|
||||
} tusb_desc_cs_video_fmt_mjpeg_t;
|
||||
} tusb_desc_video_format_mjpeg_t;
|
||||
|
||||
// MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed)
|
||||
typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_2int_t tusb_desc_video_frame_mjpeg_2int_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_mjpeg_3int_t;
|
||||
typedef tusb_desc_video_frame_uncompressed_4int_t tusb_desc_video_frame_mjpeg_4int_t;
|
||||
|
||||
// continuous = 3 intervals: min, max, step
|
||||
typedef tusb_desc_video_frame_mjpeg_3int_t tusb_desc_video_frame_mjpeg_continuous_t;
|
||||
|
||||
//------------- DV -------------//
|
||||
// DV payload specs: 3.1.1
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
|
|
@ -323,8 +432,9 @@ typedef struct TU_ATTR_PACKED {
|
|||
uint8_t bFormatIndex;
|
||||
uint32_t dwMaxVideoFrameBufferSize; /* deprecated */
|
||||
uint8_t bFormatType;
|
||||
} tusb_desc_cs_video_fmt_dv_t;
|
||||
} tusb_desc_video_format_dv_t;
|
||||
|
||||
// Frame Based payload specs: 3.1.1
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
|
|
@ -339,25 +449,7 @@ typedef struct TU_ATTR_PACKED {
|
|||
uint8_t bmInterlaceFlags;
|
||||
uint8_t bCopyProtect;
|
||||
uint8_t bVaribaleSize;
|
||||
} tusb_desc_cs_video_fmt_frame_based_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubType;
|
||||
uint8_t bFrameIndex;
|
||||
uint8_t bmCapabilities;
|
||||
uint16_t wWidth;
|
||||
uint16_t wHeight;
|
||||
uint32_t dwMinBitRate;
|
||||
uint32_t dwMaxBitRate;
|
||||
uint32_t dwMaxVideoFrameBufferSize; /* deprecated */
|
||||
uint32_t dwDefaultFrameInterval;
|
||||
uint8_t bFrameIntervalType;
|
||||
uint32_t dwFrameInterval[];
|
||||
} tusb_desc_cs_video_frm_uncompressed_t;
|
||||
|
||||
typedef tusb_desc_cs_video_frm_uncompressed_t tusb_desc_cs_video_frm_mjpeg_t;
|
||||
} tusb_desc_video_format_framebased_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
|
|
@ -373,12 +465,30 @@ typedef struct TU_ATTR_PACKED {
|
|||
uint8_t bFrameIntervalType;
|
||||
uint32_t dwBytesPerLine;
|
||||
uint32_t dwFrameInterval[];
|
||||
} tusb_desc_cs_video_frm_frame_based_t;
|
||||
} tusb_desc_video_frame_framebased_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Requests
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* 2.4.3.3 */
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bHeaderLength;
|
||||
union {
|
||||
uint8_t bmHeaderInfo;
|
||||
struct {
|
||||
uint8_t FrameID: 1;
|
||||
uint8_t EndOfFrame: 1;
|
||||
uint8_t PresentationTime: 1;
|
||||
uint8_t SourceClockReference: 1;
|
||||
uint8_t PayloadSpecific: 1;
|
||||
uint8_t StillImage: 1;
|
||||
uint8_t Error: 1;
|
||||
uint8_t EndOfHeader: 1;
|
||||
};
|
||||
};
|
||||
} tusb_video_payload_header_t;
|
||||
|
||||
/* 4.3.1.1 */
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
union {
|
||||
|
|
@ -537,7 +647,7 @@ TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not c
|
|||
/* Motion-JPEG 3.1.1 Table 3-2 and 3-4 */
|
||||
#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \
|
||||
TUSB_DESC_CS_INTERFACE, VIDEO_CS_VS_INTERFACE_FRAME_MJPEG, \
|
||||
TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_MJPEG, \
|
||||
_frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \
|
||||
U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__
|
||||
|
||||
|
|
|
|||
|
|
@ -55,17 +55,17 @@
|
|||
|
||||
typedef struct {
|
||||
tusb_desc_interface_t std;
|
||||
tusb_desc_cs_video_ctl_itf_hdr_t ctl;
|
||||
tusb_desc_video_control_header_t ctl;
|
||||
} tusb_desc_vc_itf_t;
|
||||
|
||||
typedef struct {
|
||||
tusb_desc_interface_t std;
|
||||
tusb_desc_cs_video_stm_itf_hdr_t stm;
|
||||
tusb_desc_video_streaming_inout_header_t stm;
|
||||
} tusb_desc_vs_itf_t;
|
||||
|
||||
typedef union {
|
||||
tusb_desc_cs_video_ctl_itf_hdr_t ctl;
|
||||
tusb_desc_cs_video_stm_itf_hdr_t stm;
|
||||
tusb_desc_video_control_header_t ctl;
|
||||
tusb_desc_video_streaming_inout_header_t stm;
|
||||
} tusb_desc_video_itf_hdr_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
|
|
@ -83,9 +83,9 @@ typedef union {
|
|||
uint8_t bFormatIndex;
|
||||
uint8_t bNumFrameDescriptors;
|
||||
};
|
||||
tusb_desc_cs_video_fmt_uncompressed_t uncompressed;
|
||||
tusb_desc_cs_video_fmt_mjpeg_t mjpeg;
|
||||
tusb_desc_cs_video_fmt_frame_based_t frame_based;
|
||||
tusb_desc_video_format_uncompressed_t uncompressed;
|
||||
tusb_desc_video_format_mjpeg_t mjpeg;
|
||||
tusb_desc_video_format_framebased_t frame_based;
|
||||
} tusb_desc_cs_video_fmt_t;
|
||||
|
||||
typedef union {
|
||||
|
|
@ -98,9 +98,9 @@ typedef union {
|
|||
uint16_t wWidth;
|
||||
uint16_t wHeight;
|
||||
};
|
||||
tusb_desc_cs_video_frm_uncompressed_t uncompressed;
|
||||
tusb_desc_cs_video_frm_mjpeg_t mjpeg;
|
||||
tusb_desc_cs_video_frm_frame_based_t frame_based;
|
||||
tusb_desc_video_frame_uncompressed_t uncompressed;
|
||||
tusb_desc_video_frame_mjpeg_t mjpeg;
|
||||
tusb_desc_video_frame_framebased_t frame_based;
|
||||
} tusb_desc_cs_video_frm_t;
|
||||
|
||||
/* video streaming interface */
|
||||
|
|
@ -439,8 +439,9 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm
|
|||
uint_fast32_t interval_ms = interval / 10000;
|
||||
TU_ASSERT(interval_ms);
|
||||
uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2;
|
||||
if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size)
|
||||
if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) {
|
||||
payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE;
|
||||
}
|
||||
param->dwMaxPayloadTransferSize = payload_size;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -582,8 +583,9 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *
|
|||
} else {
|
||||
payload_size = (frame_size + interval_ms - 1) / interval_ms + 2;
|
||||
}
|
||||
if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size)
|
||||
if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) {
|
||||
payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE;
|
||||
}
|
||||
param->dwMaxPayloadTransferSize = payload_size;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -44,43 +44,38 @@
|
|||
*------------------------------------------------------------------*/
|
||||
|
||||
/// defined base on EHCI specs value for Endpoint Speed
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_SPEED_FULL = 0,
|
||||
TUSB_SPEED_LOW = 1,
|
||||
TUSB_SPEED_HIGH = 2,
|
||||
TUSB_SPEED_INVALID = 0xff,
|
||||
}tusb_speed_t;
|
||||
} tusb_speed_t;
|
||||
|
||||
/// defined base on USB Specs Endpoint's bmAttributes
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_XFER_CONTROL = 0 ,
|
||||
TUSB_XFER_ISOCHRONOUS ,
|
||||
TUSB_XFER_BULK ,
|
||||
TUSB_XFER_INTERRUPT
|
||||
}tusb_xfer_type_t;
|
||||
} tusb_xfer_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_DIR_OUT = 0,
|
||||
TUSB_DIR_IN = 1,
|
||||
|
||||
TUSB_DIR_IN_MASK = 0x80
|
||||
}tusb_dir_t;
|
||||
} tusb_dir_t;
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
TUSB_EPSIZE_BULK_FS = 64,
|
||||
TUSB_EPSIZE_BULK_HS= 512,
|
||||
TUSB_EPSIZE_BULK_HS = 512,
|
||||
|
||||
TUSB_EPSIZE_ISO_FS_MAX = 1023,
|
||||
TUSB_EPSIZE_ISO_HS_MAX = 1024,
|
||||
};
|
||||
|
||||
/// Isochronous End Point Attributes
|
||||
typedef enum
|
||||
{
|
||||
/// Isochronous Endpoint Attributes
|
||||
typedef enum {
|
||||
TUSB_ISO_EP_ATT_NO_SYNC = 0x00,
|
||||
TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04,
|
||||
TUSB_ISO_EP_ATT_ADAPTIVE = 0x08,
|
||||
|
|
@ -88,11 +83,10 @@ typedef enum
|
|||
TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point
|
||||
TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point
|
||||
TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback
|
||||
}tusb_iso_ep_attribute_t;
|
||||
} tusb_iso_ep_attribute_t;
|
||||
|
||||
/// USB Descriptor Types
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_DESC_DEVICE = 0x01,
|
||||
TUSB_DESC_CONFIGURATION = 0x02,
|
||||
TUSB_DESC_STRING = 0x03,
|
||||
|
|
@ -119,10 +113,9 @@ typedef enum
|
|||
|
||||
TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30,
|
||||
TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31
|
||||
}tusb_desc_type_t;
|
||||
} tusb_desc_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_REQ_GET_STATUS = 0 ,
|
||||
TUSB_REQ_CLEAR_FEATURE = 1 ,
|
||||
TUSB_REQ_RESERVED = 2 ,
|
||||
|
|
@ -136,25 +129,22 @@ typedef enum
|
|||
TUSB_REQ_GET_INTERFACE = 10 ,
|
||||
TUSB_REQ_SET_INTERFACE = 11 ,
|
||||
TUSB_REQ_SYNCH_FRAME = 12
|
||||
}tusb_request_code_t;
|
||||
} tusb_request_code_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_REQ_FEATURE_EDPT_HALT = 0,
|
||||
TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1,
|
||||
TUSB_REQ_FEATURE_TEST_MODE = 2
|
||||
}tusb_request_feature_selector_t;
|
||||
} tusb_request_feature_selector_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_REQ_TYPE_STANDARD = 0,
|
||||
TUSB_REQ_TYPE_CLASS,
|
||||
TUSB_REQ_TYPE_VENDOR,
|
||||
TUSB_REQ_TYPE_INVALID
|
||||
} tusb_request_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_REQ_RCPT_DEVICE =0,
|
||||
TUSB_REQ_RCPT_INTERFACE,
|
||||
TUSB_REQ_RCPT_ENDPOINT,
|
||||
|
|
@ -162,8 +152,7 @@ typedef enum
|
|||
} tusb_request_recipient_t;
|
||||
|
||||
// https://www.usb.org/defined-class-codes
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
TUSB_CLASS_UNSPECIFIED = 0 ,
|
||||
TUSB_CLASS_AUDIO = 1 ,
|
||||
TUSB_CLASS_CDC = 2 ,
|
||||
|
|
@ -187,26 +176,23 @@ typedef enum
|
|||
TUSB_CLASS_MISC = 0xEF ,
|
||||
TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE ,
|
||||
TUSB_CLASS_VENDOR_SPECIFIC = 0xFF
|
||||
}tusb_class_code_t;
|
||||
} tusb_class_code_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MISC_SUBCLASS_COMMON = 2
|
||||
}misc_subclass_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
MISC_PROTOCOL_IAD = 1
|
||||
}misc_protocol_type_t;
|
||||
} misc_protocol_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
APP_SUBCLASS_USBTMC = 0x03,
|
||||
APP_SUBCLASS_DFU_RUNTIME = 0x01
|
||||
} app_subclass_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
DEVICE_CAPABILITY_WIRELESS_USB = 0x01,
|
||||
DEVICE_CAPABILITY_USB20_EXTENSION = 0x02,
|
||||
DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03,
|
||||
|
|
@ -223,7 +209,7 @@ typedef enum
|
|||
DEVICE_CAPABILITY_AUTHENTICATION = 0x0E,
|
||||
DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F,
|
||||
DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10
|
||||
}device_capability_type_t;
|
||||
} device_capability_type_t;
|
||||
|
||||
enum {
|
||||
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5),
|
||||
|
|
@ -235,28 +221,25 @@ enum {
|
|||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
XFER_RESULT_SUCCESS = 0,
|
||||
XFER_RESULT_FAILED,
|
||||
XFER_RESULT_STALLED,
|
||||
XFER_RESULT_TIMEOUT,
|
||||
XFER_RESULT_INVALID
|
||||
}xfer_result_t;
|
||||
} xfer_result_t;
|
||||
|
||||
enum // TODO remove
|
||||
{
|
||||
// TODO remove
|
||||
enum {
|
||||
DESC_OFFSET_LEN = 0,
|
||||
DESC_OFFSET_TYPE = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
INTERFACE_INVALID_NUMBER = 0xff
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00,
|
||||
MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01,
|
||||
MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02,
|
||||
|
|
@ -268,16 +251,14 @@ typedef enum
|
|||
MS_OS_20_FEATURE_VENDOR_REVISION = 0x08
|
||||
} microsoft_os_20_type_t;
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
CONTROL_STAGE_IDLE,
|
||||
CONTROL_STAGE_SETUP,
|
||||
CONTROL_STAGE_DATA,
|
||||
CONTROL_STAGE_ACK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
TUSB_INDEX_INVALID_8 = 0xFFu
|
||||
};
|
||||
|
||||
|
|
@ -290,8 +271,7 @@ TU_ATTR_PACKED_BEGIN
|
|||
TU_ATTR_BIT_FIELD_ORDER_BEGIN
|
||||
|
||||
/// USB Device Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< DEVICE Descriptor Type.
|
||||
uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant.
|
||||
|
|
@ -314,8 +294,7 @@ typedef struct TU_ATTR_PACKED
|
|||
TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct");
|
||||
|
||||
// USB Binary Device Object Store (BOS) Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type
|
||||
uint16_t wTotalLength ; ///< Total length of data returned for this descriptor
|
||||
|
|
@ -325,8 +304,7 @@ typedef struct TU_ATTR_PACKED
|
|||
TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct");
|
||||
|
||||
/// USB Configuration Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type
|
||||
uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration.
|
||||
|
|
@ -341,8 +319,7 @@ typedef struct TU_ATTR_PACKED
|
|||
TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct");
|
||||
|
||||
/// USB Interface Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type
|
||||
|
||||
|
|
@ -358,8 +335,7 @@ typedef struct TU_ATTR_PACKED
|
|||
TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct");
|
||||
|
||||
/// USB Endpoint Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; // Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType ; // ENDPOINT Descriptor Type
|
||||
|
||||
|
|
@ -379,8 +355,7 @@ typedef struct TU_ATTR_PACKED
|
|||
TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct");
|
||||
|
||||
/// USB Other Speed Configuration Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of descriptor
|
||||
uint8_t bDescriptorType ; ///< Other_speed_Configuration Type
|
||||
uint16_t wTotalLength ; ///< Total length of data returned
|
||||
|
|
@ -393,8 +368,7 @@ typedef struct TU_ATTR_PACKED
|
|||
} tusb_desc_other_speed_t;
|
||||
|
||||
/// USB Device Qualifier Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of descriptor
|
||||
uint8_t bDescriptorType ; ///< Device Qualifier Type
|
||||
uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00)
|
||||
|
|
@ -411,8 +385,7 @@ typedef struct TU_ATTR_PACKED
|
|||
TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct");
|
||||
|
||||
/// USB Interface Association Descriptor (IAD ECN)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of descriptor
|
||||
uint8_t bDescriptorType ; ///< Other_speed_Configuration Type
|
||||
|
||||
|
|
@ -426,17 +399,17 @@ typedef struct TU_ATTR_PACKED
|
|||
uint8_t iFunction ; ///< Index of the string descriptor describing the interface association.
|
||||
} tusb_desc_interface_assoc_t;
|
||||
|
||||
TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct");
|
||||
|
||||
// USB String Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type
|
||||
uint16_t unicode_string[];
|
||||
} tusb_desc_string_t;
|
||||
|
||||
// USB Binary Device Object Store (BOS)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType ;
|
||||
uint8_t bDevCapabilityType;
|
||||
|
|
@ -445,9 +418,8 @@ typedef struct TU_ATTR_PACKED
|
|||
uint8_t CapabilityData[];
|
||||
} tusb_desc_bos_platform_t;
|
||||
|
||||
// USB WebuSB URL Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
// USB WebUSB URL Descriptor
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bScheme;
|
||||
|
|
@ -455,8 +427,7 @@ typedef struct TU_ATTR_PACKED
|
|||
} tusb_desc_webusb_url_t;
|
||||
|
||||
// DFU Functional Descriptor
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
|
||||
|
|
@ -481,7 +452,7 @@ typedef struct TU_ATTR_PACKED
|
|||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
typedef struct TU_ATTR_PACKED{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
union {
|
||||
struct TU_ATTR_PACKED {
|
||||
uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t.
|
||||
|
|
@ -500,7 +471,6 @@ typedef struct TU_ATTR_PACKED{
|
|||
|
||||
TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct");
|
||||
|
||||
|
||||
TU_ATTR_PACKED_END // End of all packed definitions
|
||||
TU_ATTR_BIT_FIELD_ORDER_END
|
||||
|
||||
|
|
@ -509,36 +479,30 @@ TU_ATTR_BIT_FIELD_ORDER_END
|
|||
//--------------------------------------------------------------------+
|
||||
|
||||
// Get direction from Endpoint address
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) {
|
||||
return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
|
||||
}
|
||||
|
||||
// Get Endpoint number from address
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) {
|
||||
return (uint8_t)(addr & (~TUSB_DIR_IN_MASK));
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) {
|
||||
return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0));
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) {
|
||||
return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0);
|
||||
}
|
||||
|
||||
#if CFG_TUSB_DEBUG
|
||||
TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) {
|
||||
tu_static const char *str[] = {"out", "in"};
|
||||
return str[dir];
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) {
|
||||
tu_static const char *str[] = {"control", "isochronous", "bulk", "interrupt"};
|
||||
return str[t];
|
||||
}
|
||||
|
|
@ -549,21 +513,18 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_
|
|||
//--------------------------------------------------------------------+
|
||||
|
||||
// return next descriptor
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
|
||||
uint8_t const* desc8 = (uint8_t const*) desc;
|
||||
return desc8 + desc8[DESC_OFFSET_LEN];
|
||||
}
|
||||
|
||||
// get descriptor type
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
|
||||
return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
|
||||
}
|
||||
|
||||
// get descriptor length
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
|
||||
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue