From 3aeea3c53e73b972ff07a1d03d6cc07f97de4f2f Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 22 Jul 2014 19:58:35 +0200 Subject: usb: gadget: f_uac2: add configfs support Add support for using f_uac2 function as a component of a gadget composed with configfs. Tested-by: Sebastian Reimers Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Felipe Balbi --- Documentation/ABI/testing/configfs-usb-gadget-uac2 | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-uac2 (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac2 b/Documentation/ABI/testing/configfs-usb-gadget-uac2 new file mode 100644 index 000000000000..2bfdd4efa9bd --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-uac2 @@ -0,0 +1,12 @@ +What: /config/usb-gadget/gadget/functions/uac2.name +Date: Sep 2014 +KernelVersion: 3.18 +Description: + The attributes: + + c_chmask - capture channel mask + c_srate - capture sampling rate + c_ssize - capture sample size (bytes) + p_chmask - playback channel mask + p_srate - playback sampling rate + p_ssize - playback sample size (bytes) -- cgit v1.2.3-59-g8ed1b From 0854611a19ae4dfa56569e6f640017a1d2dd3312 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 22 Jul 2014 19:58:43 +0200 Subject: usb: gadget: f_uac1: add configfs support Add support for using f_uac1 function as a component of a gadget composed with configfs. Tested-by: Sebastian Reimers Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Felipe Balbi --- Documentation/ABI/testing/configfs-usb-gadget-uac1 | 12 ++ drivers/usb/gadget/function/f_uac1.c | 158 +++++++++++++++++++++ drivers/usb/gadget/function/u_uac1.h | 7 +- 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-uac1 (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac1 b/Documentation/ABI/testing/configfs-usb-gadget-uac1 new file mode 100644 index 000000000000..8ba9a123316e --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-uac1 @@ -0,0 +1,12 @@ +What: /config/usb-gadget/gadget/functions/uac1.name +Date: Sep 2014 +KernelVersion: 3.18 +Description: + The attributes: + + audio_buf_size - audio buffer size + fn_cap - capture pcm device file name + fn_cntl - control device file name + fn_play - playback pcm device file name + req_buf_size - ISO OUT endpoint request buffer size + req_count - ISO OUT endpoint request count diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 9a6c7ec66757..f7b203293205 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -760,12 +760,150 @@ static int control_selector_init(struct f_audio *audio) return 0; } +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); +} + +CONFIGFS_ATTR_STRUCT(f_uac1_opts); +CONFIGFS_ATTR_OPS(f_uac1_opts); + +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_uac1_attr_release, + .show_attribute = f_uac1_opts_attr_show, + .store_attribute = f_uac1_opts_attr_store, +}; + +#define UAC1_INT_ATTRIBUTE(name) \ +static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \ + char *page) \ +{ \ + 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 f_uac1_opts *opts, \ + const char *page, size_t len) \ +{ \ + 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; \ +} \ + \ +static struct f_uac1_opts_attribute f_uac1_opts_##name = \ + __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ + f_uac1_opts_##name##_show, \ + f_uac1_opts_##name##_store) + +UAC1_INT_ATTRIBUTE(req_buf_size); +UAC1_INT_ATTRIBUTE(req_count); +UAC1_INT_ATTRIBUTE(audio_buf_size); + +#define UAC1_STR_ATTRIBUTE(name) \ +static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \ + char *page) \ +{ \ + int result; \ + \ + mutex_lock(&opts->lock); \ + result = sprintf(page, "%s\n", opts->name); \ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \ + const char *page, size_t len) \ +{ \ + int ret = -EBUSY; \ + char *tmp; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) \ + goto end; \ + \ + tmp = kstrndup(page, len, GFP_KERNEL); \ + if (tmp) { \ + ret = -ENOMEM; \ + goto end; \ + } \ + if (opts->name##_alloc) \ + kfree(opts->name); \ + opts->name##_alloc = true; \ + opts->name = tmp; \ + ret = len; \ + \ +end: \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +static struct f_uac1_opts_attribute f_uac1_opts_##name = \ + __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ + f_uac1_opts_##name##_show, \ + f_uac1_opts_##name##_store) + +UAC1_STR_ATTRIBUTE(fn_play); +UAC1_STR_ATTRIBUTE(fn_cap); +UAC1_STR_ATTRIBUTE(fn_cntl); + +static struct configfs_attribute *f_uac1_attrs[] = { + &f_uac1_opts_req_buf_size.attr, + &f_uac1_opts_req_count.attr, + &f_uac1_opts_audio_buf_size.attr, + &f_uac1_opts_fn_play.attr, + &f_uac1_opts_fn_cap.attr, + &f_uac1_opts_fn_cntl.attr, + NULL, +}; + +static struct config_item_type f_uac1_func_type = { + .ct_item_ops = &f_uac1_item_ops, + .ct_attrs = f_uac1_attrs, + .ct_owner = THIS_MODULE, +}; + static void f_audio_free_inst(struct usb_function_instance *f) { struct f_uac1_opts *opts; opts = container_of(f, struct f_uac1_opts, func_inst); gaudio_cleanup(opts->card); + if (opts->fn_play_alloc) + kfree(opts->fn_play); + if (opts->fn_cap_alloc) + kfree(opts->fn_cap); + if (opts->fn_cntl_alloc) + kfree(opts->fn_cntl); kfree(opts); } @@ -777,16 +915,31 @@ static struct usb_function_instance *f_audio_alloc_inst(void) if (!opts) return ERR_PTR(-ENOMEM); + mutex_init(&opts->lock); opts->func_inst.free_func_inst = f_audio_free_inst; + config_group_init_type_name(&opts->func_inst.group, "", + &f_uac1_func_type); + + opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; + opts->req_count = UAC1_REQ_COUNT; + opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE; + opts->fn_play = FILE_PCM_PLAYBACK; + opts->fn_cap = FILE_PCM_CAPTURE; + opts->fn_cntl = FILE_CONTROL; return &opts->func_inst; } static void f_audio_free(struct usb_function *f) { struct f_audio *audio = func_to_audio(f); + struct f_uac1_opts *opts; + opts = container_of(f->fi, struct f_uac1_opts, func_inst); kfree(audio); + mutex_lock(&opts->lock); + --opts->refcnt; + mutex_unlock(&opts->lock); } static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f) @@ -797,6 +950,7 @@ 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_audio *audio; + struct f_uac1_opts *opts; /* allocate and initialize one new instance */ audio = kzalloc(sizeof(*audio), GFP_KERNEL); @@ -805,6 +959,10 @@ static struct usb_function *f_audio_alloc(struct usb_function_instance *fi) audio->card.func.name = "g_audio"; + opts = container_of(fi, struct f_uac1_opts, func_inst); + mutex_lock(&opts->lock); + ++opts->refcnt; + mutex_unlock(&opts->lock); INIT_LIST_HEAD(&audio->play_queue); spin_lock_init(&audio->lock); diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h index 214441d96fe1..f8b17fe82efe 100644 --- a/drivers/usb/gadget/function/u_uac1.h +++ b/drivers/usb/gadget/function/u_uac1.h @@ -66,8 +66,13 @@ struct f_uac1_opts { char *fn_play; char *fn_cap; char *fn_cntl; - bool bound; + unsigned bound:1; + unsigned fn_play_alloc:1; + unsigned fn_cap_alloc:1; + unsigned fn_cntl_alloc:1; struct gaudio *card; + struct mutex lock; + int refcnt; }; int gaudio_setup(struct gaudio *card); -- cgit v1.2.3-59-g8ed1b From 534574bb462d044bd6e19471597672302625bd5e Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Tue, 16 Sep 2014 16:10:51 -0500 Subject: uwb: doc: add documentation for ASIE sysfs attribute Document the /sys/class/uwb_rc/uwbN/ASIE sysfs attribute Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-class-uwb_rc | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc b/Documentation/ABI/testing/sysfs-class-uwb_rc index 6a5fd072849d..85f4875d16ac 100644 --- a/Documentation/ABI/testing/sysfs-class-uwb_rc +++ b/Documentation/ABI/testing/sysfs-class-uwb_rc @@ -43,6 +43,19 @@ Description: Reading returns the currently active channel, or -1 if the radio controller is not beaconing. +What: /sys/class/uwb_rc/uwbN/ASIE +Date: August 2014 +KernelVersion: 3.18 +Contact: linux-usb@vger.kernel.org +Description: + + The application-specific information element (ASIE) + included in this device's beacon, in space separated + hex octets. + + Reading returns the current ASIE. Writing replaces + the current ASIE with the one written. + What: /sys/class/uwb_rc/uwbN/scan Date: July 2008 KernelVersion: 2.6.27 -- cgit v1.2.3-59-g8ed1b