summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2022-02-17 17:21:17 +0800
committersakumisu <[email protected]>2022-02-17 17:21:17 +0800
commit7fdd66c632e52c92404ecc872e70da6f033e1433 (patch)
tree1e7315dc401a3e1dfa7bc34eb2fe76687241d48f
parentba3fceeb8703a68aefef01a00042b5aa07e4b9a7 (diff)
update video class structure, add vs input/output terminal and processing unit bmcontrol support
-rw-r--r--class/video/usb_video.h319
-rw-r--r--class/video/usbd_video.c515
-rw-r--r--class/video/usbd_video.h2
3 files changed, 794 insertions, 42 deletions
diff --git a/class/video/usb_video.h b/class/video/usb_video.h
index 1f045717..a482bb88 100644
--- a/class/video/usb_video.h
+++ b/class/video/usb_video.h
@@ -806,23 +806,73 @@ struct video_still_probe_and_commit_controls {
receive in a single payload transfer.*/
} __PACKED;
-struct video_cs_vc_if_descriptor {
+struct video_cs_if_vc_header_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
- uint8_t bDescriptorSubType;
- uint8_t bNumFormats;
+ uint16_t bcdVDC;
uint16_t wTotalLength;
- uint8_t bEndpointAddress;
- uint8_t bmInfo;
- uint8_t bTerminalLink;
- uint8_t bStillCaptureMethod;
- uint8_t bTriggerSupport;
- uint8_t bTriggerUsage;
+ uint32_t dwClockFrequency;
+ uint8_t bInCollection;
+ uint8_t baInterfaceNr[];
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (12 + n)
+
+struct video_cs_if_vc_input_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t iTerminal;
+ uint16_t wObjectiveFocalLenMin;
+ uint16_t wObjectiveFocalLenMax;
+ uint16_t wOcularFocalLength;
uint8_t bControlSize;
uint8_t bmaControls[];
} __PACKED;
-struct video_cs_vs_input_header_descriptor {
+#define VIDEO_SIZEOF_VC_INPUT_TERMINAL_DESC(n) (15 + n)
+
+struct video_cs_if_vc_processing_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bUnitID;
+ uint8_t bSourceID;
+ uint16_t wMaxMultiplier;
+ uint8_t bControlSize;
+ uint8_t bmaControls[2];
+ uint8_t iProcessing;
+ uint8_t bmVideoStandards;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_PROCESSING_UNIT_DESC(n) (10 + n)
+
+struct video_cs_if_vc_output_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t iTerminal;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_OUTPUT_TERMINAL_DESC 9
+
+struct video_cs_ep_vc_ep_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint16_t wMaxTransferSize;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_EP_DESC 5
+
+struct video_cs_if_vs_input_header_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
@@ -838,7 +888,9 @@ struct video_cs_vs_input_header_descriptor {
uint8_t bmaControls[];
} __PACKED;
-struct video_cs_vs_output_header_descriptor {
+#define VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(p, n) (13 + p * n)
+
+struct video_cs_if_vs_output_header_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
@@ -850,23 +902,30 @@ struct video_cs_vs_output_header_descriptor {
uint8_t bmaControls[];
} __PACKED;
-struct video_cs_vs_padload_format_descriptor {
+#define VIDEO_SIZEOF_VS_OUTPUT_TERMINAL_DESC(p, n) (9 + p * n)
+
+struct video_cs_if_vs_format_uncompressed_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
- uint8_t bNumFormats;
- uint16_t wTotalLength;
- uint8_t bEndpointAddress;
- uint8_t bTerminalLink;
- uint8_t bControlSize;
- uint8_t bmaControls[];
+ uint8_t bFormatIndex;
+ uint8_t bNumFrameDescriptors;
+ uint32_t guidFormat;
+ uint8_t bBitsPerPixel;
+ uint8_t bDefaultFrameIndex;
+ uint8_t bAspectRatioX;
+ uint8_t bAspectRatioY;
+ uint8_t bmInterlaceFlags;
+ uint8_t bCopyProtect;
} __PACKED;
-struct video_cs_vs_frame_descriptor {
+#define VIDEO_SIZEOF_VS_FORMAT_UNCOMPRESSED_DESC(n) (11 + n)
+
+struct video_cs_if_vs_frame_uncompressed_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
- uint8_t bFrameIndex;
+ uint8_t bFormatIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
@@ -875,11 +934,229 @@ struct video_cs_vs_frame_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
+
+struct video_cs_if_vs_format_mjpeg_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bNumFrameDescriptors;
+ uint8_t bmFlags;
+ uint8_t bDefaultFrameIndex;
+ uint8_t bAspectRatioX;
+ uint8_t bAspectRatioY;
+ uint8_t bmInterlaceFlags;
+ uint8_t bCopyProtect;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC 11
+
+struct video_cs_if_vs_frame_mjpeg_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bmCapabilities;
+ uint16_t wWidth;
+ uint16_t wHeight;
+ uint32_t dwMinBitRate;
+ uint32_t dwMaxBitRate;
+ uint32_t dwMaxVideoFrameBufferSize;
+ uint32_t dwDefaultFrameInterval;
+ uint8_t bFrameIntervalType;
+ uint32_t dwFrameInterval1;
+ uint32_t dwFrameInterval2;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC 34
+
+struct video_cs_if_vs_colorformat_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bColorPrimaries;
+ uint8_t bXferCharacteristics;
+ uint8_t bMatrixCoefficients;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_COLORFORMAT_DESC 6
+
+struct video_vc_input_terminal_bmcontrol_bitmap {
+ uint32_t scanning_mode : 1;
+ uint32_t auto_exposure_mode : 1;
+ uint32_t auto_exposure_priority : 1;
+ uint32_t exposure_time_absolute : 1;
+ uint32_t exposure_time_relative : 1;
+ uint32_t focus_absolute : 1;
+ uint32_t focus_relative : 1;
+ uint32_t iris_absolute : 1;
+ uint32_t iris_relative : 1;
+ uint32_t zoom_absolute : 1;
+ uint32_t zoom_relative : 1;
+ uint32_t pantilt_absolute : 1;
+ uint32_t pantilt_relative : 1;
+ uint32_t roll_absolute : 1;
+ uint32_t roll_relative : 1;
+ uint32_t reserved : 2;
+ uint32_t focus_auto : 1;
+ uint32_t pricvcy : 1;
+};
+
+struct video_vc_processing_unit_bmcontrol_bitmap {
+ uint16_t brightness : 1;
+ uint16_t contrast : 1;
+ uint16_t hue : 1;
+ uint16_t saturation : 1;
+ uint16_t sharpness : 1;
+ uint16_t gamma : 1;
+ uint16_t white_bal_temp : 1;
+ uint16_t white_bal_comp : 1;
+ uint16_t backlight_comp : 1;
+ uint16_t gain : 1;
+ uint16_t power_line_freq : 1;
+ uint16_t hue_auto : 1;
+ uint16_t white_bal_temp_auto : 1;
+ uint16_t white_bal_comp_auto : 1;
+ uint16_t digital_mult : 1;
+ uint16_t digital_mult_limit : 1;
+};
+
+struct video_camera_capabilities {
+ uint8_t support_get_request : 1;
+ uint8_t support_set_request : 1;
+ uint8_t disabled_by_automatic_mode : 1;
+ uint8_t auto_update_control : 1;
+ uint8_t async_control : 1;
+ uint8_t reserved : 3;
+};
+
+struct video_autoexposure_mode {
+ uint8_t manual_mode : 1;
+ uint8_t auto_mode : 1;
+ uint8_t shutter_priority_mode : 1;
+ uint8_t aperture_priority_mode : 1;
+ uint8_t reserved : 4;
+};
+
struct video_entity_info {
+ usb_slist_t list;
uint8_t bDescriptorSubtype;
uint8_t bEntityId;
+ uint16_t wTerminalType;
};
+
+// 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. */ \
+ 0x01, /* baInterfaceNr(1) : 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, 0x40, /* wMaxMultiplier */ \
+ 0x02, /* bControlSize */ \
+ 0x00, 0x00, /* bmControls */ \
+ 0x00, /* iProcessing */ \
+ 0x00, /* bmVideoStandards */ \
+ 0x09, \
+ 0x24, \
+ VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
+ 0x03, /* iProcessing */ \
+ WBVAL(VIDEO_TT_STREAMING), \
+ 0x00, /* bAssocTerminal */ \
+ 0x02, /* bSourceID */ \
+ 0x00 /* iTerminal */
+
+#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress) \
+ /*Class-specific VideoStream Header Descriptor (Input) */ \
+ 0x10, \
+ 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 3 (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 */ \
+ 0x00, 0x04, 0x00 /* bmaControls : No VideoStreaming specific controls are supported.*/ \
+
+#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
+ dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwFrameInterval) \
+ 0x1e, \
+ 0x24, \
+ VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, \
+ bFrameIndex, \
+ 0x00, \
+ WBVAL(wWidth), \
+ WBVAL(wHeight), \
+ DBVAL(dwMinBitRate), \
+ DBVAL(dwMaxBitRate), \
+ DBVAL(dwMaxVideoFrameBufferSize), \
+ DBVAL(dwDefaultFrameInterval), \
+ 0x01, \
+ DBVAL(dwFrameInterval)
+
+#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
+ dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwMinFrameInterval1, dwMinFrameInterval2) \
+ 0x22, /* bLength */ \
+ 0x24, /* bDescriptorType : CS_INTERFACE */ \
+ VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_MJPEG */ \
+ 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 */ \
+ DBVAL(dwMaxVideoFrameBufferSize), /* dwMaxVideoFrameBufSize (4bytes): Maximum video or still frame size, in bytes. */ \
+ DBVAL(dwDefaultFrameInterval), /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
+ 0x02, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
+ DBVAL(dwMinFrameInterval1), /* dwMinFrameInterval : 1,000,000 ns *100ns -> 10 FPS,Shortest frame interval supported (at highest frame rate), in 100 ns units */ \
+ DBVAL(dwMinFrameInterval2) /* dwMaxFrameInterval : 1,000,000 ns *100ns -> 10 FPS,Longest frame interval supported (at lowest frame rate), in 100 ns units */
+// clang-format on
#endif /* USB_VIDEO_H_ */
diff --git a/class/video/usbd_video.c b/class/video/usbd_video.c
index c2713d7f..3adad164 100644
--- a/class/video/usbd_video.c
+++ b/class/video/usbd_video.c
@@ -23,21 +23,20 @@
#include "usbd_video.h"
struct usbd_video_cfg_priv {
- struct video_entity_info *entity_info;
- uint8_t entity_count;
struct video_probe_and_commit_controls *probe;
struct video_probe_and_commit_controls *commit;
uint8_t power_mode;
uint8_t error_code;
uint8_t vcintf;
uint8_t vsintf;
+ usb_slist_t entity_info_list;
} usbd_video_cfg = { .vcintf = 0xff, .vsintf = 0xff };
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
- uint8_t cs = (uint8_t)(setup->wValue >> 8); /* control_selector */
+ uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
- switch (cs) {
+ switch (control_selector) {
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
@@ -55,6 +54,8 @@ static int usbd_video_control_request_handler(struct usb_setup_packet *setup, ui
case VIDEO_VC_REQUEST_ERROR_CODE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_GET_CUR:
+ (*data)[0] = 0x06;
+ *len = 1;
break;
case VIDEO_REQUEST_GET_INFO:
break;
@@ -74,26 +75,501 @@ static int usbd_video_control_request_handler(struct usb_setup_packet *setup, ui
static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
- uint8_t cs = (uint8_t)(setup->wValue >> 8); /* control_selector */
+ uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
- for (uint8_t i = 0; i < usbd_video_cfg.entity_count; i++) {
- if (usbd_video_cfg.entity_info[i].bEntityId == entity_id) {
- switch (usbd_video_cfg.entity_info[i].bDescriptorSubtype) {
+ usb_slist_t *i;
+ usb_slist_for_each(i, &usbd_video_cfg.entity_info_list)
+ {
+ struct video_entity_info *entity_info = usb_slist_entry(i, struct video_entity_info, list);
+ if (entity_info->bEntityId == entity_id) {
+ switch (entity_info->bDescriptorSubtype) {
+ case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
+ break;
case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
+ if (entity_info->wTerminalType == VIDEO_ITT_CAMERA) {
+ switch (control_selector) {
+ case VIDEO_CT_AE_MODE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR:
+ (*data)[0] = 0x08;
+ *len = 1;
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint32_t dwExposureTimeAbsolute = 2500;
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint32_t dwExposureTimeAbsolute = 5; //0.0005sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint32_t dwExposureTimeAbsolute = 5; //0.0005sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_FOCUS_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wFocusAbsolute = 0x0080;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wFocusAbsolute = 0;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wFocusAbsolute = 0x00ff;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wFocusAbsolute = 0x0001;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wFocusAbsolute = 0x0080;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_ZOOM_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wObjectiveFocalLength = 0x0064;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wObjectiveFocalLength = 0x0064;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wObjectiveFocalLength = 0x00c8;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wObjectiveFocalLength = 0x0001;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wObjectiveFocalLength = 0x0064;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_ROLL_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wRollAbsolute = 0x0000;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wRollAbsolute = 0x0000;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wRollAbsolute = 0x00ff;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wRollAbsolute = 0x0001;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wRollAbsolute = 0x0000;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_FOCUS_AUTO_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wFocusAuto = 0x0000;
+ memcpy(*data, (uint8_t *)&wFocusAuto, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+ } else {
+ USB_LOG_WRN("Unhandled Video Class wTerminalType 0x%02x\r\n", entity_info->wTerminalType);
+ return -2;
+ }
break;
case VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
break;
- case VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE:
+ case VIDEO_VC_SELECTOR_UNIT_DESCRIPTOR_SUBTYPE:
break;
- switch (setup->bRequest) {
- case VIDEO_REQUEST_SET_CUR:
- if (cs == VIDEO_PU_BRIGHTNESS_CONTROL) {
+ case VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE:
+ switch (control_selector) {
+ case VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wBacklightCompensation = 0x0004;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wBacklightCompensation = 0;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wBacklightCompensation = 8;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wBacklightCompensation = 1;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wBacklightCompensation = 4;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_BRIGHTNESS_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_SET_CUR: {
+ uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
+ USB_LOG_INFO("Video set brightness:%d\r\n", wBrightness);
+ } break;
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wBrightness = 0x0080;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wBrightness = 0x0001;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wBrightness = 0x00ff;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wBrightness = 0x0001;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wBrightness = 0x0080;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_CONTRAST_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wContrast = 0x0080;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wContrast = 0x0001;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wContrast = 0x00ff;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wContrast = 0x0001;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wContrast = 0x0080;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_HUE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wHue = 0x0080;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wHue = 0x0001;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wHue = 0x00ff;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wHue = 0x0001;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wHue = 0x0080;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_SATURATION_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wSaturation = 0x0001;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wSaturation = 0x00ff;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wSaturation = 0x0001;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wSaturation = 0x0080;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_SHARPNESS_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wSharpness = 0x0001;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wSharpness = 0x00ff;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wSharpness = 0x0001;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wSharpness = 0x0080;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_GAIN_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wGain = 0;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wGain = 255;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wGain = 1;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wGain = 255;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wWhiteBalance_Temprature = 417;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wWhiteBalance_Temprature = 300;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wWhiteBalance_Temprature = 600;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wWhiteBalance_Temprature = 1;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wWhiteBalance_Temprature = 417;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wWhiteBalance_Temprature_Auto = 1;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature_Auto, 1);
+ *len = 1;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
}
break;
default:
- USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ usbd_video_cfg.error_code = 0x06;
+ USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
return -1;
}
+ break;
+ case VIDEO_VC_EXTENSION_UNIT_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_ENCODING_UNIT_DESCRIPTOR_SUBTYPE:
+ break;
+
default:
break;
}
@@ -104,13 +580,13 @@ static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_pac
static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
- uint8_t cs = (uint8_t)(setup->wValue >> 8); /* control_selector */
+ uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
- switch (cs) {
+ switch (control_selector) {
case VIDEO_VS_PROBE_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
- memcpy((uint8_t *)usbd_video_cfg.probe, *data, setup->wLength);
+ //memcpy((uint8_t *)usbd_video_cfg.probe, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
*data = (uint8_t *)usbd_video_cfg.probe;
@@ -142,7 +618,7 @@ static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uin
case VIDEO_VS_COMMIT_CONTROL:
switch (setup->bRequest) {
case VIDEO_REQUEST_SET_CUR:
- memcpy((uint8_t *)usbd_video_cfg.commit, *data, setup->wLength);
+ //memcpy((uint8_t *)usbd_video_cfg.commit, *data, setup->wLength);
break;
case VIDEO_REQUEST_GET_CUR:
*data = (uint8_t *)usbd_video_cfg.commit;
@@ -266,10 +742,9 @@ void usbd_video_set_probe_and_commit_controls(struct video_probe_and_commit_cont
usbd_video_cfg.commit = commit;
}
-void usbd_video_set_entity_info(struct video_entity_info *info, uint8_t count)
+void usbd_video_add_entity_info(struct video_entity_info *info)
{
- usbd_video_cfg.entity_info = info;
- usbd_video_cfg.entity_count = count;
+ usb_slist_add_tail(&usbd_video_cfg.entity_info_list, &info->list);
}
__WEAK void usbd_video_sof_callback(void)
diff --git a/class/video/usbd_video.h b/class/video/usbd_video.h
index d9d0e32a..b4693357 100644
--- a/class/video/usbd_video.h
+++ b/class/video/usbd_video.h
@@ -33,7 +33,7 @@ void usbd_video_add_interface(usbd_class_t *class, usbd_interface_t *intf);
void usbd_video_set_probe_and_commit_controls(struct video_probe_and_commit_controls *probe,
struct video_probe_and_commit_controls *commit);
-void usbd_video_set_entity_info(struct video_entity_info *info, uint8_t count);
+void usbd_video_add_entity_info(struct video_entity_info *info);
void usbd_video_sof_callback(void);
void usbd_video_set_interface_callback(uint8_t value);