| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Badhri Jagan Sridharan <Badhri@google.com> |
| Date: Wed, 2 Sep 2015 22:49:10 -0700 |
| Subject: NOUPSTREAM: ANDROID: usb: gadget: f_midi: create F_midi device |
| |
| Android frameworks relies on the alsa |
| config reported by the f_midi device. |
| |
| [CPNOTE: 19/07/21] Lee: Should be re-written to use upstream APIs - pinged Badhri |
| |
| Bug: 111003288 |
| Bug: 120441124 |
| Change-Id: I0695e00b166fd953f50acea93802245b0d5a5240 |
| [badhri: The framework should be moved away from this] |
| Signed-off-by: Badhri Jagan Sridharan <badhri@google.com> |
| --- |
| drivers/usb/gadget/function/f_midi.c | 66 ++++++++++++++++++++++++++++ |
| 1 file changed, 66 insertions(+) |
| |
| diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c |
| --- a/drivers/usb/gadget/function/f_midi.c |
| +++ b/drivers/usb/gadget/function/f_midi.c |
| @@ -1224,6 +1224,65 @@ static void f_midi_free_inst(struct usb_function_instance *f) |
| } |
| } |
| |
| +#ifdef CONFIG_USB_CONFIGFS_UEVENT |
| +extern struct device *create_function_device(char *name); |
| +static ssize_t alsa_show(struct device *dev, |
| + struct device_attribute *attr, char *buf) |
| +{ |
| + struct usb_function_instance *fi_midi = dev_get_drvdata(dev); |
| + struct f_midi *midi; |
| + |
| + if (!fi_midi->f) |
| + dev_warn(dev, "f_midi: function not set\n"); |
| + |
| + if (fi_midi && fi_midi->f) { |
| + midi = func_to_midi(fi_midi->f); |
| + if (midi->rmidi && midi->card && midi->rmidi->card) |
| + return sprintf(buf, "%d %d\n", |
| + midi->rmidi->card->number, midi->rmidi->device); |
| + } |
| + |
| + /* print PCM card and device numbers */ |
| + return sprintf(buf, "%d %d\n", -1, -1); |
| +} |
| + |
| +static DEVICE_ATTR(alsa, S_IRUGO, alsa_show, NULL); |
| + |
| +static struct device_attribute *alsa_function_attributes[] = { |
| + &dev_attr_alsa, |
| + NULL |
| +}; |
| + |
| +static int create_alsa_device(struct usb_function_instance *fi) |
| +{ |
| + struct device *dev; |
| + struct device_attribute **attrs; |
| + struct device_attribute *attr; |
| + int err = 0; |
| + |
| + dev = create_function_device("f_midi"); |
| + if (IS_ERR(dev)) |
| + return PTR_ERR(dev); |
| + |
| + attrs = alsa_function_attributes; |
| + if (attrs) { |
| + while ((attr = *attrs++) && !err) |
| + err = device_create_file(dev, attr); |
| + if (err) { |
| + device_destroy(dev->class, dev->devt); |
| + return -EINVAL; |
| + } |
| + } |
| + dev_set_drvdata(dev, fi); |
| + return 0; |
| +} |
| +#else |
| +static int create_alsa_device(struct usb_function_instance *fi) |
| +{ |
| + return 0; |
| +} |
| +#endif |
| + |
| static struct usb_function_instance *f_midi_alloc_inst(void) |
| { |
| struct f_midi_opts *opts; |
| @@ -1242,6 +1301,11 @@ static struct usb_function_instance *f_midi_alloc_inst(void) |
| opts->out_ports = 1; |
| opts->refcnt = 1; |
| |
| + if (create_alsa_device(&opts->func_inst)) { |
| + kfree(opts); |
| + return ERR_PTR(-ENODEV); |
| + } |
| + |
| config_group_init_type_name(&opts->func_inst.group, "", |
| &midi_func_type); |
| |
| @@ -1262,6 +1326,7 @@ static void f_midi_free(struct usb_function *f) |
| kfifo_free(&midi->in_req_fifo); |
| kfree(midi); |
| free = true; |
| + opts->func_inst.f = NULL; |
| } |
| mutex_unlock(&opts->lock); |
| |
| @@ -1349,6 +1414,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) |
| midi->func.disable = f_midi_disable; |
| midi->func.free_func = f_midi_free; |
| |
| + fi->f = &midi->func; |
| return &midi->func; |
| |
| midi_free: |