mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Revert "FROMLIST: usb: gadget: f_uac*: Reduce code duplication"
This reverts commit 70267887d6.
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
Change-Id: I4487188e9b1d19332c041b6a4385854fd6b05f14
This commit is contained in:
@@ -17,7 +17,18 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,25 +13,37 @@
|
||||
#define __U_UAC_H
|
||||
|
||||
#include <linux/usb/composite.h>
|
||||
#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)
|
||||
|
||||
38
drivers/usb/gadget/function/u_uac1.h
Normal file
38
drivers/usb/gadget/function/u_uac1.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_uac1.h - Utility definitions for UAC1 function
|
||||
*
|
||||
* Copyright (C) 2016 Ruslan Bilovol <ruslan.bilovol@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __U_UAC1_H
|
||||
#define __U_UAC1_H
|
||||
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#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 */
|
||||
41
drivers/usb/gadget/function/u_uac2.h
Normal file
41
drivers/usb/gadget/function/u_uac2.h
Normal file
@@ -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 <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_UAC2_H
|
||||
#define U_UAC2_H
|
||||
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user