Skip to content

Commit fd61a2d

Browse files
Meng Dongyangrkhuangtao
authored andcommitted
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>
1 parent daf1165 commit fd61a2d

1 file changed

Lines changed: 109 additions & 0 deletions

File tree

drivers/usb/gadget/function/f_audio_source.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,10 @@ struct audio_source_config {
244244
int device;
245245
};
246246

247+
static struct class *audio_source_class;
248+
247249
struct audio_dev {
250+
struct device *dev;
248251
struct usb_function func;
249252
struct snd_card *card;
250253
struct snd_pcm *pcm;
@@ -253,13 +256,17 @@ struct audio_dev {
253256
struct list_head idle_reqs;
254257
struct usb_ep *in_ep;
255258

259+
struct work_struct work;
260+
256261
spinlock_t lock;
257262

258263
/* beginning, end and current position in our buffer */
259264
void *buffer_start;
260265
void *buffer_end;
261266
void *buffer_pos;
262267

268+
unsigned int alt;
269+
263270
/* byte size of a "period" */
264271
unsigned int period;
265272
/* 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)
278285
return container_of(f, struct audio_dev, func);
279286
}
280287

288+
static void audio_source_work(struct work_struct *data)
289+
{
290+
struct audio_dev *audio = container_of(data, struct audio_dev, work);
291+
char *set_interface[3] = { "USB_STATE=SET_INTERFACE", NULL, NULL};
292+
char **uevent_envp = NULL;
293+
294+
if (audio->alt)
295+
set_interface[1] = "1";
296+
else
297+
set_interface[1] = "0";
298+
uevent_envp = set_interface;
299+
300+
if (uevent_envp) {
301+
kobject_uevent_env(&audio->dev->kobj, KOBJ_CHANGE,
302+
uevent_envp);
303+
pr_info("%s: sent uevent %s\n", __func__,
304+
uevent_envp[0]);
305+
} else {
306+
pr_info("%s: did not send uevent set interface\n",
307+
__func__);
308+
}
309+
}
310+
311+
static ssize_t
312+
alt_show(struct device *dev, struct device_attribute *attr,
313+
char *buf)
314+
{
315+
struct audio_dev *audio = dev_get_drvdata(dev);
316+
317+
return sprintf(buf, "%d\n", audio->alt);
318+
}
319+
320+
static ssize_t
321+
alt_store(struct device *dev, struct device_attribute *attr,
322+
const char *buf, size_t size)
323+
{
324+
unsigned int value;
325+
struct audio_dev *audio = dev_get_drvdata(dev);
326+
327+
if (sscanf(buf, "%d\n", &value) != 1)
328+
return -1;
329+
330+
if (audio->alt != value) {
331+
audio->alt = value;
332+
schedule_work(&audio->work);
333+
}
334+
return size;
335+
}
336+
static DEVICE_ATTR_RW(alt);
337+
338+
static struct device_attribute *audio_source_attributes[] = {
339+
&dev_attr_alt,
340+
NULL
341+
};
342+
343+
static int audio_source_create_device(struct audio_dev *audio)
344+
{
345+
struct device_attribute **attrs = audio_source_attributes;
346+
struct device_attribute *attr;
347+
int err;
348+
349+
audio->dev = device_create(audio_source_class, NULL,
350+
MKDEV(0, 0), NULL, "audio_source0");
351+
if (IS_ERR(audio->dev))
352+
return PTR_ERR(audio->dev);
353+
354+
dev_set_drvdata(audio->dev, audio);
355+
356+
while ((attr = *attrs++)) {
357+
err = device_create_file(audio->dev, attr);
358+
if (err) {
359+
device_destroy(audio_source_class, audio->dev->devt);
360+
return err;
361+
}
362+
}
363+
return 0;
364+
}
365+
281366
/*-------------------------------------------------------------------------*/
282367

283368
struct audio_source_instance {
@@ -574,6 +659,11 @@ static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
574659
if (ret)
575660
return ret;
576661

662+
if (audio->alt != alt) {
663+
audio->alt = alt;
664+
schedule_work(&audio->work);
665+
}
666+
577667
usb_ep_enable(audio->in_ep);
578668
return 0;
579669
}
@@ -636,6 +726,13 @@ audio_bind(struct usb_configuration *c, struct usb_function *f)
636726
err = snd_card_setup(c, config);
637727
if (err)
638728
return err;
729+
730+
audio_source_class = class_create(THIS_MODULE, "audio_source");
731+
if (IS_ERR(audio_source_class))
732+
return PTR_ERR(audio_source_class);
733+
734+
INIT_WORK(&audio->work, audio_source_work);
735+
audio_source_create_device(audio);
639736
}
640737

641738
audio_build_desc(audio);
@@ -697,11 +794,16 @@ audio_unbind(struct usb_configuration *c, struct usb_function *f)
697794
while ((req = audio_req_get(audio)))
698795
audio_request_free(req, audio->in_ep);
699796

797+
cancel_work_sync(&audio->work);
798+
device_destroy(audio_source_class, audio->dev->devt);
799+
class_destroy(audio_source_class);
800+
700801
snd_card_free_when_closed(audio->card);
701802
audio->card = NULL;
702803
audio->pcm = NULL;
703804
audio->substream = NULL;
704805
audio->in_ep = NULL;
806+
audio->dev = NULL;
705807

706808
if (IS_ENABLED(CONFIG_USB_CONFIGFS)) {
707809
struct audio_source_instance *fi_audio =
@@ -879,6 +981,13 @@ int audio_source_bind_config(struct usb_configuration *c,
879981
if (err)
880982
goto add_fail;
881983

984+
audio_source_class = class_create(THIS_MODULE, "audio_source");
985+
if (IS_ERR(audio_source_class))
986+
return PTR_ERR(audio_source_class);
987+
988+
INIT_WORK(&audio->work, audio_source_work);
989+
audio_source_create_device(audio);
990+
882991
return 0;
883992

884993
add_fail:

0 commit comments

Comments
 (0)