This commit is contained in:
刘可亮
2024-09-03 11:16:08 +08:00
parent cf270df8d6
commit 803cac77d5
2931 changed files with 614364 additions and 31222 deletions

View File

@@ -12,6 +12,7 @@
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
#define DELAY_TIME_AFTER_RESET 200
#define HUB_CLEAR_FEATURE_CNT 20
#define EXTHUB_FIRST_INDEX 2
@@ -87,7 +88,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
if (ret < 0) {
return ret;
}
memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
return ret;
}
#if 0
@@ -184,7 +185,7 @@ static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
{
if (desc->bLength != USB_SIZEOF_HUB_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
USB_LOG_ERR("invalid hub bLength 0x%02x\r\n", desc->bLength);
return -1;
} else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB) {
USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
@@ -288,7 +289,8 @@ static void usbh_hubport_release(struct usbh_hubport *child)
}
child->config.config_desc.bNumInterfaces = 0;
usbh_kill_urb(&child->ep0_urb);
usb_osal_mutex_delete(child->mutex);
if (child->parent->is_roothub)
usb_osal_mutex_delete(child->mutex);
}
}
@@ -449,7 +451,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
uint16_t mask;
uint16_t feat;
uint8_t speed;
int ret;
int ret = 0, cnt = 0;
if (!hub->connected) {
return;
@@ -483,10 +485,14 @@ static void usbh_hub_events(struct usbh_hub *hub)
mask = 1;
feat = HUB_PORT_FEATURE_C_CONNECTION;
while (portchange) {
/* To avoid dead loops when hub power failure */
if (cnt >= HUB_CLEAR_FEATURE_CNT)
break;
cnt++;
if (portchange & mask) {
ret = usbh_hub_clear_feature(hub, port + 1, feat);
if (ret < 0) {
USB_LOG_ERR("Failed to clear port %u, change mask:%04x, errorcode:%d\r\n", port + 1, mask, ret);
USB_LOG_ERR("Failed to clear port %u, portchange:%04x, mask:%04x, feat:0x%x, errcode:%d\r\n", port + 1, portchange, mask, feat, ret);
continue;
}
portchange &= (~mask);
@@ -598,7 +604,13 @@ static void usbh_hub_events(struct usbh_hub *hub)
child->port = port + 1;
child->speed = speed;
child->bus = hub->bus;
child->mutex = usb_osal_mutex_create();
/* All child-hub share the same mutex. Otherwise if multiple child-hubs
* communicate simultaneously, resources will not be protected.
*/
if (hub->is_roothub)
child->mutex = usb_osal_mutex_create();
else
child->mutex = hub->bus->hcd.roothub.child[0].mutex;
USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
@@ -650,7 +662,7 @@ static void usbh_hub_thread(void *argument)
}
#ifdef KERNEL_BAREMETAL
#ifdef AIC_USING_USB0_HOST
#if defined(AIC_USING_USB0_HOST) || defined(AIC_USING_USB0_OTG)
extern struct usbh_bus *usb_ehci0_hs_bus;
int usb_ehci0_init = 0;
#endif
@@ -664,23 +676,15 @@ void usbh_hub_poll(void)
struct usbh_hub *hub;
struct usbh_bus *bus = NULL;
#ifdef AIC_USING_USB0_HOST
#if defined(AIC_USING_USB0_HOST) || defined(AIC_USING_USB0_OTG)
bus = usb_ehci0_hs_bus;
if (usb_ehci0_init == 0) {
usb_ehci0_init = 1;
usb_hc_init(bus);
}
if (!usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER))
if (bus->hub_mq && !usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, 1000))
usbh_hub_events(hub);
#endif
#ifdef AIC_USING_USB1_HOST
bus = usb_ehci1_hs_bus;
if (usb_ehci1_init == 0) {
usb_ehci1_init = 1;
usb_hc_init(bus);
}
if (!usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER))
if (bus->hub_mq && !usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, 1000))
usbh_hub_events(hub);
#endif
}
@@ -695,7 +699,8 @@ int usbh_hub_initialize(struct usbh_bus *bus)
{
char thread_name[32] = { 0 };
bus->hub_mq = usb_osal_mq_create(7);
if (bus->hub_mq == NULL)
bus->hub_mq = usb_osal_mq_create(7);
if (bus->hub_mq == NULL) {
USB_LOG_ERR("Failed to create hub mq\r\n");
return -1;
@@ -708,6 +713,8 @@ int usbh_hub_initialize(struct usbh_bus *bus)
USB_LOG_ERR("Failed to create hub thread\r\n");
return -1;
}
#else
usb_hc_init(bus);
#endif
return 0;
}
@@ -734,8 +741,10 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
usb_hc_deinit(bus);
usb_osal_leave_critical_section(flags);
#ifndef KERNEL_BAREMETAL
usb_osal_mq_delete(bus->hub_mq);
bus->hub_mq = NULL;
#endif
usb_osal_thread_delete(bus->hub_thread);
return 0;

View File

@@ -58,6 +58,11 @@ static void usbd_msc_reset(void)
g_usbd_msc.readonly = false;
}
__WEAK bool usbd_msc_check_storage(void)
{
return true;
}
static int msc_storage_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("MSC Class request: "
@@ -107,6 +112,15 @@ static void usbd_msc_bot_abort(void)
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&g_usbd_msc.cbw, USB_SIZEOF_MSC_CBW);
}
static void usb_msc_set_stall(void)
{
if ((g_usbd_msc.cbw.bmFlags == 0) && (g_usbd_msc.cbw.dDataLength != 0)) {
usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr);
}
usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr);
usbd_msc_thread_deinit();
}
static void usbd_msc_send_csw(uint8_t CSW_Status)
{
g_usbd_msc.csw.dSignature = MSC_CSW_Signature;
@@ -167,6 +181,13 @@ static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
}
*data = NULL;
*len = 0;
if (false == usbd_msc_check_storage()) {
g_usbd_msc.csw.dDataResidue = 0;
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
}
return true;
}
@@ -320,6 +341,7 @@ static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
{
//SCSI_MEDIUM_EJECTED;
g_usbd_msc.popup = true;
usbd_msc_set_popup();
} else if ((g_usbd_msc.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
{
//SCSI_MEDIUM_UNLOCKED;
@@ -421,6 +443,9 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_get_cap(0, &g_usbd_msc.scsi_blk_nbr, &g_usbd_msc.scsi_blk_size);
uint8_t format_capacity[SCSIRESP_READFORMATCAPACITIES_SIZEOF] = {
0x00,
0x00,
@@ -449,6 +474,8 @@ static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
return false;
}
usbd_msc_get_cap(0, &g_usbd_msc.scsi_blk_nbr, &g_usbd_msc.scsi_blk_size);
uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 24) & 0xff),
(uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 16) & 0xff),
@@ -461,6 +488,13 @@ static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
(uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
};
if (false == usbd_msc_check_storage()) {
g_usbd_msc.csw.dDataResidue = 0;
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usb_msc_set_stall();
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
}
memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
*len = SCSIRESP_READCAPACITY10_SIZEOF;
return true;
@@ -491,9 +525,20 @@ static bool SCSI_read10(uint8_t **data, uint32_t *len)
}
g_usbd_msc.stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
if (g_usbd_msc.usbd_msc_mq != NULL) {
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
} else {
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usb_msc_set_stall();
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
}
return true;
#else
if (false == usbd_msc_check_storage()) {
g_usbd_msc.csw.dDataResidue = 0;
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
}
return SCSI_processRead();
#endif
}
@@ -523,7 +568,13 @@ static bool SCSI_read12(uint8_t **data, uint32_t *len)
}
g_usbd_msc.stage = MSC_DATA_IN;
#ifdef CONFIG_USBDEV_MSC_THREAD
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
if (g_usbd_msc.usbd_msc_mq != NULL) {
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
} else {
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usb_msc_set_stall();
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
}
return true;
#else
return SCSI_processRead();
@@ -785,7 +836,14 @@ void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
case SCSI_CMD_WRITE12:
#ifdef CONFIG_USBDEV_MSC_THREAD
g_usbd_msc.nbytes = nbytes;
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_OUT);
if (g_usbd_msc.usbd_msc_mq != NULL) {
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_OUT);
} else {
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usb_msc_set_stall();
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
}
return;
#else
if (SCSI_processWrite(nbytes) == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -809,7 +867,15 @@ void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
#ifdef CONFIG_USBDEV_MSC_THREAD
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
g_usbd_msc.nbytes = nbytes;
if (g_usbd_msc.usbd_msc_mq != NULL) {
usb_osal_mq_send(g_usbd_msc.usbd_msc_mq, MSC_DATA_IN);
} else {
SCSI_SetSenseData(SCSI_KCQNR_MEDIANOTPRESENT);
usb_msc_set_stall();
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
return;
}
#else
if (SCSI_processRead() == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -850,6 +916,8 @@ static void usbdev_msc_thread(void *argument)
continue;
}
USB_LOG_DBG("%d\r\n", event);
if (false == usbd_msc_check_storage())
continue;
if (event == MSC_DATA_OUT) {
if (SCSI_processWrite(g_usbd_msc.nbytes) == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
@@ -864,6 +932,26 @@ static void usbdev_msc_thread(void *argument)
}
#endif
void usbd_msc_thread_deinit(void)
{
#ifdef CONFIG_USBDEV_MSC_THREAD
if (g_usbd_msc.usbd_msc_thread) {
usb_osal_thread_delete(g_usbd_msc.usbd_msc_thread);
}
g_usbd_msc.usbd_msc_thread = NULL;
#endif
}
void usbd_msc_thread_init(void)
{
#ifdef CONFIG_USBDEV_MSC_THREAD
g_usbd_msc.usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, NULL);
if (g_usbd_msc.usbd_msc_thread == NULL) {
return ;
}
#endif
}
struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep)
{
intf->class_interface_handler = msc_storage_class_interface_request_handler;
@@ -879,6 +967,11 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin
usbd_add_endpoint(&mass_ep_data[MSD_OUT_EP_IDX]);
usbd_add_endpoint(&mass_ep_data[MSD_IN_EP_IDX]);
#ifdef CONFIG_USBDEV_MSC_THREAD
if (g_usbd_msc.usbd_msc_mq != NULL)
usb_osal_mq_delete(g_usbd_msc.usbd_msc_mq);
#endif
memset((uint8_t *)&g_usbd_msc, 0, sizeof(struct usbd_msc_priv));
usbd_msc_get_cap(0, &g_usbd_msc.scsi_blk_nbr, &g_usbd_msc.scsi_blk_size);
@@ -888,16 +981,10 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin
return NULL;
}
#ifdef CONFIG_USBDEV_MSC_THREAD
#ifdef CONFIG_USBDEV_MSC_THREAD
g_usbd_msc.usbd_msc_mq = usb_osal_mq_create(1);
if (g_usbd_msc.usbd_msc_mq == NULL) {
return NULL;
}
g_usbd_msc.usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, NULL);
if (g_usbd_msc.usbd_msc_thread == NULL) {
return NULL;
}
#endif
#endif
return intf;
}
@@ -908,5 +995,6 @@ void usbd_msc_set_readonly(bool readonly)
bool usbd_msc_set_popup(void)
{
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED);
return g_usbd_msc.popup;
}

View File

@@ -23,7 +23,9 @@ int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_set_readonly(bool readonly);
bool usbd_msc_set_popup(void);
void usbd_msc_thread_init(void);
void usbd_msc_thread_deinit(void);
bool usbd_msc_check_storage(void);
#ifdef __cplusplus
}
#endif

View File

@@ -109,6 +109,22 @@ static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t
return ret;
}
static void usbh_msc_cbw_error_dump(struct CBW *cbw)
{
USB_LOG_INFO("CBW:\r\n");
USB_LOG_INFO("dSignature: 0x%08x\n", (unsigned int)cbw->dSignature);
USB_LOG_INFO("dTag: 0x%08x\n", (unsigned int)cbw->dTag);
USB_LOG_INFO("dDataLength:0x%08x\n", (unsigned int)cbw->dDataLength);
USB_LOG_INFO("bmFlags: 0x%02x\n", cbw->bmFlags);
USB_LOG_INFO("bCBLength: 0x%02x\n", cbw->bCBLength);
USB_LOG_INFO("scsi command: \r\n");
USB_LOG_INFO("CB[0]: 0x%02x\n", cbw->CB[0]);
USB_LOG_INFO("start sector: \r\n");
USB_LOG_INFO("CB[2:5]: 0x%02x%02x%02x%02x\n", cbw->CB[5], cbw->CB[4], cbw->CB[3], cbw->CB[2]);
USB_LOG_INFO("sector's num: \r\n");
USB_LOG_INFO("CB[7]: 0x%02x%02x\n", cbw->CB[8], cbw->CB[7]);
}
static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, struct CSW *csw, uint8_t *buffer)
{
int nbytes;
@@ -119,6 +135,7 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes < 0) {
USB_LOG_ERR("cbw transfer error\r\n");
usbh_msc_cbw_error_dump(cbw);
goto __err_exit;
}
@@ -137,7 +154,8 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
}
if (nbytes < 0) {
USB_LOG_ERR("msc data transfer error\r\n");
USB_LOG_ERR("msc data transfer error, nbytes:%d\r\n", nbytes);
usbh_msc_cbw_error_dump(cbw);
goto __err_exit;
}
}
@@ -146,7 +164,8 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
memset(csw, 0, USB_SIZEOF_MSC_CSW);
nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)csw, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
if (nbytes < 0) {
USB_LOG_ERR("csw transfer error\r\n");
USB_LOG_ERR("csw transfer error, nbytes:%d\r\n", nbytes);
usbh_msc_cbw_error_dump(cbw);
goto __err_exit;
}
@@ -154,12 +173,14 @@ static int usbh_bulk_cbw_csw_xfer(struct usbh_msc *msc_class, struct CBW *cbw, s
/* check csw status */
if (csw->dSignature != MSC_CSW_Signature) {
USB_LOG_ERR("csw signature error\r\n");
USB_LOG_ERR("csw signature error, dSignature: 0x%08x\r\n", (unsigned int)csw->dSignature);
usbh_msc_cbw_error_dump(cbw);
return -USB_ERR_INVAL;
}
if (csw->bStatus != 0) {
USB_LOG_ERR("csw bStatus %d\r\n", csw->bStatus);
USB_LOG_ERR("csw Status error, bStatus: %d\r\n", csw->bStatus);
usbh_msc_cbw_error_dump(cbw);
return -USB_ERR_INVAL;
}
__err_exit:

View File

@@ -806,14 +806,15 @@ struct video_still_probe_and_commit_controls {
struct video_cs_if_vc_header_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdVDC;
uint8_t bDescriptorSubType;
uint16_t bcdUVC;
uint16_t wTotalLength;
uint32_t dwClockFrequency;
uint8_t bInCollection;
uint8_t baInterfaceNr[];
} __PACKED;
#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (11 + n)
#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (12 + n)
struct video_cs_if_vc_input_terminal_descriptor {
uint8_t bLength;
@@ -860,6 +861,22 @@ struct video_cs_if_vc_output_terminal_descriptor {
#define VIDEO_SIZEOF_VC_OUTPUT_TERMINAL_DESC 9
struct video_cs_if_vc_extension_unit_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bUnitID;
uint8_t guidExtensionCode[16];
uint8_t bNumControls;
uint8_t bNrInPins;
// uint8_t baSourceID[];
uint8_t bControlSize;
// uint8_t bmControls[]
uint8_t iExtension;
} __PACKED;
#define VIDEO_SIZEOF_VC_EXTENSION_UNIT_DESC(p, n) (24 + p + n)
struct video_cs_ep_vc_ep_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -922,7 +939,7 @@ struct video_cs_if_vs_frame_uncompressed_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
@@ -931,10 +948,10 @@ struct video_cs_if_vs_frame_uncompressed_descriptor {
uint32_t dwMaxVideoFrameBufferSize;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwFrameInterval;
uint32_t dwFrameInterval[];
} __PACKED;
#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC 30
#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC(n) (26 + 4 * (n))
struct video_cs_if_vs_format_mjpeg_descriptor {
uint8_t bLength;
@@ -956,7 +973,7 @@ struct video_cs_if_vs_frame_mjpeg_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
@@ -965,11 +982,48 @@ struct video_cs_if_vs_frame_mjpeg_descriptor {
uint32_t dwMaxVideoFrameBufferSize;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwFrameInterval1;
uint32_t dwFrameInterval2;
uint32_t dwFrameInterval[];
} __PACKED;
#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + n)
#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + 4 * (n))
/* H264 Payload - 3.1.1. H264 Video Format Descriptor */
struct video_cs_if_vs_format_h26x_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bNumFrameDescriptors;
uint8_t guidFormat[16];
uint8_t bBitsPerPixel;
uint8_t bDefaultFrameIndex;
uint8_t bAspectRatioX;
uint8_t bAspectRatioY;
uint8_t bmInterfaceFlags;
uint8_t bCopyProtect;
uint8_t bVariableSize;
} __PACKED;
#define VIDEO_SIZEOF_VS_FORMAT_H264_DESC 28
/* H264 Payload - 3.1.2. H264 Video Frame Descriptor */
struct video_cs_if_vs_frame_h26x_descriptor {
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 dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwBytesPerLine;
uint32_t dwFrameInterval[];
} __PACKED;
#define VIDEO_SIZEOF_VS_FRAME_H264_DESC(n) (26 + 4 * (n))
struct video_cs_if_vs_colorformat_descriptor {
uint8_t bLength;
@@ -1041,74 +1095,148 @@ struct video_autoexposure_mode {
#define VIDEO_GUID_YUY2 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_NV12 0x4E, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_NV21 0x4E, 0x56, 0x32, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_M420 0x4D, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_I420 0x49, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_GUID_H264 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
#define VIDEO_PIXEL_YUY2 0x10
#define VIDEO_PIXEL_NV12 0x0c
#define VIDEO_VC_TERMINAL_LEN (13 + 18 + 12 + 9)
/*Length of template descriptor: 81 bytes*/
#define VIDEO_VC_DESCRIPTOR_LEN (8 + 9 + VIDEO_VC_TERMINAL_LEN + 7 + 5)
#define VIDEO_VC_NOEP_DESCRIPTOR_LEN (8 + 9 + VIDEO_VC_TERMINAL_LEN)
// clang-format off
#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bNumEndpoints, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
/* Interface Association Descriptor */ \
0x08, \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
bFirstInterface, \
0x02, \
USB_DEVICE_CLASS_VIDEO, \
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
0x00, \
0x00, \
/* VideoControl Interface Descriptor */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
bNumEndpoints, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ \
/*Class-specific VideoControl Interface Descriptor */ \
0x0d, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
WBVAL(wTotalLength), /* wTotalLength */ \
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
0x01, /* bInCollection : Number of streaming interfaces. */ \
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ \
/* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
0x12, \
0x24, \
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x01, /* bTerminalID */ \
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
0x00, /* bAssocTerminal */ \
0x00, /* iTerminal */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
WBVAL(0x0000), /* wOcularFocalLength */ \
0x03, /* bControlSize */ \
0x00, 0x00, 0x00, /* bmControls */ \
0x0c, \
0x24, \
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
0x02, /* bUnitID */ \
0x01, /* bSourceID */ \
0x00, 0x00, /* wMaxMultiplier */ \
0x02, /* bControlSize */ \
0x00, 0x00, /* bmControls */ \
0x00, /* iProcessing */ \
0x00, /* bmVideoStandards */ \
0x09, \
0x24, \
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x03, /* bTerminalID */ \
WBVAL(VIDEO_TT_STREAMING), \
0x00, /* bAssocTerminal */ \
0x02, /* bSourceID */ \
0x00 /* iTerminal */
#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bEndpointAddress, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
/* Interface Association Descriptor */ \
0x08, \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
bFirstInterface, \
0x02, \
USB_DEVICE_CLASS_VIDEO, \
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
0x00, \
0x00, /* VideoControl Interface Descriptor */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x01, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ /*Class-specific VideoControl Interface Descriptor */ \
0x0d, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
WBVAL(wTotalLength), /* wTotalLength */ \
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
0x01, /* bInCollection : Number of streaming interfaces. */ \
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
0x12, \
0x24, \
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x01, /* bTerminalID */ \
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
0x00, /* bAssocTerminal */ \
0x00, /* iTerminal */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
WBVAL(0x0000), /* wOcularFocalLength */ \
0x03, /* bControlSize */ \
0x00, 0x00, 0x00, /* bmControls */ \
0x0c, \
0x24, \
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
0x02, /* bUnitID */ \
0x01, /* bSourceID */ \
0x00, 0x00, /* wMaxMultiplier */ \
0x02, /* bControlSize */ \
0x00, 0x00, /* bmControls */ \
0x00, /* iProcessing */ \
0x00, /* bmVideoStandards */ \
0x09, \
0x24, \
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x03, /* bTerminalID */ \
WBVAL(VIDEO_TT_STREAMING), \
0x00, /* bAssocTerminal */ \
0x02, /* bSourceID */ \
0x00, /* iTerminal */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
bEndpointAddress, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x10, 0x00, /* wMaxPacketSize */ \
0x08, /* bInterval */ \
/* Class-specific VC Interrupt Endpoint Descriptor */ \
0x05, 0x25, 0x03, 0x10, 0x00
#define VIDEO_VC_NOEP_DESCRIPTOR_INIT(bFirstInterface, bEndpointAddress, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
/* Interface Association Descriptor */ \
0x08, \
USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
bFirstInterface, \
0x02, \
USB_DEVICE_CLASS_VIDEO, \
VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
0x00, \
0x00, /* VideoControl Interface Descriptor */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
stridx, /* iInterface:Index to string descriptor that contains the string <Your Product Name> */ /*Class-specific VideoControl Interface Descriptor */ \
0x0d, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
WBVAL(wTotalLength), /* wTotalLength */ \
DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
0x01, /* bInCollection : Number of streaming interfaces. */ \
(uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
0x12, \
0x24, \
VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x01, /* bTerminalID */ \
WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
0x00, /* bAssocTerminal */ \
0x00, /* iTerminal */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
WBVAL(0x0000), /* wOcularFocalLength */ \
0x03, /* bControlSize */ \
0x00, 0x00, 0x00, /* bmControls */ \
0x0c, \
0x24, \
VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
0x02, /* bUnitID */ \
0x01, /* bSourceID */ \
0x00, 0x00, /* wMaxMultiplier */ \
0x02, /* bControlSize */ \
0x00, 0x00, /* bmControls */ \
0x00, /* iProcessing */ \
0x00, /* bmVideoStandards */ \
0x09, \
0x24, \
VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
0x03, /* bTerminalID */ \
WBVAL(VIDEO_TT_STREAMING), \
0x00, /* bAssocTerminal */ \
0x02, /* bSourceID */ \
0x00 /* iTerminal */ \
#define VIDEO_VS_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints) \
/* Video Streaming (VS) Interface Descriptor */ \
0x09, /* bLength */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType : INTERFACE */ \
bInterfaceNumber, /* bInterfaceNumber: Index of this interface */ \
bAlternateSetting, /* bAlternateSetting: Index of this alternate setting */ \
@@ -1118,23 +1246,39 @@ struct video_autoexposure_mode {
0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
0x00 /* iInterface : unused */
#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
/*Class-specific VideoStream Header Descriptor (Input) */ \
0x0d + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
WBVAL(wTotalLength), \
bEndpointAddress, \
0x00, /* bmInfo : No dynamic format change supported. */ \
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
#define VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
/*Class-specific VideoStream Header Descriptor (Input) */ \
0x0d + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
WBVAL(wTotalLength), \
bEndpointAddress, \
0x00, /* bmInfo : No dynamic format change supported. */ \
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
0x01, /* bControlSize : Size of the bmaControls field */ \
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat) \
#define VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
/*Class-specific VideoStream Header Descriptor (Input) */ \
0x0d + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_SUBTYPE, \
bNumFormats, /* bNumFormats : One format descriptor follows. */ \
WBVAL(wTotalLength), \
bEndpointAddress, \
0x00, /* bmInfo : No dynamic format change supported. */ \
0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat, bBitsPerPixel) \
/*Payload Format(UNCOMPRESSED) Descriptor */ \
0x1b, \
0x24, \
@@ -1142,7 +1286,7 @@ struct video_autoexposure_mode {
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
GUIDFormat, /* GUID Format YUY2 {32595559-0000-0010-8000-00AA00389B71} */ \
0x0c, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
bBitsPerPixel, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
@@ -1150,8 +1294,8 @@ struct video_autoexposure_mode {
0x00 /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */
#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwFrameInterval) \
0x1e, \
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
0x1a + PP_NARG(__VA_ARGS__), \
0x24, \
VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, \
bFrameIndex, \
@@ -1161,13 +1305,13 @@ struct video_autoexposure_mode {
DBVAL(dwMinBitRate), \
DBVAL(dwMaxBitRate), \
DBVAL(dwMaxVideoFrameBufferSize), \
DBVAL(dwDefaultFrameInterval), \
0x01, \
DBVAL(dwFrameInterval)
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
__VA_ARGS__
#define VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
/*Payload Format(MJPEG) Descriptor */ \
0x0b, /* bLength */ \
0x0b, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
0x06, /* bDescriptorSubType : VS_FORMAT_MJPEG subtype */ \
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
@@ -1181,7 +1325,7 @@ struct video_autoexposure_mode {
#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_MJPEG */ \
bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
@@ -1194,5 +1338,46 @@ struct video_autoexposure_mode {
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
__VA_ARGS__
#define VIDEO_VS_FORMAT_H264_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
/*Payload Format(H.264) Descriptor */ \
0x1c, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_FORMAT_FRAME_BASED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FORMAT_FRAME_BASED subtype */\
bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
VIDEO_GUID_H264, \
0x00, /* bmFlags : Uses fixed size samples.. */ \
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
0x00, /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */ \
0x00 /* Variable size: False */
#define VIDEO_VS_FRAME_H264_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
dwDefaultFrameInterval, bFrameIntervalType, ...) \
0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_FRAME_FRAME_BASED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_BASED */ \
bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
0x00, /* bmCapabilities : Still images using capture method 0 are supported at this frame setting.D1: Fixed frame-rate. */ \
WBVAL(wWidth), /* wWidth (2bytes): Width of frame is 128 pixels. */ \
WBVAL(wHeight), /* wHeight (2bytes): Height of frame is 64 pixels. */ \
DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \
DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
DBVAL(0x00), /* dwBytesPerLine (4bytes) */ \
__VA_ARGS__
#define VIDEO_VS_COLOR_MATCHING_DESCRIPTOR_INIT() \
0x06, /* bLength */ \
0x24, /* bDescriptorType : CS_INTERFACE */ \
VIDEO_VS_COLORFORMAT_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_COLORFORMAT */ \
0x01, /* bColorPrimaries */ \
0x01, /* bTransferCharacteristics */ \
0x04 /* bMatrixCoefficients */
// clang-format on
#endif /*USB_VIDEO_H */
#endif /*USB_VIDEO_H */

View File

@@ -762,7 +762,7 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
return intf;
}
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
uint32_t usbd_video_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
{
uint32_t packets;
uint32_t last_packet_size;
@@ -786,4 +786,4 @@ uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8
uvc_header[1] ^= 1;
*out_len = (input_len + 2 * packets);
return packets;
}
}

View File

@@ -20,7 +20,7 @@ struct usbd_interface *usbd_video_init_intf(struct usbd_interface *intf,
void usbd_video_open(uint8_t intf);
void usbd_video_close(uint8_t intf);
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
uint32_t usbd_video_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
#ifdef __cplusplus
}