Hi Andrzej,

On Thu, Jul 17, 2014 at 02:42:19PM +0200, Andrzej Pietrasiewicz wrote:
> Add support for using uvc as a component of a composite gadget
> set up with configfs.
> 
> Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
> ---
>  Documentation/ABI/testing/configfs-usb-gadget-uvc |   11 +
>  drivers/usb/gadget/Kconfig                        |   11 +
>  drivers/usb/gadget/function/Makefile              |    2 +-
>  drivers/usb/gadget/function/f_uvc.c               |   94 +
>  drivers/usb/gadget/function/u_uvc.h               |   19 +
>  drivers/usb/gadget/function/uvc_configfs.c        | 2928 
> +++++++++++++++++++++
>  drivers/usb/gadget/function/uvc_configfs.h        |  283 ++
>  7 files changed, 3347 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-uvc
>  create mode 100644 drivers/usb/gadget/function/uvc_configfs.c
>  create mode 100644 drivers/usb/gadget/function/uvc_configfs.h
> 
> diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc 
> b/Documentation/ABI/testing/configfs-usb-gadget-uvc
> new file mode 100644
> index 0000000..b3b4ba5
> --- /dev/null
> +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
> @@ -0,0 +1,11 @@
> +What:                /config/usb-gadget/gadget/functions/uvc.name
> +Date:                Oct 2014
> +KenelVersion:        3.18
> +Description:
> +             The attributes:
> +
> +             streaming_interval      - 1..16
> +             streaming_maxpacket     - 1..1023 (fs), 1..3072 (hs/ss)
> +             streaming_maxburst      - 0..15 (ss only)
> +             trace                   - trace level bitmask,
> +                                       common for all uvc instances
> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> index 4b3d4e9..ce55234 100644
> --- a/drivers/usb/gadget/Kconfig
> +++ b/drivers/usb/gadget/Kconfig
> @@ -356,6 +356,17 @@ config USB_CONFIGFS_F_FS
>         implemented in kernel space (for instance Ethernet, serial or
>         mass storage) and other are implemented in user space.
>  
> +config USB_CONFIGFS_F_UVC
> +     boolean "USB Webcam function"     
> +     depends on USB_CONFIGFS
> +     depends on VIDEO_DEV
> +     select VIDEOBUF2_VMALLOC
> +     select USB_F_UVC
> +     help
> +       The Webcam function acts as a composite USB Audio and Video Class
> +       device. It provides a userspace API to process UVC control requests
> +       and stream video data to the host.
> +
>  source "drivers/usb/gadget/legacy/Kconfig"
>  
>  endchoice
> diff --git a/drivers/usb/gadget/function/Makefile 
> b/drivers/usb/gadget/function/Makefile
> index ad80f21..94391f3 100644
> --- a/drivers/usb/gadget/function/Makefile
> +++ b/drivers/usb/gadget/function/Makefile
> @@ -32,5 +32,5 @@ usb_f_mass_storage-y                := f_mass_storage.o 
> storage_common.o
>  obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
>  usb_f_fs-y                   := f_fs.o
>  obj-$(CONFIG_USB_F_FS)               += usb_f_fs.o
> -usb_f_uvc-y                  := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o
> +usb_f_uvc-y                  := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o 
> uvc_configfs.o
>  obj-$(CONFIG_USB_F_UVC)              += usb_f_uvc.o
> diff --git a/drivers/usb/gadget/function/f_uvc.c 
> b/drivers/usb/gadget/function/f_uvc.c
> index 9d22928..10ad916 100644
> --- a/drivers/usb/gadget/function/f_uvc.c
> +++ b/drivers/usb/gadget/function/f_uvc.c
> @@ -28,6 +28,7 @@
>  #include <media/v4l2-event.h>
>  
>  #include "uvc.h"
> +#include "uvc_configfs.h"
>  #include "uvc_v4l2.h"
>  #include "uvc_video.h"
>  #include "u_uvc.h"
> @@ -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);
> +
>       /* Descriptors layout
>        *
>        * uvc_iad
> @@ -642,6 +646,7 @@ uvc_function_bind(struct usb_configuration *c, struct 
> usb_function *f)
>       uvc_streaming_intf_alt0.iInterface = ret;
>       uvc_streaming_intf_alt1.iInterface = ret;
>  
> +
>       /* Allocate interface IDs. */
>       if ((ret = usb_interface_id(c, f)) < 0)
>               goto error;
> @@ -657,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;
> +     }
>  
>       /* Preallocate control endpoint request. */
>       uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
> @@ -735,16 +755,87 @@ 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 = to_uvc(f);
> +     struct f_uvc_opts *opts;
>  
> +     opts = container_of(f->fi, struct f_uvc_opts, func_inst);
>       kfree(uvc);

How about to_f_uvc_opts instead of container_of here?

[snip]

I am trying to work with your patches. It was possible
to compile and run this together with your other f_uvc series.

Now I tried the configfs instructions in the coverletter together
with the dummy_udc.0. On this udc it was possible to load
webcam.ko. But the configfs implementation does bailout on uvc_copy_descriptors:


        if (!uvc_control_desc || !uvc_streaming_cl)
               return ERR_PTR(-ENODEV);


root@virtual:/cfg/usb_gadget/g1 echo dummy_udc.0 > UDC
configfs-gadget gadget: uvc_function_bind
configfs-gadget dummy_udc.0: failed to start g1: -19
sh: write error: No such device

Regards,
Michael


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to