ANDROID: usb: gadget: create F_midi device
authorBadhri Jagan Sridharan <Badhri@google.com>
Thu, 3 Sep 2015 05:49:10 +0000 (22:49 -0700)
committerJohn Stultz <john.stultz@linaro.org>
Tue, 16 Feb 2016 21:52:14 +0000 (13:52 -0800)
Android frameworks relies on the alsa
config reported by the f_midi device.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Change-Id: I0695e00b166fd953f50acea93802245b0d5a5240

drivers/usb/gadget/function/f_midi.c

index 898a570319f17c3128b7a44878ebc09ea7242961..8a0e7f988d25045bbb1eb16e3156b328bacf0d1a 100644 (file)
@@ -1040,6 +1040,65 @@ static void f_midi_free_inst(struct usb_function_instance *f)
        kfree(opts);
 }
 
+#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->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;
@@ -1057,6 +1116,11 @@ static struct usb_function_instance *f_midi_alloc_inst(void)
        opts->in_ports = 1;
        opts->out_ports = 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);
 
@@ -1158,6 +1222,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;
 
 setup_fail: