@@ -90,6 +90,15 @@ static struct uvcg_format *find_format_by_index(struct uvc_device *uvc, int inde
return uformat;
}
+static struct uvcg_format *get_default_format(struct uvc_device *uvc)
+{
+ /*
+ * UVC does not specify which format index shall be used as default.
+ * Use the first format of the descriptor as default.
+ */
+ return find_format_by_index(uvc, 1);
+}
+
static struct uvcg_frame *find_frame_by_index(struct uvc_device *uvc,
struct uvcg_format *uformat,
int index)
@@ -112,6 +121,29 @@ static struct uvcg_frame *find_frame_by_index(struct uvc_device *uvc,
return uframe;
}
+static struct uvcg_frame *get_default_frame(struct uvc_device *uvc,
+ struct uvcg_format *uformat)
+{
+ struct uvcg_frame *frame = NULL;
+ int frame_index = 0;
+
+ if (uformat->type == UVCG_UNCOMPRESSED) {
+ struct uvcg_uncompressed *u;
+
+ u = to_uvcg_uncompressed(&uformat->group.cg_item);
+ frame_index = u->desc.bDefaultFrameIndex;
+ } else if (uformat->type == UVCG_MJPEG) {
+ struct uvcg_mjpeg *u;
+
+ u = to_uvcg_mjpeg(&uformat->group.cg_item);
+ frame_index = u->desc.bDefaultFrameIndex;
+ }
+ if (frame_index != 0)
+ frame = find_frame_by_index(uvc, uformat, frame_index);
+
+ return frame;
+}
+
static struct uvcg_format *find_format_by_pix(struct uvc_device *uvc,
u32 pixelformat)
{
@@ -133,12 +165,37 @@ static struct uvcg_format *find_format_by_pix(struct uvc_device *uvc,
void uvc_init_default_format(struct uvc_device *uvc)
{
struct uvc_video *video = &uvc->video;
+ struct uvcg_format *uformat;
+ struct uvcg_frame *uframe = NULL;
- video->fcc = V4L2_PIX_FMT_YUYV;
- video->bpp = 16;
- video->width = 320;
- video->height = 240;
- video->imagesize = 320 * 240 * 2;
+ uformat = get_default_format(uvc);
+ if (uformat)
+ uframe = get_default_frame(uvc, uformat);
+
+ /* Fallback on some arbitrary default */
+ if (!uframe) {
+ video->fcc = V4L2_PIX_FMT_YUYV;
+ video->bpp = 16;
+ video->width = 320;
+ video->height = 240;
+ video->imagesize = 320 * 240 * 2;
+
+ return;
+ }
+
+ video->fcc = to_uvc_format(uformat)->fcc;
+
+ if (uformat->type == UVCG_UNCOMPRESSED) {
+ struct uvcg_uncompressed *u;
+
+ u = to_uvcg_uncompressed(&uformat->group.cg_item);
+ video->bpp = u->desc.bBitsPerPixel;
+ } else {
+ video->bpp = 0;
+ }
+ video->width = uframe->frame.w_width;
+ video->height = uframe->frame.w_height;
+ video->imagesize = uvc_get_frame_size(uformat, uframe);
}
static struct uvcg_frame *find_closest_frame_by_size(struct uvc_device *uvc,
The configfs is supported to get a list of valid formats, which will be checked in TRY_FMT and ENUM_FMT. The device should be initialized with a valid format instead of some arbitrary format that the user space won't be able to set. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> --- drivers/usb/gadget/function/uvc_v4l2.c | 67 +++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-)