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@xxxxxxxxxxxxxx> --- drivers/usb/gadget/function/uvc_v4l2.c | 67 +++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 5620546eb43b..3f728f451ed5 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -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, -- 2.30.2