#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"
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;
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);
{
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)) {
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)
.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,
&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)
{
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;