rk: restore file mode
[firefly-linux-kernel-4.4.55.git] / drivers / usb / gadget / android.c
index 04cbeb134814ae925beead5f9387bb8350dd4b38..f1264747677ece818c56d4319a68043b4089d1a8 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "f_fs.c"
 #include "f_audio_source.c"
+#include "f_midi.c"
 #include "f_mass_storage.c"
 #include "f_mtp.c"
 #include "f_accessory.c"
@@ -48,8 +49,14 @@ MODULE_VERSION("1.0");
 static const char longname[] = "Gadget Android";
 
 /* Default vendor and product IDs, overridden by userspace */
-#define VENDOR_ID              0x18D1
-#define PRODUCT_ID             0x0001
+#define VENDOR_ID              0x2207
+#define PRODUCT_ID             0x2910
+
+/* f_midi configuration */
+#define MIDI_INPUT_PORTS    1
+#define MIDI_OUTPUT_PORTS   1
+#define MIDI_BUFFER_SIZE    256
+#define MIDI_QUEUE_LENGTH   32
 
 struct android_usb_function {
        char *name;
@@ -90,6 +97,9 @@ struct android_dev {
        struct usb_composite_dev *cdev;
        struct device *dev;
 
+       void (*setup_complete)(struct usb_ep *ep,
+                               struct usb_request *req);
+
        bool enabled;
        int disable_depth;
        struct mutex mutex;
@@ -347,6 +357,9 @@ static void functionfs_closed_callback(struct ffs_data *ffs)
        config->opened = false;
        config->data = NULL;
 
+       if (!WARN_ON(!ffs->gadget)) {
+               dev->cdev->next_string_id -= ffs->strings_count;
+       }
        functionfs_unbind(ffs);
 
        mutex_unlock(&dev->mutex);
@@ -756,15 +769,21 @@ static int mass_storage_function_init(struct android_usb_function *f,
 {
        struct mass_storage_function_config *config;
        struct fsg_common *common;
-       int err;
+       int err, i;
+       const char *name[2];
 
        config = kzalloc(sizeof(struct mass_storage_function_config),
                                                                GFP_KERNEL);
        if (!config)
                return -ENOMEM;
 
-       config->fsg.nluns = 1;
-       config->fsg.luns[0].removable = 1;
+       config->fsg.nluns = 2;
+       name[0] = "lun";
+       name[1] = "lun1";
+       for (i = 0; i < config->fsg.nluns; i++) {
+               config->fsg.luns[i].removable = 1;
+               config->fsg.luns[i].nofua = 1;
+       }
 
        common = fsg_common_init(NULL, cdev, &config->fsg);
        if (IS_ERR(common)) {
@@ -772,17 +791,23 @@ static int mass_storage_function_init(struct android_usb_function *f,
                return PTR_ERR(common);
        }
 
-       err = sysfs_create_link(&f->dev->kobj,
-                               &common->luns[0].dev.kobj,
-                               "lun");
-       if (err) {
-               kfree(config);
-               return err;
+       for (i = 0; i < config->fsg.nluns; i++) {
+               err = sysfs_create_link(&f->dev->kobj,
+                                       &common->luns[i].dev.kobj,
+                                       name[i]);
+               if (err)
+                       goto error;
        }
 
        config->common = common;
        f->config = config;
        return 0;
+error:
+       for (; i > 0 ; i--)
+               sysfs_remove_link(&f->dev->kobj, name[i-1]);
+       fsg_common_release(&common->ref);
+       kfree(config);
+       return err;
 }
 
 static void mass_storage_function_cleanup(struct android_usb_function *f)
@@ -930,6 +955,60 @@ static struct android_usb_function audio_source_function = {
        .attributes     = audio_source_function_attributes,
 };
 
+static int midi_function_init(struct android_usb_function *f,
+                                       struct usb_composite_dev *cdev)
+{
+       struct midi_alsa_config *config;
+
+       config = kzalloc(sizeof(struct midi_alsa_config), GFP_KERNEL);
+       f->config = config;
+       if (!config)
+               return -ENOMEM;
+       config->card = -1;
+       config->device = -1;
+       return 0;
+}
+
+static void midi_function_cleanup(struct android_usb_function *f)
+{
+       kfree(f->config);
+}
+
+static int midi_function_bind_config(struct android_usb_function *f,
+                                               struct usb_configuration *c)
+{
+       struct midi_alsa_config *config = f->config;
+
+       return f_midi_bind_config(c, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                       MIDI_INPUT_PORTS, MIDI_OUTPUT_PORTS, MIDI_BUFFER_SIZE,
+                       MIDI_QUEUE_LENGTH, config);
+}
+
+static ssize_t midi_alsa_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct android_usb_function *f = dev_get_drvdata(dev);
+       struct midi_alsa_config *config = f->config;
+
+       /* print ALSA card and device numbers */
+       return sprintf(buf, "%d %d\n", config->card, config->device);
+}
+
+static DEVICE_ATTR(alsa, S_IRUGO, midi_alsa_show, NULL);
+
+static struct device_attribute *midi_function_attributes[] = {
+       &dev_attr_alsa,
+       NULL
+};
+
+static struct android_usb_function midi_function = {
+       .name           = "midi",
+       .init           = midi_function_init,
+       .cleanup        = midi_function_cleanup,
+       .bind_config    = midi_function_bind_config,
+       .attributes     = midi_function_attributes,
+};
+
 static struct android_usb_function *supported_functions[] = {
        &ffs_function,
        &acm_function,
@@ -939,10 +1018,10 @@ static struct android_usb_function *supported_functions[] = {
        &mass_storage_function,
        &accessory_function,
        &audio_source_function,
+       &midi_function,
        NULL
 };
 
-
 static int android_init_functions(struct android_usb_function **functions,
                                  struct usb_composite_dev *cdev)
 {
@@ -1312,6 +1391,9 @@ static int android_bind(struct usb_composite_dev *cdev)
        struct usb_gadget       *gadget = cdev->gadget;
        int                     id, ret;
 
+       /* Save the default handler */
+       dev->setup_complete = cdev->req->complete;
+
        /*
         * Start disconnected. Userspace will connect the gadget once
         * it is done configuring the functions.
@@ -1347,6 +1429,7 @@ static int android_bind(struct usb_composite_dev *cdev)
                return id;
        strings_dev[STRING_SERIAL_IDX].id = id;
        device_desc.iSerialNumber = id;
+       device_desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());
 
        usb_gadget_set_selfpowered(gadget);
        dev->cdev = cdev;
@@ -1378,6 +1461,7 @@ android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
 
        req->zero = 0;
        req->length = 0;
+       req->complete = dev->setup_complete;
        gadget->ep0->driver_data = cdev;
 
        list_for_each_entry(f, &dev->enabled_functions, enabled_list) {