[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230723190538.27750-1-quic_akakum@quicinc.com>
Date: Mon, 24 Jul 2023 00:35:38 +0530
From: Akash Kumar <quic_akakum@...cinc.com>
To: Thinh Nguyen <Thinh.Nguyen@...opsys.com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Jing Leng <jleng@...arella.com>,
Felipe Balbi <balbi@...nel.org>
CC: Pratham PratapĀ <quic_ppratap@...cinc.com>,
Jack Pham <quic_jackp@...cinc.com>,
<linux-usb@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
Akash Kumar <quic_akakum@...cinc.com>
Subject: [PATCH v2] usb: gadget: f_uac2: uevent changes for uac2
Adding uevent from usb audio gadget driver for uac2 playback/capture
events, which userspace reads and later reads sysfs entry to know if
playback or capture has stopped or started by host application.
/config/usb_gadget/g1/functions/uac2.0 # cat c_status
1 --> capture started
0 --> capture stopped
/config/usb_gadget/g1/functions/uac2.0 # cat p_status
1 --> playback started
0 --> playback stopped
Signed-off-by: Akash Kumar <quic_akakum@...cinc.com>
---
.../ABI/testing/configfs-usb-gadget-uac2 | 4 ++
drivers/usb/gadget/function/f_uac2.c | 47 +++++++++++++++++++
drivers/usb/gadget/function/u_uac2.h | 5 ++
3 files changed, 56 insertions(+)
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac2 b/Documentation/ABI/testing/configfs-usb-gadget-uac2
index 2bfdd4efa9bd..196c6921a163 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uac2
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uac2
@@ -10,3 +10,7 @@ Description:
p_chmask - playback channel mask
p_srate - playback sampling rate
p_ssize - playback sample size (bytes)
+ c_status - usb uac2 audio capture state
+ (0: capture stopped, 1: capture started)
+ p_status - usb uac2 audio playback state
+ (0: playback stopped, 1: playback started)
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index db2d4980cb35..f1f7631e9380 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -739,6 +739,8 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
struct usb_gadget *gadget = cdev->gadget;
struct device *dev = &gadget->dev;
int ret = 0;
+ struct f_uac2_opts *audio_opts =
+ container_of(fn->fi, struct f_uac2_opts, func_inst);
/* No i/f has more than 2 alt settings */
if (alt > 1) {
@@ -762,6 +764,8 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
ret = u_audio_start_capture(&uac2->g_audio);
else
u_audio_stop_capture(&uac2->g_audio);
+ audio_opts->c_status = alt;
+ schedule_work(&audio_opts->work);
} else if (intf == uac2->as_in_intf) {
uac2->as_in_alt = alt;
@@ -769,6 +773,8 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
ret = u_audio_start_playback(&uac2->g_audio);
else
u_audio_stop_playback(&uac2->g_audio);
+ audio_opts->p_status = alt;
+ schedule_work(&audio_opts->work);
} else {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return -EINVAL;
@@ -801,11 +807,16 @@ static void
afunc_disable(struct usb_function *fn)
{
struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct f_uac2_opts *audio_opts =
+ container_of(fn->fi, struct f_uac2_opts, func_inst);
uac2->as_in_alt = 0;
uac2->as_out_alt = 0;
+ audio_opts->p_status = 0;//alt;
+ audio_opts->c_status = 0; //alt;
u_audio_stop_capture(&uac2->g_audio);
u_audio_stop_playback(&uac2->g_audio);
+ schedule_work(&audio_opts->work);
}
static int
@@ -1036,6 +1047,25 @@ UAC2_ATTRIBUTE(c_srate);
UAC2_ATTRIBUTE(c_ssize);
UAC2_ATTRIBUTE(req_number);
+#define UAC2_ATTRIBUTE_RO(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 = scnprintf(page, PAGE_SIZE, "%u\n", opts->name); \
+ mutex_unlock(&opts->lock); \
+ \
+ return result; \
+} \
+CONFIGFS_ATTR_RO(f_uac2_opts_, name)
+
+UAC2_ATTRIBUTE_RO(c_status);
+UAC2_ATTRIBUTE_RO(p_status);
+
static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_p_chmask,
&f_uac2_opts_attr_p_srate,
@@ -1044,6 +1074,8 @@ static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_c_srate,
&f_uac2_opts_attr_c_ssize,
&f_uac2_opts_attr_req_number,
+ &f_uac2_opts_attr_c_status,
+ &f_uac2_opts_attr_p_status,
NULL,
};
@@ -1053,11 +1085,23 @@ static const struct config_item_type f_uac2_func_type = {
.ct_owner = THIS_MODULE,
};
+static void f_uac2_audio_status_change_work(struct work_struct *data)
+{
+ struct f_uac2_opts *audio_opts =
+ container_of(data, struct f_uac2_opts, work);
+ char *envp[2] = { "UAC2_STATE=Changed", NULL };
+
+ kobject_uevent_env(&audio_opts->device->kobj,
+ KOBJ_CHANGE, envp);
+}
+
static void afunc_free_inst(struct usb_function_instance *f)
{
struct f_uac2_opts *opts;
opts = container_of(f, struct f_uac2_opts, func_inst);
+ device_destroy(opts->device->class, opts->device->devt);
+ cancel_work_sync(&opts->work);
kfree(opts);
}
@@ -1082,6 +1126,9 @@ static struct usb_function_instance *afunc_alloc_inst(void)
opts->c_srate = UAC2_DEF_CSRATE;
opts->c_ssize = UAC2_DEF_CSSIZE;
opts->req_number = UAC2_DEF_REQ_NUM;
+ INIT_WORK(&opts->work, f_uac2_audio_status_change_work);
+ opts->device = create_function_device("f_uac2");
+
return &opts->func_inst;
}
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h
index b5035711172d..3ccf2eb002f1 100644
--- a/drivers/usb/gadget/function/u_uac2.h
+++ b/drivers/usb/gadget/function/u_uac2.h
@@ -36,6 +36,11 @@ struct f_uac2_opts {
struct mutex lock;
int refcnt;
+ int c_status;
+ int p_status;
+ struct device *device;
+ struct work_struct work;
};
+extern struct device *create_function_device(char *name);
#endif
--
2.17.1
Powered by blists - more mailing lists