diff options
Diffstat (limited to 'drivers/usb/gadget/legacy')
-rw-r--r-- | drivers/usb/gadget/legacy/Kconfig | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/Makefile | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/audio.c | 149 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/dbgp.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/inode.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/webcam.c | 75 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/zero.c | 21 |
7 files changed, 226 insertions, 30 deletions
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index aa376f006333..24392d269709 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -54,6 +54,8 @@ config USB_AUDIO depends on SND select USB_LIBCOMPOSITE select SND_PCM + select USB_F_UAC1 if GADGET_UAC1 + select USB_F_UAC2 if !GADGET_UAC1 help This Gadget Audio driver is compatible with USB Audio Class specification 2.0. It implements 1 AudioControl interface, @@ -466,6 +468,7 @@ config USB_G_WEBCAM depends on VIDEO_DEV select USB_LIBCOMPOSITE select VIDEOBUF2_VMALLOC + select USB_F_UVC help The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile index edba2d1ee0f3..7f485f25705e 100644 --- a/drivers/usb/gadget/legacy/Makefile +++ b/drivers/usb/gadget/legacy/Makefile @@ -2,9 +2,9 @@ # USB gadget drivers # -ccflags-y := -Idrivers/usb/gadget/ -ccflags-y += -Idrivers/usb/gadget/udc/ -ccflags-y += -Idrivers/usb/gadget/function/ +ccflags-y := -I$(srctree)/drivers/usb/gadget/ +ccflags-y += -I$(srctree)/drivers/usb/gadget/udc/ +ccflags-y += -I$(srctree)/drivers/usb/gadget/function/ g_zero-y := zero.o g_audio-y := audio.o diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index 6eb695e5e43a..f46a3956e43d 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -21,6 +21,66 @@ USB_GADGET_COMPOSITE_OPTIONS(); +#ifndef CONFIG_GADGET_UAC1 +#include "u_uac2.h" + +/* Playback(USB-IN) Default Stereo - Fl/Fr */ +static int p_chmask = UAC2_DEF_PCHMASK; +module_param(p_chmask, uint, S_IRUGO); +MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); + +/* Playback Default 48 KHz */ +static int p_srate = UAC2_DEF_PSRATE; +module_param(p_srate, uint, S_IRUGO); +MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); + +/* Playback Default 16bits/sample */ +static int p_ssize = UAC2_DEF_PSSIZE; +module_param(p_ssize, uint, S_IRUGO); +MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); + +/* Capture(USB-OUT) Default Stereo - Fl/Fr */ +static int c_chmask = UAC2_DEF_CCHMASK; +module_param(c_chmask, uint, S_IRUGO); +MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); + +/* Capture Default 64 KHz */ +static int c_srate = UAC2_DEF_CSRATE; +module_param(c_srate, uint, S_IRUGO); +MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); + +/* Capture Default 16bits/sample */ +static int c_ssize = UAC2_DEF_CSSIZE; +module_param(c_ssize, uint, S_IRUGO); +MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); +#else +#include "u_uac1.h" + +static char *fn_play = FILE_PCM_PLAYBACK; +module_param(fn_play, charp, S_IRUGO); +MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); + +static char *fn_cap = FILE_PCM_CAPTURE; +module_param(fn_cap, charp, S_IRUGO); +MODULE_PARM_DESC(fn_cap, "Capture PCM device file name"); + +static char *fn_cntl = FILE_CONTROL; +module_param(fn_cntl, charp, S_IRUGO); +MODULE_PARM_DESC(fn_cntl, "Control device file name"); + +static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; +module_param(req_buf_size, int, S_IRUGO); +MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); + +static int req_count = UAC1_REQ_COUNT; +module_param(req_count, int, S_IRUGO); +MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); + +static int audio_buf_size = UAC1_AUDIO_BUF_SIZE; +module_param(audio_buf_size, int, S_IRUGO); +MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); +#endif + /* string IDs are assigned dynamically */ static struct usb_string strings_dev[] = { @@ -40,12 +100,12 @@ static struct usb_gadget_strings *audio_strings[] = { NULL, }; -#ifdef CONFIG_GADGET_UAC1 -#include "u_uac1.h" -#include "u_uac1.c" -#include "f_uac1.c" +#ifndef CONFIG_GADGET_UAC1 +static struct usb_function_instance *fi_uac2; +static struct usb_function *f_uac2; #else -#include "f_uac2.c" +static struct usb_function_instance *fi_uac1; +static struct usb_function *f_uac1; #endif /*-------------------------------------------------------------------------*/ @@ -109,6 +169,8 @@ static const struct usb_descriptor_header *otg_desc[] = { static int __init audio_do_config(struct usb_configuration *c) { + int status; + /* FIXME alloc iConfiguration string, set it in c->strings */ if (gadget_is_otg(c->cdev->gadget)) { @@ -116,7 +178,31 @@ static int __init audio_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - audio_bind_config(c); +#ifdef CONFIG_GADGET_UAC1 + f_uac1 = usb_get_function(fi_uac1); + if (IS_ERR(f_uac1)) { + status = PTR_ERR(f_uac1); + return status; + } + + status = usb_add_function(c, f_uac1); + if (status < 0) { + usb_put_function(f_uac1); + return status; + } +#else + f_uac2 = usb_get_function(fi_uac2); + if (IS_ERR(f_uac2)) { + status = PTR_ERR(f_uac2); + return status; + } + + status = usb_add_function(c, f_uac2); + if (status < 0) { + usb_put_function(f_uac2); + return status; + } +#endif return 0; } @@ -126,17 +212,47 @@ static struct usb_configuration audio_config_driver = { .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -#ifndef CONFIG_GADGET_UAC1 - .unbind = uac2_unbind_config, -#endif }; /*-------------------------------------------------------------------------*/ static int __init audio_bind(struct usb_composite_dev *cdev) { +#ifndef CONFIG_GADGET_UAC1 + struct f_uac2_opts *uac2_opts; +#else + struct f_uac1_opts *uac1_opts; +#endif int status; +#ifndef CONFIG_GADGET_UAC1 + fi_uac2 = usb_get_function_instance("uac2"); + if (IS_ERR(fi_uac2)) + return PTR_ERR(fi_uac2); +#else + fi_uac1 = usb_get_function_instance("uac1"); + if (IS_ERR(fi_uac1)) + return PTR_ERR(fi_uac1); +#endif + +#ifndef CONFIG_GADGET_UAC1 + uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst); + uac2_opts->p_chmask = p_chmask; + uac2_opts->p_srate = p_srate; + uac2_opts->p_ssize = p_ssize; + uac2_opts->c_chmask = c_chmask; + uac2_opts->c_srate = c_srate; + uac2_opts->c_ssize = c_ssize; +#else + uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); + uac1_opts->fn_play = fn_play; + uac1_opts->fn_cap = fn_cap; + uac1_opts->fn_cntl = fn_cntl; + uac1_opts->req_buf_size = req_buf_size; + uac1_opts->req_count = req_count; + uac1_opts->audio_buf_size = audio_buf_size; +#endif + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; @@ -152,13 +268,26 @@ static int __init audio_bind(struct usb_composite_dev *cdev) return 0; fail: +#ifndef CONFIG_GADGET_UAC1 + usb_put_function_instance(fi_uac2); +#else + usb_put_function_instance(fi_uac1); +#endif return status; } static int __exit audio_unbind(struct usb_composite_dev *cdev) { #ifdef CONFIG_GADGET_UAC1 - gaudio_cleanup(); + if (!IS_ERR_OR_NULL(f_uac1)) + usb_put_function(f_uac1); + if (!IS_ERR_OR_NULL(fi_uac1)) + usb_put_function_instance(fi_uac1); +#else + if (!IS_ERR_OR_NULL(f_uac2)) + usb_put_function(f_uac2); + if (!IS_ERR_OR_NULL(fi_uac2)) + usb_put_function_instance(fi_uac2); #endif return 0; } diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index 225e385a6160..1b075132f8f1 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -410,6 +410,7 @@ static __refdata struct usb_gadget_driver dbgp_driver = { .bind = dbgp_bind, .unbind = dbgp_unbind, .setup = dbgp_setup, + .reset = dbgp_disconnect, .disconnect = dbgp_disconnect, .driver = { .owner = THIS_MODULE, diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index e96077b8bf79..edefec2cc584 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1775,6 +1775,7 @@ static struct usb_gadget_driver gadgetfs_driver = { .bind = gadgetfs_bind, .unbind = gadgetfs_unbind, .setup = gadgetfs_setup, + .reset = gadgetfs_disconnect, .disconnect = gadgetfs_disconnect, .suspend = gadgetfs_suspend, diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c index a11d8e420bfe..04a3da20f742 100644 --- a/drivers/usb/gadget/legacy/webcam.c +++ b/drivers/usb/gadget/legacy/webcam.c @@ -12,23 +12,31 @@ #include <linux/kernel.h> #include <linux/device.h> +#include <linux/module.h> #include <linux/usb/video.h> -#include "f_uvc.h" - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "uvc_queue.c" -#include "uvc_video.c" -#include "uvc_v4l2.c" -#include "f_uvc.c" +#include "u_uvc.h" USB_GADGET_COMPOSITE_OPTIONS(); + +/*-------------------------------------------------------------------------*/ + +/* module parameters specific to the Video streaming endpoint */ +static unsigned int streaming_interval = 1; +module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_interval, "1 - 16"); + +static unsigned int streaming_maxpacket = 1024; +module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); + +static unsigned int streaming_maxburst; +module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); + +static unsigned int trace; +module_param(trace, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(trace, "Trace level bitmask"); /* -------------------------------------------------------------------------- * Device descriptor */ @@ -63,6 +71,9 @@ static struct usb_gadget_strings *webcam_device_strings[] = { NULL, }; +static struct usb_function_instance *fi_uvc; +static struct usb_function *f_uvc; + static struct usb_device_descriptor webcam_device_descriptor = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, @@ -326,9 +337,17 @@ static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = { static int __init webcam_config_bind(struct usb_configuration *c) { - return uvc_bind_config(c, uvc_fs_control_cls, uvc_ss_control_cls, - uvc_fs_streaming_cls, uvc_hs_streaming_cls, - uvc_ss_streaming_cls); + int status = 0; + + f_uvc = usb_get_function(fi_uvc); + if (IS_ERR(f_uvc)) + return PTR_ERR(f_uvc); + + status = usb_add_function(c, f_uvc); + if (status < 0) + usb_put_function(f_uvc); + + return status; } static struct usb_configuration webcam_config_driver = { @@ -342,14 +361,36 @@ static struct usb_configuration webcam_config_driver = { static int /* __init_or_exit */ webcam_unbind(struct usb_composite_dev *cdev) { + if (!IS_ERR_OR_NULL(f_uvc)) + usb_put_function(f_uvc); + if (!IS_ERR_OR_NULL(fi_uvc)) + usb_put_function_instance(fi_uvc); return 0; } static int __init webcam_bind(struct usb_composite_dev *cdev) { + struct f_uvc_opts *uvc_opts; int ret; + fi_uvc = usb_get_function_instance("uvc"); + if (IS_ERR(fi_uvc)) + return PTR_ERR(fi_uvc); + + uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst); + + uvc_opts->streaming_interval = streaming_interval; + uvc_opts->streaming_maxpacket = streaming_maxpacket; + uvc_opts->streaming_maxburst = streaming_maxburst; + uvc_set_trace_param(trace); + + uvc_opts->fs_control = uvc_fs_control_cls; + uvc_opts->ss_control = uvc_ss_control_cls; + uvc_opts->fs_streaming = uvc_fs_streaming_cls; + uvc_opts->hs_streaming = uvc_hs_streaming_cls; + uvc_opts->ss_streaming = uvc_ss_streaming_cls; + /* Allocate string descriptor numbers ... note that string contents * can be overridden by the composite_dev glue. */ @@ -373,7 +414,7 @@ webcam_bind(struct usb_composite_dev *cdev) return 0; error: - webcam_unbind(cdev); + usb_put_function_instance(fi_uvc); return ret; } diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c index c3d496828b74..ebf09f439f3a 100644 --- a/drivers/usb/gadget/legacy/zero.c +++ b/drivers/usb/gadget/legacy/zero.c @@ -68,6 +68,8 @@ static struct usb_zero_options gzero_options = { .isoc_maxpacket = GZERO_ISOC_MAXPACKET, .bulk_buflen = GZERO_BULK_BUFLEN, .qlen = GZERO_QLEN, + .int_interval = GZERO_INT_INTERVAL, + .int_maxpacket = GZERO_INT_MAXPACKET, }; /*-------------------------------------------------------------------------*/ @@ -266,6 +268,21 @@ module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)"); +module_param_named(int_interval, gzero_options.int_interval, uint, + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(int_interval, "1 - 16"); + +module_param_named(int_maxpacket, gzero_options.int_maxpacket, uint, + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(int_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); + +module_param_named(int_mult, gzero_options.int_mult, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(int_mult, "0 - 2 (hs/ss only)"); + +module_param_named(int_maxburst, gzero_options.int_maxburst, uint, + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(int_maxburst, "0 - 15 (ss only)"); + static struct usb_function *func_lb; static struct usb_function_instance *func_inst_lb; @@ -301,6 +318,10 @@ static int __init zero_bind(struct usb_composite_dev *cdev) ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket; ss_opts->isoc_mult = gzero_options.isoc_mult; ss_opts->isoc_maxburst = gzero_options.isoc_maxburst; + ss_opts->int_interval = gzero_options.int_interval; + ss_opts->int_maxpacket = gzero_options.int_maxpacket; + ss_opts->int_mult = gzero_options.int_mult; + ss_opts->int_maxburst = gzero_options.int_maxburst; ss_opts->bulk_buflen = gzero_options.bulk_buflen; func_ss = usb_get_function(func_inst_ss); |