From e12828d267e458a0190a55b673a16d4fd04813b4 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 1 Dec 2021 19:50:29 +0800 Subject: [PATCH] Revert "FROMLIST: usb: gadget: f_uac*: Reduce code duplication" This reverts commit 70267887d6fc6a7dd9ddff0b47c7322a968ba286. Signed-off-by: Tao Huang Change-Id: I4487188e9b1d19332c041b6a4385854fd6b05f14 --- drivers/usb/gadget/function/f_uac1.c | 141 +++++++++++++++++------ drivers/usb/gadget/function/f_uac2.c | 159 +++++++++++++++++++------- drivers/usb/gadget/function/u_audio.c | 1 + drivers/usb/gadget/function/u_uac.h | 83 +++++++++++++- drivers/usb/gadget/function/u_uac1.h | 38 ++++++ drivers/usb/gadget/function/u_uac2.h | 41 +++++++ drivers/usb/gadget/legacy/audio.c | 91 +++++++++++---- 7 files changed, 448 insertions(+), 106 deletions(-) create mode 100644 drivers/usb/gadget/function/u_uac1.h create mode 100644 drivers/usb/gadget/function/u_uac2.h diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 3af8a1cd172e..e745e901b3b7 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -17,7 +17,18 @@ #include #include "u_audio.h" -#include "u_uac.h" +#include "u_uac1.h" + +struct f_uac1 { + struct g_audio g_audio; + u8 ac_intf, as_in_intf, as_out_intf; + u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */ +}; + +static inline struct f_uac1 *func_to_uac1(struct usb_function *f) +{ + return container_of(f, struct f_uac1, g_audio.func); +} /* * DESCRIPTORS ... most are static, but strings and full @@ -434,7 +445,7 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) struct usb_composite_dev *cdev = f->config->cdev; struct usb_gadget *gadget = cdev->gadget; struct device *dev = &gadget->dev; - struct f_uac *uac1 = func_to_uac(f); + struct f_uac1 *uac1 = func_to_uac1(f); int ret = 0; /* No i/f has more than 2 alt settings */ @@ -479,7 +490,7 @@ static int f_audio_get_alt(struct usb_function *f, unsigned intf) struct usb_composite_dev *cdev = f->config->cdev; struct usb_gadget *gadget = cdev->gadget; struct device *dev = &gadget->dev; - struct f_uac *uac1 = func_to_uac(f); + struct f_uac1 *uac1 = func_to_uac1(f); if (intf == uac1->ac_intf) return uac1->ac_alt; @@ -497,7 +508,7 @@ static int f_audio_get_alt(struct usb_function *f, unsigned intf) static void f_audio_disable(struct usb_function *f) { - struct f_uac *uac1 = func_to_uac(f); + struct f_uac1 *uac1 = func_to_uac1(f); uac1->as_out_alt = 0; uac1->as_in_alt = 0; @@ -513,16 +524,16 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct usb_gadget *gadget = cdev->gadget; - struct f_uac *uac1 = func_to_uac(f); + struct f_uac1 *uac1 = func_to_uac1(f); struct g_audio *audio = func_to_g_audio(f); - struct f_uac_opts *audio_opts; + struct f_uac1_opts *audio_opts; struct usb_ep *ep = NULL; struct usb_string *us; u8 *sam_freq; int rate; int status; - audio_opts = container_of(f->fi, struct f_uac_opts, func_inst); + audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst); us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1)); if (IS_ERR(us)) @@ -635,26 +646,82 @@ fail: /*-------------------------------------------------------------------------*/ +static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_uac1_opts, + func_inst.group); +} + +static void f_uac1_attr_release(struct config_item *item) +{ + struct f_uac1_opts *opts = to_f_uac1_opts(item); + + usb_put_function_instance(&opts->func_inst); +} + static struct configfs_item_operations f_uac1_item_ops = { - .release = f_uac_attr_release, + .release = f_uac1_attr_release, }; -UAC_ATTRIBUTE(c_chmask); -UAC_ATTRIBUTE(c_srate); -UAC_ATTRIBUTE(c_ssize); -UAC_ATTRIBUTE(p_chmask); -UAC_ATTRIBUTE(p_srate); -UAC_ATTRIBUTE(p_ssize); -UAC_ATTRIBUTE(req_number); +#define UAC1_ATTRIBUTE(name) \ +static ssize_t f_uac1_opts_##name##_show( \ + struct config_item *item, \ + char *page) \ +{ \ + struct f_uac1_opts *opts = to_f_uac1_opts(item); \ + int result; \ + \ + mutex_lock(&opts->lock); \ + result = sprintf(page, "%u\n", opts->name); \ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_uac1_opts_##name##_store( \ + struct config_item *item, \ + const char *page, size_t len) \ +{ \ + struct f_uac1_opts *opts = to_f_uac1_opts(item); \ + int ret; \ + u32 num; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + ret = kstrtou32(page, 0, &num); \ + if (ret) \ + goto end; \ + \ + opts->name = num; \ + ret = len; \ + \ +end: \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(f_uac1_opts_, name) + +UAC1_ATTRIBUTE(c_chmask); +UAC1_ATTRIBUTE(c_srate); +UAC1_ATTRIBUTE(c_ssize); +UAC1_ATTRIBUTE(p_chmask); +UAC1_ATTRIBUTE(p_srate); +UAC1_ATTRIBUTE(p_ssize); +UAC1_ATTRIBUTE(req_number); static struct configfs_attribute *f_uac1_attrs[] = { - &f_uac_opts_attr_c_chmask, - &f_uac_opts_attr_c_srate, - &f_uac_opts_attr_c_ssize, - &f_uac_opts_attr_p_chmask, - &f_uac_opts_attr_p_srate, - &f_uac_opts_attr_p_ssize, - &f_uac_opts_attr_req_number, + &f_uac1_opts_attr_c_chmask, + &f_uac1_opts_attr_c_srate, + &f_uac1_opts_attr_c_ssize, + &f_uac1_opts_attr_p_chmask, + &f_uac1_opts_attr_p_srate, + &f_uac1_opts_attr_p_ssize, + &f_uac1_opts_attr_req_number, NULL, }; @@ -666,15 +733,15 @@ static const struct config_item_type f_uac1_func_type = { static void f_audio_free_inst(struct usb_function_instance *f) { - struct f_uac_opts *opts; + struct f_uac1_opts *opts; - opts = container_of(f, struct f_uac_opts, func_inst); + opts = container_of(f, struct f_uac1_opts, func_inst); kfree(opts); } static struct usb_function_instance *f_audio_alloc_inst(void) { - struct f_uac_opts *opts; + struct f_uac1_opts *opts; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) @@ -686,23 +753,23 @@ static struct usb_function_instance *f_audio_alloc_inst(void) config_group_init_type_name(&opts->func_inst.group, "", &f_uac1_func_type); - opts->c_chmask = UAC_DEF_CCHMASK; - opts->c_srate = UAC_DEF_CSRATE; - opts->c_ssize = UAC_DEF_CSSIZE; - opts->p_chmask = UAC_DEF_PCHMASK; - opts->p_srate = UAC_DEF_PSRATE; - opts->p_ssize = UAC_DEF_PSSIZE; - opts->req_number = UAC_DEF_REQ_NUM; + opts->c_chmask = UAC1_DEF_CCHMASK; + opts->c_srate = UAC1_DEF_CSRATE; + opts->c_ssize = UAC1_DEF_CSSIZE; + opts->p_chmask = UAC1_DEF_PCHMASK; + opts->p_srate = UAC1_DEF_PSRATE; + opts->p_ssize = UAC1_DEF_PSSIZE; + opts->req_number = UAC1_DEF_REQ_NUM; return &opts->func_inst; } static void f_audio_free(struct usb_function *f) { struct g_audio *audio; - struct f_uac_opts *opts; + struct f_uac1_opts *opts; audio = func_to_g_audio(f); - opts = container_of(f->fi, struct f_uac_opts, func_inst); + opts = container_of(f->fi, struct f_uac1_opts, func_inst); kfree(audio); mutex_lock(&opts->lock); --opts->refcnt; @@ -721,15 +788,15 @@ static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f) static struct usb_function *f_audio_alloc(struct usb_function_instance *fi) { - struct f_uac *uac1; - struct f_uac_opts *opts; + struct f_uac1 *uac1; + struct f_uac1_opts *opts; /* allocate and initialize one new instance */ uac1 = kzalloc(sizeof(*uac1), GFP_KERNEL); if (!uac1) return ERR_PTR(-ENOMEM); - opts = container_of(fi, struct f_uac_opts, func_inst); + opts = container_of(fi, struct f_uac1_opts, func_inst); mutex_lock(&opts->lock); ++opts->refcnt; mutex_unlock(&opts->lock); diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 9a2df37fc87d..f68768e30687 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -12,7 +12,7 @@ #include #include "u_audio.h" -#include "u_uac.h" +#include "u_uac2.h" /* * The driver implements a simple UAC_2 topology. @@ -42,6 +42,23 @@ #define EPIN_EN(_opts) ((_opts)->p_chmask != 0) #define EPOUT_EN(_opts) ((_opts)->c_chmask != 0) +struct f_uac2 { + struct g_audio g_audio; + u8 ac_intf, as_in_intf, as_out_intf; + u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */ +}; + +static inline struct f_uac2 *func_to_uac2(struct usb_function *f) +{ + return container_of(f, struct f_uac2, g_audio.func); +} + +static inline +struct f_uac2_opts *g_audio_to_uac2_opts(struct g_audio *agdev) +{ + return container_of(agdev->func.fi, struct f_uac2_opts, func_inst); +} + /* --------- USB Function Interface ------------- */ enum { @@ -430,7 +447,7 @@ struct cntrl_range_lay3 { __le32 dRES; } __packed; -static int set_ep_max_packet_size(const struct f_uac_opts *uac2_opts, +static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, struct usb_endpoint_descriptor *ep_desc, enum usb_device_speed speed, bool is_playback) { @@ -474,7 +491,7 @@ static int set_ep_max_packet_size(const struct f_uac_opts *uac2_opts, /* Use macro to overcome line length limitation */ #define USBDHDR(p) (struct usb_descriptor_header *)(p) -static void setup_descriptor(struct f_uac_opts *opts) +static void setup_descriptor(struct f_uac2_opts *opts) { /* patch descriptors */ int i = 1; /* ID's start with 1 */ @@ -593,16 +610,16 @@ static void setup_descriptor(struct f_uac_opts *opts) static int afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) { - struct f_uac *uac2 = func_to_uac(fn); + struct f_uac2 *uac2 = func_to_uac2(fn); struct g_audio *agdev = func_to_g_audio(fn); struct usb_composite_dev *cdev = cfg->cdev; struct usb_gadget *gadget = cdev->gadget; struct device *dev = &gadget->dev; - struct f_uac_opts *uac2_opts; + struct f_uac2_opts *uac2_opts; struct usb_string *us; int ret; - uac2_opts = container_of(fn->fi, struct f_uac_opts, func_inst); + uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); us = usb_gstrings_attach(cdev, fn_strings, ARRAY_SIZE(strings_fn)); if (IS_ERR(us)) @@ -759,7 +776,7 @@ static int afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = fn->config->cdev; - struct f_uac *uac2 = func_to_uac(fn); + struct f_uac2 *uac2 = func_to_uac2(fn); struct usb_gadget *gadget = cdev->gadget; struct device *dev = &gadget->dev; int ret = 0; @@ -804,7 +821,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) static int afunc_get_alt(struct usb_function *fn, unsigned intf) { - struct f_uac *uac2 = func_to_uac(fn); + struct f_uac2 *uac2 = func_to_uac2(fn); struct g_audio *agdev = func_to_g_audio(fn); if (intf == uac2->ac_intf) @@ -824,7 +841,7 @@ afunc_get_alt(struct usb_function *fn, unsigned intf) static void afunc_disable(struct usb_function *fn) { - struct f_uac *uac2 = func_to_uac(fn); + struct f_uac2 *uac2 = func_to_uac2(fn); uac2->as_in_alt = 0; uac2->as_out_alt = 0; @@ -837,7 +854,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) { struct usb_request *req = fn->config->cdev->req; struct g_audio *agdev = func_to_g_audio(fn); - struct f_uac_opts *opts; + struct f_uac2_opts *opts; u16 w_length = le16_to_cpu(cr->wLength); u16 w_index = le16_to_cpu(cr->wIndex); u16 w_value = le16_to_cpu(cr->wValue); @@ -846,7 +863,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) int value = -EOPNOTSUPP; int p_srate, c_srate; - opts = g_audio_to_uac_opts(agdev); + opts = g_audio_to_uac2_opts(agdev); p_srate = opts->p_srate; c_srate = opts->c_srate; @@ -878,7 +895,7 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) { struct usb_request *req = fn->config->cdev->req; struct g_audio *agdev = func_to_g_audio(fn); - struct f_uac_opts *opts; + struct f_uac2_opts *opts; u16 w_length = le16_to_cpu(cr->wLength); u16 w_index = le16_to_cpu(cr->wIndex); u16 w_value = le16_to_cpu(cr->wValue); @@ -888,7 +905,7 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) int value = -EOPNOTSUPP; int p_srate, c_srate; - opts = g_audio_to_uac_opts(agdev); + opts = g_audio_to_uac2_opts(agdev); p_srate = opts->p_srate; c_srate = opts->c_srate; @@ -942,7 +959,7 @@ out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) static int setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr) { - struct f_uac *uac2 = func_to_uac(fn); + struct f_uac2 *uac2 = func_to_uac2(fn); struct g_audio *agdev = func_to_g_audio(fn); u16 w_index = le16_to_cpu(cr->wIndex); u8 intf = w_index & 0xff; @@ -994,26 +1011,80 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) return value; } +static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_uac2_opts, + func_inst.group); +} + +static void f_uac2_attr_release(struct config_item *item) +{ + struct f_uac2_opts *opts = to_f_uac2_opts(item); + + usb_put_function_instance(&opts->func_inst); +} + static struct configfs_item_operations f_uac2_item_ops = { - .release = f_uac_attr_release, + .release = f_uac2_attr_release, }; -UAC_ATTRIBUTE(p_chmask); -UAC_ATTRIBUTE(p_srate); -UAC_ATTRIBUTE(p_ssize); -UAC_ATTRIBUTE(c_chmask); -UAC_ATTRIBUTE(c_srate); -UAC_ATTRIBUTE(c_ssize); -UAC_ATTRIBUTE(req_number); +#define UAC2_ATTRIBUTE(name) \ +static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + struct f_uac2_opts *opts = to_f_uac2_opts(item); \ + int result; \ + \ + mutex_lock(&opts->lock); \ + result = sprintf(page, "%u\n", opts->name); \ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + struct f_uac2_opts *opts = to_f_uac2_opts(item); \ + int ret; \ + u32 num; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + ret = kstrtou32(page, 0, &num); \ + if (ret) \ + goto end; \ + \ + opts->name = num; \ + ret = len; \ + \ +end: \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(f_uac2_opts_, name) + +UAC2_ATTRIBUTE(p_chmask); +UAC2_ATTRIBUTE(p_srate); +UAC2_ATTRIBUTE(p_ssize); +UAC2_ATTRIBUTE(c_chmask); +UAC2_ATTRIBUTE(c_srate); +UAC2_ATTRIBUTE(c_ssize); +UAC2_ATTRIBUTE(req_number); static struct configfs_attribute *f_uac2_attrs[] = { - &f_uac_opts_attr_p_chmask, - &f_uac_opts_attr_p_srate, - &f_uac_opts_attr_p_ssize, - &f_uac_opts_attr_c_chmask, - &f_uac_opts_attr_c_srate, - &f_uac_opts_attr_c_ssize, - &f_uac_opts_attr_req_number, + &f_uac2_opts_attr_p_chmask, + &f_uac2_opts_attr_p_srate, + &f_uac2_opts_attr_p_ssize, + &f_uac2_opts_attr_c_chmask, + &f_uac2_opts_attr_c_srate, + &f_uac2_opts_attr_c_ssize, + &f_uac2_opts_attr_req_number, NULL, }; @@ -1025,15 +1096,15 @@ static const struct config_item_type f_uac2_func_type = { static void afunc_free_inst(struct usb_function_instance *f) { - struct f_uac_opts *opts; + struct f_uac2_opts *opts; - opts = container_of(f, struct f_uac_opts, func_inst); + opts = container_of(f, struct f_uac2_opts, func_inst); kfree(opts); } static struct usb_function_instance *afunc_alloc_inst(void) { - struct f_uac_opts *opts; + struct f_uac2_opts *opts; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) @@ -1045,23 +1116,23 @@ static struct usb_function_instance *afunc_alloc_inst(void) config_group_init_type_name(&opts->func_inst.group, "", &f_uac2_func_type); - opts->p_chmask = UAC_DEF_PCHMASK; - opts->p_srate = UAC_DEF_PSRATE; - opts->p_ssize = UAC_DEF_PSSIZE; - opts->c_chmask = UAC_DEF_CCHMASK; - opts->c_srate = UAC_DEF_CSRATE; - opts->c_ssize = UAC_DEF_CSSIZE; - opts->req_number = UAC_DEF_REQ_NUM; + opts->p_chmask = UAC2_DEF_PCHMASK; + opts->p_srate = UAC2_DEF_PSRATE; + opts->p_ssize = UAC2_DEF_PSSIZE; + opts->c_chmask = UAC2_DEF_CCHMASK; + opts->c_srate = UAC2_DEF_CSRATE; + opts->c_ssize = UAC2_DEF_CSSIZE; + opts->req_number = UAC2_DEF_REQ_NUM; return &opts->func_inst; } static void afunc_free(struct usb_function *f) { struct g_audio *agdev; - struct f_uac_opts *opts; + struct f_uac2_opts *opts; agdev = func_to_g_audio(f); - opts = container_of(f->fi, struct f_uac_opts, func_inst); + opts = container_of(f->fi, struct f_uac2_opts, func_inst); kfree(agdev); mutex_lock(&opts->lock); --opts->refcnt; @@ -1080,14 +1151,14 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) static struct usb_function *afunc_alloc(struct usb_function_instance *fi) { - struct f_uac *uac2; - struct f_uac_opts *opts; + struct f_uac2 *uac2; + struct f_uac2_opts *opts; uac2 = kzalloc(sizeof(*uac2), GFP_KERNEL); if (uac2 == NULL) return ERR_PTR(-ENOMEM); - opts = container_of(fi, struct f_uac_opts, func_inst); + opts = container_of(fi, struct f_uac2_opts, func_inst); mutex_lock(&opts->lock); ++opts->refcnt; mutex_unlock(&opts->lock); diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 828452c74684..265c4d805f81 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -335,6 +335,7 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep) dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__); } + int u_audio_start_capture(struct g_audio *audio_dev) { struct snd_uac_chip *uac = audio_dev->uac; diff --git a/drivers/usb/gadget/function/u_uac.h b/drivers/usb/gadget/function/u_uac.h index c473c8e58c26..224ddc397c70 100644 --- a/drivers/usb/gadget/function/u_uac.h +++ b/drivers/usb/gadget/function/u_uac.h @@ -13,25 +13,37 @@ #define __U_UAC_H #include +#include "u_audio.h" #define UAC_DEF_CCHMASK 0x3 #define UAC_DEF_CSRATE 48000 #define UAC_DEF_CSSIZE 2 +#define UAC_DEF_CFU 0 #define UAC_DEF_PCHMASK 0x3 #define UAC_DEF_PSRATE 48000 #define UAC_DEF_PSSIZE 2 +#define UAC_DEF_PFU 0 #define UAC_DEF_REQ_NUM 2 #define UAC1_OUT_EP_MAX_PACKET_SIZE 200 +#define EPIN_EN(_opts) ((_opts)->p_chmask != 0) +#define EPOUT_EN(_opts) ((_opts)->c_chmask != 0) +#define EPIN_FU(_opts) ((_opts)->p_feature_unit != 0) +#define EPOUT_FU(_opts) ((_opts)->c_feature_unit != 0) + struct f_uac_opts { struct usb_function_instance func_inst; int c_chmask; - int c_srate; + int c_srate[UAC_MAX_RATES]; + int c_srate_active; int c_ssize; + int c_feature_unit; int p_chmask; - int p_srate; + int p_srate[UAC_MAX_RATES]; + int p_srate_active; int p_ssize; + int p_feature_unit; int req_number; unsigned bound:1; @@ -82,10 +94,77 @@ end: \ \ CONFIGFS_ATTR(f_uac_opts_, name) +#define UAC_RATE_ATTRIBUTE(name) \ +static ssize_t f_uac_opts_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + struct f_uac_opts *opts = to_f_uac_opts(item); \ + int result = 0; \ + int i; \ + \ + mutex_lock(&opts->lock); \ + page[0] = '\0'; \ + for (i = 0; i < UAC_MAX_RATES; i++) { \ + if (opts->name[i] == 0) \ + continue; \ + result += sprintf(page + strlen(page), "%u,", \ + opts->name[i]); \ + } \ + if (strlen(page) > 0) \ + page[strlen(page) - 1] = '\n'; \ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_uac_opts_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + struct f_uac_opts *opts = to_f_uac_opts(item); \ + char *split_page = NULL; \ + int ret = -EINVAL; \ + char *token; \ + u32 num; \ + int i; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + i = 0; \ + memset(opts->name, 0x00, sizeof(opts->name)); \ + split_page = kstrdup(page, GFP_KERNEL); \ + while ((token = strsep(&split_page, ",")) != NULL) { \ + ret = kstrtou32(token, 0, &num); \ + if (ret) \ + goto end; \ + \ + opts->name[i++] = num; \ + opts->name##_active = num; \ + ret = len; \ + }; \ + \ +end: \ + kfree(split_page); \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(f_uac_opts_, name) + struct f_uac { struct g_audio g_audio; u8 ac_intf, as_in_intf, as_out_intf; u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */ + int ctl_id; + + struct list_head cs; + u8 set_cmd; + u8 get_cmd; + struct usb_audio_control *set_con; + struct usb_audio_control *get_con; }; static inline struct f_uac *func_to_uac(struct usb_function *f) diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h new file mode 100644 index 000000000000..39c0e29e1b46 --- /dev/null +++ b/drivers/usb/gadget/function/u_uac1.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * u_uac1.h - Utility definitions for UAC1 function + * + * Copyright (C) 2016 Ruslan Bilovol + */ + +#ifndef __U_UAC1_H +#define __U_UAC1_H + +#include + +#define UAC1_OUT_EP_MAX_PACKET_SIZE 200 +#define UAC1_DEF_CCHMASK 0x3 +#define UAC1_DEF_CSRATE 48000 +#define UAC1_DEF_CSSIZE 2 +#define UAC1_DEF_PCHMASK 0x3 +#define UAC1_DEF_PSRATE 48000 +#define UAC1_DEF_PSSIZE 2 +#define UAC1_DEF_REQ_NUM 2 + + +struct f_uac1_opts { + struct usb_function_instance func_inst; + int c_chmask; + int c_srate; + int c_ssize; + int p_chmask; + int p_srate; + int p_ssize; + int req_number; + unsigned bound:1; + + struct mutex lock; + int refcnt; +}; + +#endif /* __U_UAC1_H */ diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h new file mode 100644 index 000000000000..b5035711172d --- /dev/null +++ b/drivers/usb/gadget/function/u_uac2.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * u_uac2.h + * + * Utility definitions for UAC2 function + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz + */ + +#ifndef U_UAC2_H +#define U_UAC2_H + +#include + +#define UAC2_DEF_PCHMASK 0x3 +#define UAC2_DEF_PSRATE 48000 +#define UAC2_DEF_PSSIZE 2 +#define UAC2_DEF_CCHMASK 0x3 +#define UAC2_DEF_CSRATE 64000 +#define UAC2_DEF_CSSIZE 2 +#define UAC2_DEF_REQ_NUM 2 + +struct f_uac2_opts { + struct usb_function_instance func_inst; + int p_chmask; + int p_srate; + int p_ssize; + int c_chmask; + int c_srate; + int c_ssize; + int req_number; + bool bound; + + struct mutex lock; + int refcnt; +}; + +#endif diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index 104d1c4ce7f9..a748ed0842e8 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -17,36 +17,69 @@ USB_GADGET_COMPOSITE_OPTIONS(); -#if !defined(CONFIG_GADGET_UAC1) || !defined(CONFIG_GADGET_UAC1_LEGACY) -#include "u_uac.h" +#ifndef CONFIG_GADGET_UAC1 +#include "u_uac2.h" /* Playback(USB-IN) Default Stereo - Fl/Fr */ -static int p_chmask = UAC_DEF_PCHMASK; +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 = UAC_DEF_PSRATE; +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 = UAC_DEF_PSSIZE; +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 = UAC_DEF_CCHMASK; +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 = UAC_DEF_CSRATE; +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 = UAC_DEF_CSSIZE; +static int c_ssize = UAC2_DEF_CSSIZE; +module_param(c_ssize, uint, S_IRUGO); +MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); +#else +#ifndef CONFIG_GADGET_UAC1_LEGACY +#include "u_uac1.h" + +/* Playback(USB-IN) Default Stereo - Fl/Fr */ +static int p_chmask = UAC1_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 = UAC1_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 = UAC1_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 = UAC1_DEF_CCHMASK; +module_param(c_chmask, uint, S_IRUGO); +MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); + +/* Capture Default 48 KHz */ +static int c_srate = UAC1_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 = UAC1_DEF_CSSIZE; module_param(c_ssize, uint, S_IRUGO); MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); #else /* CONFIG_GADGET_UAC1_LEGACY */ @@ -76,6 +109,7 @@ 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 /* CONFIG_GADGET_UAC1_LEGACY */ +#endif /* string IDs are assigned dynamically */ @@ -201,10 +235,14 @@ static struct usb_configuration audio_config_driver = { static int audio_bind(struct usb_composite_dev *cdev) { -#if !defined(CONFIG_GADGET_UAC1) || !defined(CONFIG_GADGET_UAC1_LEGACY) - struct f_uac_opts *uac_opts; +#ifndef CONFIG_GADGET_UAC1 + struct f_uac2_opts *uac2_opts; +#else +#ifndef CONFIG_GADGET_UAC1_LEGACY + struct f_uac1_opts *uac1_opts; #else struct f_uac1_legacy_opts *uac1_opts; +#endif #endif int status; @@ -212,11 +250,9 @@ static int audio_bind(struct usb_composite_dev *cdev) fi_uac2 = usb_get_function_instance("uac2"); if (IS_ERR(fi_uac2)) return PTR_ERR(fi_uac2); - uac_opts = container_of(fi_uac2, struct f_uac_opts, func_inst); #else #ifndef CONFIG_GADGET_UAC1_LEGACY fi_uac1 = usb_get_function_instance("uac1"); - uac_opts = container_of(fi_uac1, struct f_uac_opts, func_inst); #else fi_uac1 = usb_get_function_instance("uac1_legacy"); #endif @@ -224,17 +260,25 @@ static int audio_bind(struct usb_composite_dev *cdev) return PTR_ERR(fi_uac1); #endif -#if !defined(CONFIG_GADGET_UAC1) || !defined(CONFIG_GADGET_UAC1_LEGACY) - memset(uac_opts, 0x0, sizeof(*uac_opts)); - uac_opts->p_chmask = p_chmask; - uac_opts->p_srate[0] = p_srate; - uac_opts->p_srate_active = p_srate; - uac_opts->p_ssize = p_ssize; - uac_opts->c_chmask = c_chmask; - uac_opts->c_srate[0] = c_srate; - uac_opts->c_srate_active = c_srate; - uac_opts->c_ssize = c_ssize; - uac_opts->req_number = UAC_DEF_REQ_NUM; +#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; + uac2_opts->req_number = UAC2_DEF_REQ_NUM; +#else +#ifndef CONFIG_GADGET_UAC1_LEGACY + uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); + uac1_opts->p_chmask = p_chmask; + uac1_opts->p_srate = p_srate; + uac1_opts->p_ssize = p_ssize; + uac1_opts->c_chmask = c_chmask; + uac1_opts->c_srate = c_srate; + uac1_opts->c_ssize = c_ssize; + uac1_opts->req_number = UAC1_DEF_REQ_NUM; #else /* CONFIG_GADGET_UAC1_LEGACY */ uac1_opts = container_of(fi_uac1, struct f_uac1_legacy_opts, func_inst); uac1_opts->fn_play = fn_play; @@ -244,6 +288,7 @@ static int audio_bind(struct usb_composite_dev *cdev) uac1_opts->req_count = req_count; uac1_opts->audio_buf_size = audio_buf_size; #endif /* CONFIG_GADGET_UAC1_LEGACY */ +#endif status = usb_string_ids_tab(cdev, strings_dev); if (status < 0)