diff options
| author | sakumisu <[email protected]> | 2022-02-17 17:21:17 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2022-02-17 17:21:17 +0800 |
| commit | 7fdd66c632e52c92404ecc872e70da6f033e1433 (patch) | |
| tree | 1e7315dc401a3e1dfa7bc34eb2fe76687241d48f | |
| parent | ba3fceeb8703a68aefef01a00042b5aa07e4b9a7 (diff) | |
update video class structure, add vs input/output terminal and processing unit bmcontrol support
| -rw-r--r-- | class/video/usb_video.h | 319 | ||||
| -rw-r--r-- | class/video/usbd_video.c | 515 | ||||
| -rw-r--r-- | class/video/usbd_video.h | 2 |
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); |
