usb: gadget: uac: add uevent of setting interface

Add uevent of setting interface to notify the application.
In some cases that the application want to get the change event
and state of alt immediately when to select the next operation,
but current code doesn't have the interface for it. So this patch
sent a uevent when setting interface and report the state of alt
throw attribute of uevent.

Change-Id: I47084f99bc046dede86d6b5777677f3799056c03
Signed-off-by: Meng Dongyang <daniel.meng@rock-chips.com>
This commit is contained in:
Meng Dongyang
2018-05-16 18:46:31 +08:00
committed by Tao Huang
parent daf1165257
commit fd61a2db4c

View File

@@ -244,7 +244,10 @@ struct audio_source_config {
int device;
};
static struct class *audio_source_class;
struct audio_dev {
struct device *dev;
struct usb_function func;
struct snd_card *card;
struct snd_pcm *pcm;
@@ -253,6 +256,8 @@ struct audio_dev {
struct list_head idle_reqs;
struct usb_ep *in_ep;
struct work_struct work;
spinlock_t lock;
/* beginning, end and current position in our buffer */
@@ -260,6 +265,8 @@ struct audio_dev {
void *buffer_end;
void *buffer_pos;
unsigned int alt;
/* byte size of a "period" */
unsigned int period;
/* bytes sent since last call to snd_pcm_period_elapsed */
@@ -278,6 +285,84 @@ static inline struct audio_dev *func_to_audio(struct usb_function *f)
return container_of(f, struct audio_dev, func);
}
static void audio_source_work(struct work_struct *data)
{
struct audio_dev *audio = container_of(data, struct audio_dev, work);
char *set_interface[3] = { "USB_STATE=SET_INTERFACE", NULL, NULL};
char **uevent_envp = NULL;
if (audio->alt)
set_interface[1] = "1";
else
set_interface[1] = "0";
uevent_envp = set_interface;
if (uevent_envp) {
kobject_uevent_env(&audio->dev->kobj, KOBJ_CHANGE,
uevent_envp);
pr_info("%s: sent uevent %s\n", __func__,
uevent_envp[0]);
} else {
pr_info("%s: did not send uevent set interface\n",
__func__);
}
}
static ssize_t
alt_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct audio_dev *audio = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", audio->alt);
}
static ssize_t
alt_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int value;
struct audio_dev *audio = dev_get_drvdata(dev);
if (sscanf(buf, "%d\n", &value) != 1)
return -1;
if (audio->alt != value) {
audio->alt = value;
schedule_work(&audio->work);
}
return size;
}
static DEVICE_ATTR_RW(alt);
static struct device_attribute *audio_source_attributes[] = {
&dev_attr_alt,
NULL
};
static int audio_source_create_device(struct audio_dev *audio)
{
struct device_attribute **attrs = audio_source_attributes;
struct device_attribute *attr;
int err;
audio->dev = device_create(audio_source_class, NULL,
MKDEV(0, 0), NULL, "audio_source0");
if (IS_ERR(audio->dev))
return PTR_ERR(audio->dev);
dev_set_drvdata(audio->dev, audio);
while ((attr = *attrs++)) {
err = device_create_file(audio->dev, attr);
if (err) {
device_destroy(audio_source_class, audio->dev->devt);
return err;
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
struct audio_source_instance {
@@ -574,6 +659,11 @@ static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (ret)
return ret;
if (audio->alt != alt) {
audio->alt = alt;
schedule_work(&audio->work);
}
usb_ep_enable(audio->in_ep);
return 0;
}
@@ -636,6 +726,13 @@ audio_bind(struct usb_configuration *c, struct usb_function *f)
err = snd_card_setup(c, config);
if (err)
return err;
audio_source_class = class_create(THIS_MODULE, "audio_source");
if (IS_ERR(audio_source_class))
return PTR_ERR(audio_source_class);
INIT_WORK(&audio->work, audio_source_work);
audio_source_create_device(audio);
}
audio_build_desc(audio);
@@ -697,11 +794,16 @@ audio_unbind(struct usb_configuration *c, struct usb_function *f)
while ((req = audio_req_get(audio)))
audio_request_free(req, audio->in_ep);
cancel_work_sync(&audio->work);
device_destroy(audio_source_class, audio->dev->devt);
class_destroy(audio_source_class);
snd_card_free_when_closed(audio->card);
audio->card = NULL;
audio->pcm = NULL;
audio->substream = NULL;
audio->in_ep = NULL;
audio->dev = NULL;
if (IS_ENABLED(CONFIG_USB_CONFIGFS)) {
struct audio_source_instance *fi_audio =
@@ -879,6 +981,13 @@ int audio_source_bind_config(struct usb_configuration *c,
if (err)
goto add_fail;
audio_source_class = class_create(THIS_MODULE, "audio_source");
if (IS_ERR(audio_source_class))
return PTR_ERR(audio_source_class);
INIT_WORK(&audio->work, audio_source_work);
audio_source_create_device(audio);
return 0;
add_fail: