*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/usb/midi.h>
#include "u_f.h"
+#include "u_midi.h"
MODULE_AUTHOR("Ben Williamson");
MODULE_LICENSE("GPL v2");
DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
/* B.3.1 Standard AC Interface Descriptor */
-static struct usb_interface_descriptor ac_interface_desc __initdata = {
+static struct usb_interface_descriptor ac_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
};
/* B.3.2 Class-Specific AC Interface Descriptor */
-static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = {
+static struct uac1_ac_header_descriptor_1 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,
};
/* B.4.1 Standard MS Interface Descriptor */
-static struct usb_interface_descriptor ms_interface_desc __initdata = {
+static struct usb_interface_descriptor ms_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
};
/* B.4.2 Class-Specific MS Interface Descriptor */
-static struct usb_ms_header_descriptor ms_header_desc __initdata = {
+static struct usb_ms_header_descriptor ms_header_desc = {
.bLength = USB_DT_MS_HEADER_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,
usb_ep_disable(midi->out_ep);
}
+#ifdef USBF_MIDI_INCLUDED
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = f->config->cdev;
usb_free_all_descriptors(f);
kfree(midi);
}
+#endif
static int f_midi_snd_free(struct snd_device *device)
{
/* MIDI function driver setup/binding */
-static int __init
-f_midi_bind(struct usb_configuration *c, struct usb_function *f)
+static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_descriptor_header **midi_function;
struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
struct f_midi *midi = func_to_midi(f);
int status, n, jack = 1, i = 0;
+#ifndef USBF_MIDI_INCLUDED
+ midi->gadget = cdev->gadget;
+ tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
+ status = f_midi_register_card(midi);
+ if (status < 0)
+ goto fail_register;
+
+#endif
/* maybe allocate device-global string ID */
if (midi_string_defs[0].id == 0) {
status = usb_string_id(c->cdev);
kfree(midi_function);
usb_free_descriptors(f->hs_descriptors);
fail:
+#ifndef USBF_MIDI_INCLUDED
+ f_midi_unregister_card(midi);
+fail_register:
+#endif
/* we might as well release our claims on endpoints */
if (midi->out_ep)
midi->out_ep->driver_data = NULL;
return status;
}
+#ifdef USBF_MIDI_INCLUDED
/**
* f_midi_bind_config - add USB MIDI function to a configuration
* @c: the configuration to supcard the USB audio function
return status;
}
+#else
+
+static void f_midi_free_inst(struct usb_function_instance *f)
+{
+ struct f_midi_opts *opts;
+
+ opts = container_of(f, struct f_midi_opts, func_inst);
+
+ kfree(opts);
+}
+
+static struct usb_function_instance *f_midi_alloc_inst(void)
+{
+ struct f_midi_opts *opts;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+ opts->func_inst.free_func_inst = f_midi_free_inst;
+
+ return &opts->func_inst;
+}
+
+static void f_midi_free(struct usb_function *f)
+{
+ struct f_midi *midi;
+ struct f_midi_opts *opts;
+ int i;
+
+ midi = func_to_midi(f);
+ opts = container_of(f->fi, struct f_midi_opts, func_inst);
+ kfree(midi->id);
+ for (i = opts->in_ports - 1; i >= 0; --i)
+ kfree(midi->in_port[i]);
+ kfree(midi);
+}
+
+static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct f_midi *midi = func_to_midi(f);
+ struct snd_card *card;
+
+ DBG(cdev, "unbind\n");
+
+ /* just to be sure */
+ f_midi_disable(f);
+
+ card = midi->card;
+ midi->card = NULL;
+ if (card)
+ snd_card_free(card);
+
+ usb_free_all_descriptors(f);
+}
+
+struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
+{
+ struct f_midi *midi;
+ struct f_midi_opts *opts;
+ int status, i;
+
+ opts = container_of(fi, struct f_midi_opts, func_inst);
+ /* sanity check */
+ if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS)
+ return ERR_PTR(-EINVAL);
+
+ /* allocate and initialize one new instance */
+ midi = kzalloc(sizeof(*midi), GFP_KERNEL);
+ if (!midi)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < opts->in_ports; i++) {
+ struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL);
+
+ if (!port) {
+ status = -ENOMEM;
+ goto setup_fail;
+ }
+
+ port->midi = midi;
+ port->active = 0;
+ port->cable = i;
+ midi->in_port[i] = port;
+ }
+
+ /* set up ALSA midi devices */
+ midi->id = kstrdup(opts->id, GFP_KERNEL);
+ if (opts->id && !midi->id) {
+ status = -ENOMEM;
+ goto kstrdup_fail;
+ }
+ midi->in_ports = opts->in_ports;
+ midi->out_ports = opts->out_ports;
+ midi->index = opts->index;
+ midi->buflen = opts->buflen;
+ midi->qlen = opts->qlen;
+
+ midi->func.name = "gmidi function";
+ midi->func.strings = midi_strings;
+ midi->func.bind = f_midi_bind;
+ midi->func.unbind = f_midi_unbind;
+ midi->func.set_alt = f_midi_set_alt;
+ midi->func.disable = f_midi_disable;
+ midi->func.free_func = f_midi_free;
+
+ return &midi->func;
+
+kstrdup_fail:
+ f_midi_unregister_card(midi);
+setup_fail:
+ for (--i; i >= 0; i--)
+ kfree(midi->in_port[i]);
+ kfree(midi);
+ return ERR_PTR(status);
+}
+
+DECLARE_USB_FUNCTION_INIT(midi, f_midi_alloc_inst, f_midi_alloc);
+#endif