#include <linux/usb/video.h>
#include "u_uvc.h"
+#include "uvc_configfs.h"
USB_GADGET_COMPOSITE_OPTIONS();
.bNumConfigurations = 0, /* dynamic */
};
-DECLARE_UVC_HEADER_DESCRIPTOR(1);
-
static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
.bLength = UVC_DT_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bmaControls[1][0] = 4,
};
-static const struct uvc_format_uncompressed uvc_format_yuv = {
- .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
- .bFormatIndex = 1,
- .bNumFrameDescriptors = 2,
- .guidFormat =
- { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
- .bBitsPerPixel = 16,
- .bDefaultFrameIndex = 1,
- .bAspectRatioX = 0,
- .bAspectRatioY = 0,
- .bmInterlaceFlags = 0,
- .bCopyProtect = 0,
+static const struct uvcg_color_matching uvcg_color_matching = {
+ .desc = {
+ .bLength = UVC_DT_COLOR_MATCHING_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_COLORFORMAT,
+ .bColorPrimaries = 1,
+ .bTransferCharacteristics = 1,
+ .bMatrixCoefficients = 4,
+ },
+};
+
+static struct uvcg_uncompressed uvcg_format_yuv = {
+ .fmt = {
+ .type = UVCG_UNCOMPRESSED,
+ /* add to .frames and fill .num_frames at runtime */
+ .color_matching = (struct uvcg_color_matching *)&uvcg_color_matching,
+ },
+ .desc = {
+ .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
+ .bFormatIndex = 1,
+ .bNumFrameDescriptors = 2,
+ .guidFormat = {
+ 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+ },
+ .bBitsPerPixel = 16,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterlaceFlags = 0,
+ .bCopyProtect = 0,
+ },
+};
+
+static struct uvcg_format_ptr uvcg_format_ptr_yuv = {
+ .fmt = &uvcg_format_yuv.fmt,
};
DECLARE_UVC_FRAME_UNCOMPRESSED(1);
DECLARE_UVC_FRAME_UNCOMPRESSED(3);
+#define UVCG_WIDTH_360P 640
+#define UVCG_HEIGHT_360P 360
+#define UVCG_MIN_BITRATE_360P 18432000
+#define UVCG_MAX_BITRATE_360P 55296000
+#define UVCG_MAX_VIDEO_FB_SZ_360P 460800
+#define UVCG_FRM_INTERV_0_360P 666666
+#define UVCG_FRM_INTERV_1_360P 1000000
+#define UVCG_FRM_INTERV_2_360P 5000000
+#define UVCG_DEFAULT_FRM_INTERV_360P UVCG_FRM_INTERV_0_360P
+
static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
.bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
.bFrameIndex = 1,
.bmCapabilities = 0,
- .wWidth = cpu_to_le16(640),
- .wHeight = cpu_to_le16(360),
- .dwMinBitRate = cpu_to_le32(18432000),
- .dwMaxBitRate = cpu_to_le32(55296000),
- .dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
- .dwDefaultFrameInterval = cpu_to_le32(666666),
+ .wWidth = cpu_to_le16(UVCG_WIDTH_360P),
+ .wHeight = cpu_to_le16(UVCG_HEIGHT_360P),
+ .dwMinBitRate = cpu_to_le32(UVCG_MIN_BITRATE_360P),
+ .dwMaxBitRate = cpu_to_le32(UVCG_MAX_BITRATE_360P),
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_360P),
+ .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_360P),
.bFrameIntervalType = 3,
- .dwFrameInterval[0] = cpu_to_le32(666666),
- .dwFrameInterval[1] = cpu_to_le32(1000000),
- .dwFrameInterval[2] = cpu_to_le32(5000000),
+ .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_360P),
+ .dwFrameInterval[1] = cpu_to_le32(UVCG_FRM_INTERV_1_360P),
+ .dwFrameInterval[2] = cpu_to_le32(UVCG_FRM_INTERV_2_360P),
+};
+
+static u32 uvcg_frame_yuv_360p_dw_frame_interval[] = {
+ [0] = UVCG_FRM_INTERV_0_360P,
+ [1] = UVCG_FRM_INTERV_1_360P,
+ [2] = UVCG_FRM_INTERV_2_360P,
+};
+
+static const struct uvcg_frame uvcg_frame_yuv_360p = {
+ .fmt_type = UVCG_UNCOMPRESSED,
+ .frame = {
+ .b_length = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
+ .b_descriptor_type = USB_DT_CS_INTERFACE,
+ .b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED,
+ .b_frame_index = 1,
+ .bm_capabilities = 0,
+ .w_width = UVCG_WIDTH_360P,
+ .w_height = UVCG_HEIGHT_360P,
+ .dw_min_bit_rate = UVCG_MIN_BITRATE_360P,
+ .dw_max_bit_rate = UVCG_MAX_BITRATE_360P,
+ .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_360P,
+ .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_360P,
+ .b_frame_interval_type = 3,
+ },
+ .dw_frame_interval = uvcg_frame_yuv_360p_dw_frame_interval,
+};
+
+static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_360p = {
+ .frm = (struct uvcg_frame *)&uvcg_frame_yuv_360p,
};
+#define UVCG_WIDTH_720P 1280
+#define UVCG_HEIGHT_720P 720
+#define UVCG_MIN_BITRATE_720P 29491200
+#define UVCG_MAX_BITRATE_720P 29491200
+#define UVCG_MAX_VIDEO_FB_SZ_720P 1843200
+#define UVCG_FRM_INTERV_0_720P 5000000
+#define UVCG_DEFAULT_FRM_INTERV_720P UVCG_FRM_INTERV_0_720P
static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
.bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
.bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
.bFrameIndex = 2,
.bmCapabilities = 0,
- .wWidth = cpu_to_le16(1280),
- .wHeight = cpu_to_le16(720),
- .dwMinBitRate = cpu_to_le32(29491200),
- .dwMaxBitRate = cpu_to_le32(29491200),
- .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
- .dwDefaultFrameInterval = cpu_to_le32(5000000),
+ .wWidth = cpu_to_le16(UVCG_WIDTH_720P),
+ .wHeight = cpu_to_le16(UVCG_HEIGHT_720P),
+ .dwMinBitRate = cpu_to_le32(UVCG_MIN_BITRATE_720P),
+ .dwMaxBitRate = cpu_to_le32(UVCG_MAX_BITRATE_720P),
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_720P),
+ .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_720P),
.bFrameIntervalType = 1,
- .dwFrameInterval[0] = cpu_to_le32(5000000),
+ .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_720P),
};
-static const struct uvc_format_mjpeg uvc_format_mjpg = {
- .bLength = UVC_DT_FORMAT_MJPEG_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
- .bFormatIndex = 2,
- .bNumFrameDescriptors = 2,
- .bmFlags = 0,
- .bDefaultFrameIndex = 1,
- .bAspectRatioX = 0,
- .bAspectRatioY = 0,
- .bmInterlaceFlags = 0,
- .bCopyProtect = 0,
+static u32 uvcg_frame_yuv_720p_dw_frame_interval[] = {
+ [0] = UVCG_FRM_INTERV_0_720P,
+};
+
+static const struct uvcg_frame uvcg_frame_yuv_720p = {
+ .fmt_type = UVCG_UNCOMPRESSED,
+ .frame = {
+ .b_length = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
+ .b_descriptor_type = USB_DT_CS_INTERFACE,
+ .b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED,
+ .b_frame_index = 2,
+ .bm_capabilities = 0,
+ .w_width = UVCG_WIDTH_720P,
+ .w_height = UVCG_HEIGHT_720P,
+ .dw_min_bit_rate = UVCG_MIN_BITRATE_720P,
+ .dw_max_bit_rate = UVCG_MAX_BITRATE_720P,
+ .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_720P,
+ .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_720P,
+ .b_frame_interval_type = 1,
+ },
+ .dw_frame_interval = uvcg_frame_yuv_720p_dw_frame_interval,
+};
+
+static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_720p = {
+ .frm = (struct uvcg_frame *)&uvcg_frame_yuv_720p,
+};
+
+static struct uvcg_mjpeg uvcg_format_mjpeg = {
+ .fmt = {
+ .type = UVCG_MJPEG,
+ /* add to .frames and fill .num_frames at runtime */
+ .color_matching = (struct uvcg_color_matching *)&uvcg_color_matching,
+ },
+ .desc = {
+ .bLength = UVC_DT_FORMAT_MJPEG_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
+ .bFormatIndex = 2,
+ .bNumFrameDescriptors = 2,
+ .bmFlags = 0,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterlaceFlags = 0,
+ .bCopyProtect = 0,
+ },
+};
+
+static struct uvcg_format_ptr uvcg_format_ptr_mjpeg = {
+ .fmt = &uvcg_format_mjpeg.fmt,
};
DECLARE_UVC_FRAME_MJPEG(1);
.bDescriptorSubType = UVC_VS_FRAME_MJPEG,
.bFrameIndex = 1,
.bmCapabilities = 0,
- .wWidth = cpu_to_le16(640),
- .wHeight = cpu_to_le16(360),
- .dwMinBitRate = cpu_to_le32(18432000),
- .dwMaxBitRate = cpu_to_le32(55296000),
- .dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
- .dwDefaultFrameInterval = cpu_to_le32(666666),
+ .wWidth = cpu_to_le16(UVCG_WIDTH_360P),
+ .wHeight = cpu_to_le16(UVCG_HEIGHT_360P),
+ .dwMinBitRate = cpu_to_le32(UVCG_MIN_BITRATE_360P),
+ .dwMaxBitRate = cpu_to_le32(UVCG_MAX_BITRATE_360P),
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_360P),
+ .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_360P),
.bFrameIntervalType = 3,
- .dwFrameInterval[0] = cpu_to_le32(666666),
- .dwFrameInterval[1] = cpu_to_le32(1000000),
- .dwFrameInterval[2] = cpu_to_le32(5000000),
+ .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_360P),
+ .dwFrameInterval[1] = cpu_to_le32(UVCG_FRM_INTERV_1_360P),
+ .dwFrameInterval[2] = cpu_to_le32(UVCG_FRM_INTERV_2_360P),
+};
+
+static u32 uvcg_frame_mjpeg_360p_dw_frame_interval[] = {
+ [0] = UVCG_FRM_INTERV_0_360P,
+ [1] = UVCG_FRM_INTERV_1_360P,
+ [2] = UVCG_FRM_INTERV_2_360P,
+};
+
+static const struct uvcg_frame uvcg_frame_mjpeg_360p = {
+ .fmt_type = UVCG_MJPEG,
+ .frame = {
+ .b_length = UVC_DT_FRAME_MJPEG_SIZE(3),
+ .b_descriptor_type = USB_DT_CS_INTERFACE,
+ .b_descriptor_subtype = UVC_VS_FRAME_MJPEG,
+ .b_frame_index = 1,
+ .bm_capabilities = 0,
+ .w_width = UVCG_WIDTH_360P,
+ .w_height = UVCG_HEIGHT_360P,
+ .dw_min_bit_rate = UVCG_MIN_BITRATE_360P,
+ .dw_max_bit_rate = UVCG_MAX_BITRATE_360P,
+ .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_360P,
+ .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_360P,
+ .b_frame_interval_type = 3,
+ },
+ .dw_frame_interval = uvcg_frame_mjpeg_360p_dw_frame_interval,
+};
+
+static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_360p = {
+ .frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_360p,
};
static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
.bDescriptorSubType = UVC_VS_FRAME_MJPEG,
.bFrameIndex = 2,
.bmCapabilities = 0,
- .wWidth = cpu_to_le16(1280),
- .wHeight = cpu_to_le16(720),
- .dwMinBitRate = cpu_to_le32(29491200),
- .dwMaxBitRate = cpu_to_le32(29491200),
- .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
- .dwDefaultFrameInterval = cpu_to_le32(5000000),
+ .wWidth = cpu_to_le16(UVCG_WIDTH_720P),
+ .wHeight = cpu_to_le16(UVCG_HEIGHT_720P),
+ .dwMinBitRate = cpu_to_le32(UVCG_MIN_BITRATE_720P),
+ .dwMaxBitRate = cpu_to_le32(UVCG_MAX_BITRATE_720P),
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_720P),
+ .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_720P),
.bFrameIntervalType = 1,
- .dwFrameInterval[0] = cpu_to_le32(5000000),
+ .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_720P),
};
-static const struct uvc_color_matching_descriptor uvc_color_matching = {
- .bLength = UVC_DT_COLOR_MATCHING_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = UVC_VS_COLORFORMAT,
- .bColorPrimaries = 1,
- .bTransferCharacteristics = 1,
- .bMatrixCoefficients = 4,
+static u32 uvcg_frame_mjpeg_720p_dw_frame_interval[] = {
+ [0] = UVCG_FRM_INTERV_0_720P,
+};
+
+static const struct uvcg_frame uvcg_frame_mjpeg_720p = {
+ .fmt_type = UVCG_MJPEG,
+ .frame = {
+ .b_length = UVC_DT_FRAME_MJPEG_SIZE(1),
+ .b_descriptor_type = USB_DT_CS_INTERFACE,
+ .b_descriptor_subtype = UVC_VS_FRAME_MJPEG,
+ .b_frame_index = 2,
+ .bm_capabilities = 0,
+ .w_width = UVCG_WIDTH_720P,
+ .w_height = UVCG_HEIGHT_720P,
+ .dw_min_bit_rate = UVCG_MIN_BITRATE_720P,
+ .dw_max_bit_rate = UVCG_MAX_BITRATE_720P,
+ .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_720P,
+ .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_720P,
+ .b_frame_interval_type = 1,
+ },
+ .dw_frame_interval = uvcg_frame_mjpeg_720p_dw_frame_interval,
+};
+
+static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_720p = {
+ .frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_720p,
+};
+
+static struct uvcg_streaming_header uvcg_streaming_header = {
};
static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
- (const struct uvc_descriptor_header *) &uvc_format_yuv,
+ (const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
- (const struct uvc_descriptor_header *) &uvc_color_matching,
- (const struct uvc_descriptor_header *) &uvc_format_mjpg,
+ (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
+ (const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
- (const struct uvc_descriptor_header *) &uvc_color_matching,
+ (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
NULL,
};
static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
- (const struct uvc_descriptor_header *) &uvc_format_yuv,
+ (const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
- (const struct uvc_descriptor_header *) &uvc_color_matching,
- (const struct uvc_descriptor_header *) &uvc_format_mjpg,
+ (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
+ (const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
- (const struct uvc_descriptor_header *) &uvc_color_matching,
+ (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
NULL,
};
static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
- (const struct uvc_descriptor_header *) &uvc_format_yuv,
+ (const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
- (const struct uvc_descriptor_header *) &uvc_color_matching,
- (const struct uvc_descriptor_header *) &uvc_format_mjpg,
+ (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
+ (const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
- (const struct uvc_descriptor_header *) &uvc_color_matching,
+ (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
NULL,
};
uvc_opts->hs_streaming = uvc_hs_streaming_cls;
uvc_opts->ss_streaming = uvc_ss_streaming_cls;
+ INIT_LIST_HEAD(&uvcg_format_yuv.fmt.frames);
+ list_add_tail(&uvcg_frame_ptr_yuv_360p.entry, &uvcg_format_yuv.fmt.frames);
+ list_add_tail(&uvcg_frame_ptr_yuv_720p.entry, &uvcg_format_yuv.fmt.frames);
+ uvcg_format_yuv.fmt.num_frames = 2;
+
+ INIT_LIST_HEAD(&uvcg_format_mjpeg.fmt.frames);
+ list_add_tail(&uvcg_frame_ptr_mjpeg_360p.entry, &uvcg_format_mjpeg.fmt.frames);
+ list_add_tail(&uvcg_frame_ptr_mjpeg_720p.entry, &uvcg_format_mjpeg.fmt.frames);
+ uvcg_format_mjpeg.fmt.num_frames = 2;
+
+ INIT_LIST_HEAD(&uvcg_streaming_header.formats);
+ list_add_tail(&uvcg_format_ptr_yuv.entry, &uvcg_streaming_header.formats);
+ list_add_tail(&uvcg_format_ptr_mjpeg.entry, &uvcg_streaming_header.formats);
+ uvcg_streaming_header.num_fmt = 2;
+
+ uvc_opts->header = &uvcg_streaming_header;
+
/* Allocate string descriptor numbers ... note that string contents
* can be overridden by the composite_dev glue.
*/