Hi Andrzej,
Thank you for the patch.
git am complains with
Applying: usb/gadget: f_uvc: add configfs support
/home/laurent/src/kernel/media.git/.git/rebase-apply/patch:40: trailing
whitespace.
boolean "USB Webcam function"
warning: 1 line adds whitespace errors.
Could you please fix that ?
On Friday 28 February 2014 10:32:30 Andrzej Pietrasiewicz wrote:
> Add support for using uvc as a component of a composite gadget
> set up with configfs.
>
> Signed-off-by: Andrzej Pietrasiewicz <[email protected]>
> ---
> Documentation/ABI/testing/configfs-usb-gadget-uvc | 11 +
> drivers/usb/gadget/Kconfig | 11 +
> drivers/usb/gadget/Makefile | 2 +-
> drivers/usb/gadget/f_uvc.c | 97 +-
> drivers/usb/gadget/u_uvc.h | 19 +
> drivers/usb/gadget/uvc_configfs.c | 2928 ++++++++++++++++++
> drivers/usb/gadget/uvc_configfs.h | 283 ++
> 7 files changed, 3348 insertions(+), 3 deletions(-)
> create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-uvc
> create mode 100644 drivers/usb/gadget/uvc_configfs.c
> create mode 100644 drivers/usb/gadget/uvc_configfs.h
[snip]
> diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
> index bbadc0a..31e8bed 100644
> --- a/drivers/usb/gadget/f_uvc.c
> +++ b/drivers/usb/gadget/f_uvc.c
> @@ -31,6 +31,7 @@
> #include "u_uvc.h"
> #include "uvc_video.h"
> #include "uvc_v4l2.h"
> +#include "uvc_configfs.h"
Please keep the headers sorted alphabetically.
> unsigned int uvc_gadget_trace_param;
>
> @@ -467,6 +468,9 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum
> usb_device_speed speed) break;
> }
>
> + if (!uvc_control_desc || !uvc_streaming_cls)
> + return ERR_PTR(-ENODEV);
> +
Is this a configfs-specific problem ? If not it should be moved to a separate
patch.
> /* Descriptors layout
> *
> * uvc_iad
> @@ -658,10 +662,25 @@ uvc_function_bind(struct usb_configuration *c, struct
> usb_function *f)
>
> /* Copy descriptors */
> f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
> + if (IS_ERR(f->fs_descriptors)) {
> + ret = PTR_ERR(f->fs_descriptors);
> + f->fs_descriptors = NULL;
> + goto error;
> + }
> if (gadget_is_dualspeed(cdev->gadget))
> f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
> + if (IS_ERR(f->hs_descriptors)) {
> + ret = PTR_ERR(f->hs_descriptors);
> + f->hs_descriptors = NULL;
> + goto error;
> + }
> if (gadget_is_superspeed(c->cdev->gadget))
> f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
> + if (IS_ERR(f->ss_descriptors)) {
> + ret = PTR_ERR(f->ss_descriptors);
> + f->ss_descriptors = NULL;
> + goto error;
> + }
Same comment here. Should't you also handle the case where
uvc_copy_descriptors() returns NULL ? It seems a pretty fatal error too.
>
> /* Preallocate control endpoint request. */
> uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
> @@ -738,17 +757,88 @@ static struct usb_function_instance
> *uvc_alloc_inst(void) opts = kzalloc(sizeof(*opts), GFP_KERNEL);
> if (!opts)
> return ERR_PTR(-ENOMEM);
> + mutex_init(&opts->lock);
> opts->func_inst.free_func_inst = uvc_free_inst;
>
> + config_group_init_type_name(&f_uvc_header_group, "header",
> + &f_uvc_header_type);
> + config_group_init_type_name(&f_uvc_processing_group, "processing",
> + &f_uvc_processing_type);
> + config_group_init_type_name(&f_uvc_class_fs_group, "fs",
> + &f_uvc_class_fs_type);
> + config_group_init_type_name(&f_uvc_class_ss_group, "ss",
> + &f_uvc_class_ss_type);
> + f_uvc_class_group.default_groups = f_uvc_class_default_groups;
> + config_group_init_type_name(&f_uvc_class_group, "class",
> + &f_uvc_class_type);
> + config_group_init_type_name(&f_uvc_camera_group, "camera",
> + &f_uvc_camera_type);
> + config_group_init_type_name(&f_uvc_output_group, "output",
> + &f_uvc_output_type);
> + f_uvc_terminal_group.default_groups = f_uvc_terminal_default_groups;
> + config_group_init_type_name(&f_uvc_terminal_group, "terminal",
> + &f_uvc_terminal_type);
> + f_uvc_control_group.group.default_groups = f_uvc_control_default_groups;
> + INIT_LIST_HEAD(&f_uvc_control_group.known_targets);
> + config_group_init_type_name(&f_uvc_control_group.group, "control",
> + &f_uvc_control_type);
> + config_group_init_type_name(&f_uvc_input_header_group, "input_header",
> + &f_uvc_input_header_type);
> + config_group_init_type_name(&f_uvc_color_matching_group,
"color_matching",
> + &f_uvc_color_matching_type);
> + config_group_init_type_name(&f_uvc_streaming_fs_group, "fs",
> + &f_uvc_streaming_fs_type);
> + config_group_init_type_name(&f_uvc_streaming_hs_group, "hs",
> + &f_uvc_streaming_hs_type);
> + config_group_init_type_name(&f_uvc_streaming_ss_group, "ss",
> + &f_uvc_streaming_ss_type);
> + f_uvc_streaming_class_group.default_groups =
> + f_uvc_streaming_class_default_groups;
> + config_group_init_type_name(&f_uvc_streaming_class_group, "class",
> + &f_uvc_streaming_class_type);
> + config_group_init_type_name(&f_uvc_frame_yuv_group, "yuv",
> + &f_uvc_frame_yuv_type);
> + config_group_init_type_name(&f_uvc_frame_mjpeg_group, "mjpeg",
> + &f_uvc_frame_mjpeg_type);
> + f_uvc_frame_group.default_groups = f_uvc_frame_default_groups;
> + config_group_init_type_name(&f_uvc_frame_group, "frame",
> + &f_uvc_frame_type);
> + config_group_init_type_name(&f_uvc_format_yuv_group, "yuv",
> + &f_uvc_format_yuv_type);
> + config_group_init_type_name(&f_uvc_format_mjpeg_group, "mjpeg",
> + &f_uvc_format_mjpeg_type);
> + f_uvc_format_group.group.default_groups = f_uvc_format_default_groups;
> + INIT_LIST_HEAD(&f_uvc_format_group.known_targets);
> + config_group_init_type_name(&f_uvc_format_group.group, "format",
> + &f_uvc_format_type);
> + f_uvc_streaming_group.group.default_groups =
> f_uvc_streaming_default_groups;
> + INIT_LIST_HEAD(&f_uvc_streaming_group.known_targets);
> + config_group_init_type_name(&f_uvc_streaming_group.group, "streaming",
> + &f_uvc_streaming_type);
> + opts->func_inst.group.default_groups = f_uvc_default_groups;
> + opts->fs_class = &f_uvc_class_fs_group.cg_item;
> + opts->ss_class = &f_uvc_class_ss_group.cg_item;
> + opts->fs_streaming_class = &f_uvc_streaming_fs_group.cg_item;
> + opts->hs_streaming_class = &f_uvc_streaming_hs_group.cg_item;
> + opts->ss_streaming_class = &f_uvc_streaming_ss_group.cg_item;
> + INIT_LIST_HEAD(&opts->known_targets);
> + config_group_init_type_name(&opts->func_inst.group, "",
> + &uvc_func_type);
> +
> return &opts->func_inst;
> }
>
> static void uvc_free(struct usb_function *f)
> {
> struct uvc_device *uvc;
> + struct f_uvc_opts *opts;
>
> uvc = to_uvc(f);
> + opts = container_of(f->fi, struct f_uvc_opts, func_inst);
> kfree(uvc);
> + mutex_lock(&opts->lock);
> + --opts->refcnt;
> + mutex_unlock(&opts->lock);
> }
>
> static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
> @@ -778,14 +868,17 @@ struct usb_function *uvc_alloc(struct
> usb_function_instance *fi) if (uvc == NULL)
> return ERR_PTR(-ENOMEM);
>
> - uvc->state = UVC_STATE_DISCONNECTED;
> opts = container_of(fi, struct f_uvc_opts, func_inst);
> -
> + mutex_lock(&opts->lock);
> + ++opts->refcnt;
> uvc->desc.fs_control = opts->fs_control;
> uvc->desc.ss_control = opts->ss_control;
> uvc->desc.fs_streaming = opts->fs_streaming;
> uvc->desc.hs_streaming = opts->hs_streaming;
> uvc->desc.ss_streaming = opts->ss_streaming;
> + mutex_unlock(&opts->lock);
> +
> + uvc->state = UVC_STATE_DISCONNECTED;
>
> /* Register the function. */
> uvc->func.name = "uvc";
> diff --git a/drivers/usb/gadget/u_uvc.h b/drivers/usb/gadget/u_uvc.h
> index 1909ad5..8277fdf 100644
> --- a/drivers/usb/gadget/u_uvc.h
> +++ b/drivers/usb/gadget/u_uvc.h
> @@ -29,6 +29,25 @@ struct f_uvc_opts {
> const struct uvc_descriptor_header * const *fs_streaming;
> const struct uvc_descriptor_header * const *hs_streaming;
> const struct uvc_descriptor_header * const *ss_streaming;
> +
> + /*
> + * Read/write access to configfs attributes is handled by configfs.
> + *
> + * This is to protect the data from concurrent access by read/write
> + * and create symlink/remove symlink.
This sounds like a pretty common problem to me, shouldn't it be handled by the
configfs core ?
> + */
> + struct mutex lock;
> + int refcnt;
> + /*
> + * In uvc function's configfs directory there will be symbolic links.
> + * The allowed targets are in the "known_targets" list.
> + */
> + struct list_head known_targets;
> + struct config_item *fs_class;
> + struct config_item *ss_class;
> + struct config_item *fs_streaming_class;
> + struct config_item *ss_streaming_class;
> + struct config_item *hs_streaming_class;
> };
>
> void uvc_set_trace_param(unsigned int uvc_gadget_trace_param_webcam);
> diff --git a/drivers/usb/gadget/uvc_configfs.c
> b/drivers/usb/gadget/uvc_configfs.c new file mode 100644
> index 0000000..2031114
> --- /dev/null
> +++ b/drivers/usb/gadget/uvc_configfs.c
> @@ -0,0 +1,2928 @@
> +/*
> + * uvc_configfs.c
> + *
> + * Configfs hierarchy definitions for the uvc function
> + *
> + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * Author: Andrzej Pietrasiewicz <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include "uvc_configfs.h"
> +#include "configfs.h"
> +#include "u_uvc.h"
Please sort the headers here too.
I'll have to learn about configfs to understand the code below, that will take
a bit more time. I propose sorting out the rest of the issues I've pointed out
for the patch set and work on getting patches 1/8 to 7/8 mainlined in the
meantime.
> diff --git a/drivers/usb/gadget/uvc_configfs.h
> b/drivers/usb/gadget/uvc_configfs.h new file mode 100644
> index 0000000..13f554f
> --- /dev/null
> +++ b/drivers/usb/gadget/uvc_configfs.h
> @@ -0,0 +1,283 @@
> +/*
> + * uvc_configfs.h
> + *
> + * Configfs hierarchy definitions for the uvc function
> + *
> + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * Author: Andrzej Pietrasiewicz <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef UVC_CONFIGFS_H
> +#define UVC_CONFIGFS_H
The UVC gadget headers are guarded by
_F_UVC_H_
U_UVC_H
_UVC_GADGET_H_
UVC_CONFIGFS_H
_UVC_QUEUE_H_
__UVC__V4L2__H__
__UVC__VIDEO__H__
I propose standardizing it to
__F_UVC_H__
__U_UVC_H__
__UVC_GADGET_H__
__UVC_CONFIGFS_H__
__UVC_QUEUE_H__
__UVC_V4L2_H__
__UVC_VIDEO_H__
or
_F_UVC_H_
_U_UVC_H_
_UVC_GADGET_H_
_UVC_CONFIGFS_H_
_UVC_QUEUE_H_
_UVC_V4L2_H_
_UVC_VIDEO_H_
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/configfs.h>
> +#include <linux/usb/video.h>
Usual comment :-)
[snip]
> +
> +#endif /* UVC_CONFIGFS_H */
--
Regards,
Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html