Skip to content
Permalink
Browse files
usb: gadget: uvc: add VIDIOC function
This patch adds support to the v4l2 VIDIOC for enum_format, enum_framesizes,
enum_frameintervals and try_fmt. The linked/active configfs userspace setup is
used in the v4l2 interface functions.

With the v4l2 vidiocontrols the userspace can use the v4l2 api to negotiate and
alloc the data. It doesn't have to bring its own configfs parser.

Also it only needs to be extended with subscription for streamon, streamoff,
connect and disconnect for stream handling and become able to serve the uvc
device.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
  • Loading branch information
mgrzeschik authored and intel-lab-lkp committed Nov 17, 2021
1 parent 32b9d75 commit 3227638d6b37451cc22e7ee61a3311ec3f6498ce
Show file tree
Hide file tree
Showing 5 changed files with 406 additions and 50 deletions.
@@ -881,6 +881,7 @@ static void uvc_free(struct usb_function *f)
struct uvc_device *uvc = to_uvc(f);
struct f_uvc_opts *opts = container_of(f->fi, struct f_uvc_opts,
func_inst);
config_item_put(&uvc->header->item);
--opts->refcnt;
kfree(uvc);
}
@@ -908,6 +909,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
struct uvc_device *uvc;
struct f_uvc_opts *opts;
struct uvc_descriptor_header **strm_cls;
struct config_item *streaming, *header, *h;

uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
if (uvc == NULL)
@@ -939,6 +941,28 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
uvc->desc.fs_streaming = opts->fs_streaming;
uvc->desc.hs_streaming = opts->hs_streaming;
uvc->desc.ss_streaming = opts->ss_streaming;

streaming = config_group_find_item(&opts->func_inst.group, "streaming");
if (!streaming) {
config_item_put(streaming);
return ERR_PTR(-ENOMEM);
}
header = config_group_find_item(to_config_group(streaming), "header");
config_item_put(streaming);
if (!header) {
config_item_put(header);
return ERR_PTR(-ENOMEM);
}
h = config_group_find_item(to_config_group(header), "h");
config_item_put(header);
if (!h) {
config_item_put(h);
return ERR_PTR(-ENOMEM);
}
uvc->header = to_uvcg_streaming_header(h);
if (!uvc->header->linked)
return ERR_PTR(-EBUSY);

++opts->refcnt;
mutex_unlock(&opts->lock);

@@ -88,11 +88,10 @@ struct uvc_video {
struct work_struct pump;

/* Frame parameters */
u8 bpp;
u32 fcc;
unsigned int width;
unsigned int height;
unsigned int imagesize;
struct uvcg_format *cur_format;
struct uvcg_frame *cur_frame;
unsigned int cur_ival;

struct mutex mutex; /* protects frame parameters */

unsigned int uvc_num_requests;
@@ -130,6 +129,8 @@ struct uvc_device {
struct uvc_video video;
bool func_connected;

struct uvcg_streaming_header *header;

/* Descriptors */
struct {
const struct uvc_descriptor_header * const *fs_control;
@@ -175,4 +176,10 @@ extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
extern void uvc_function_disconnect(struct uvc_device *uvc);

extern struct uvcg_format *find_format_by_index(struct uvc_device *uvc,
int index);
extern struct uvcg_frame *find_frame_by_index(struct uvc_device *uvc,
struct uvcg_format *uformat,
int index);

#endif /* _UVC_GADGET_H_ */
@@ -21,6 +21,8 @@
#include <media/videobuf2-vmalloc.h>

#include "uvc.h"
#include "u_uvc.h"
#include "uvc_configfs.h"

/* ------------------------------------------------------------------------
* Video buffers queue management.
@@ -51,7 +53,7 @@ static int uvc_queue_setup(struct vb2_queue *vq,

*nplanes = 1;

sizes[0] = video->imagesize;
sizes[0] = video->cur_frame->frame.dw_max_video_frame_buffer_size;

if (cdev->gadget->speed < USB_SPEED_SUPER)
video->uvc_num_requests = 4;

0 comments on commit 3227638

Please sign in to comment.