vserver 1.9.5.x5
[linux-2.6.git] / sound / usb / usbmidi.c
index a2f1b56..496e520 100644 (file)
 #include <sound/rawmidi.h>
 #include "usbaudio.h"
 
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_DESCRIPTION("USB Audio/MIDI helper module");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
 struct usb_ms_header_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
        __u8  bDescriptorSubtype;
        __u8  bcdMSC[2];
-       __u16 wTotalLength;
+       __le16 wTotalLength;
 } __attribute__ ((packed));
 
 struct usb_ms_endpoint_descriptor {
@@ -175,7 +180,7 @@ static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep,
  */
 static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-       snd_usb_midi_in_endpoint_t* ep = snd_magic_cast(snd_usb_midi_in_endpoint_t, urb->context, return);
+       snd_usb_midi_in_endpoint_t* ep = urb->context;
 
        if (urb->status == 0) {
                uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer;
@@ -229,7 +234,7 @@ static void snd_usbmidi_in_midiman_complete(struct urb* urb, struct pt_regs *reg
 
 static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-       snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, urb->context, return);
+       snd_usb_midi_out_endpoint_t* ep = urb->context;
 
        if (urb->status < 0) {
                if (snd_usbmidi_urb_error(urb->status) < 0)
@@ -393,7 +398,7 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
        int p;
        struct urb* urb = ep->urb;
        unsigned long flags;
-       
+
        spin_lock_irqsave(&ep->buffer_lock, flags);
        if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) {
                spin_unlock_irqrestore(&ep->buffer_lock, flags);
@@ -417,14 +422,14 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
 
 static void snd_usbmidi_out_tasklet(unsigned long data)
 {
-       snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, (void*)data, return);
-       
+       snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+
        snd_usbmidi_do_output(ep);
 }
 
 static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
 {
-       snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, substream->rmidi->private_data, return -ENXIO);
+       snd_usb_midi_t* umidi = substream->rmidi->private_data;
        usbmidi_out_port_t* port = NULL;
        int i, j;
 
@@ -499,11 +504,10 @@ static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
 static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
 {
        if (ep->urb) {
-               if (ep->urb->transfer_buffer)
-                       kfree(ep->urb->transfer_buffer);
+               kfree(ep->urb->transfer_buffer);
                usb_free_urb(ep->urb);
        }
-       snd_magic_kfree(ep);
+       kfree(ep);
 }
 
 /*
@@ -516,7 +520,7 @@ static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* u
        struct usb_host_interface *hostif;
        struct usb_interface_descriptor* intfd;
 
-       if (umidi->chip->dev->descriptor.idVendor != 0x0582)
+       if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) != 0x0582)
                return NULL;
        intf = umidi->iface;
        if (!intf || intf->num_altsetting != 2)
@@ -571,7 +575,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
        int length;
 
        rep->in = NULL;
-       ep = snd_magic_kcalloc(snd_usb_midi_in_endpoint_t, 0, GFP_KERNEL);
+       ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
        if (!ep)
                return -ENOMEM;
        ep->umidi = umidi;
@@ -627,11 +631,10 @@ static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
        if (ep->tasklet.func)
                tasklet_kill(&ep->tasklet);
        if (ep->urb) {
-               if (ep->urb->transfer_buffer)
-                       kfree(ep->urb->transfer_buffer);
+               kfree(ep->urb->transfer_buffer);
                usb_free_urb(ep->urb);
        }
-       snd_magic_kfree(ep);
+       kfree(ep);
 }
 
 /*
@@ -647,7 +650,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
        void* buffer;
 
        rep->out = NULL;
-       ep = snd_magic_kcalloc(snd_usb_midi_out_endpoint_t, 0, GFP_KERNEL);
+       ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
        if (!ep)
                return -ENOMEM;
        ep->umidi = umidi;
@@ -695,7 +698,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
                if (ep->in)
                        snd_usbmidi_in_endpoint_delete(ep->in);
        }
-       snd_magic_kfree(umidi);
+       kfree(umidi);
 }
 
 /*
@@ -710,15 +713,15 @@ void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
                snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
                if (ep->out && ep->out->urb)
-                       usb_unlink_urb(ep->out->urb);
+                       usb_kill_urb(ep->out->urb);
                if (ep->in && ep->in->urb)
-                       usb_unlink_urb(ep->in->urb);
+                       usb_kill_urb(ep->in->urb);
        }
 }
 
 static void snd_usbmidi_rawmidi_free(snd_rawmidi_t* rmidi)
 {
-       snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, rmidi->private_data, return);
+       snd_usb_midi_t* umidi = rmidi->private_data;
        snd_usbmidi_free(umidi);
 }
 
@@ -834,8 +837,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
 
        /* TODO: read port name from jack descriptor */
        name_format = "%s MIDI %d";
-       vendor = umidi->chip->dev->descriptor.idVendor;
-       product = umidi->chip->dev->descriptor.idProduct;
+       vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
+       product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
        for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
                if (snd_usbmidi_port_names[i].vendor == vendor &&
                    snd_usbmidi_port_names[i].product == product &&
@@ -964,7 +967,7 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
  * If the endpoints aren't specified, use the first bulk endpoints in the
  * first alternate setting of the interface.
  */
-static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
                                       snd_usb_midi_endpoint_info_t* endpoint)
 {
        struct usb_interface* intf;
@@ -998,7 +1001,7 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
 /*
  * Detects the endpoints and ports of Yamaha devices.
  */
-static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
                                     snd_usb_midi_endpoint_info_t* endpoint)
 {
        struct usb_interface* intf;
@@ -1144,6 +1147,44 @@ static int snd_usbmidi_create_rawmidi(snd_usb_midi_t* umidi,
        return 0;
 }
 
+/*
+ * Temporarily stop input.
+ */
+void snd_usbmidi_input_stop(struct list_head* p)
+{
+       snd_usb_midi_t* umidi;
+       int i;
+
+       umidi = list_entry(p, snd_usb_midi_t, list);
+       for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+               snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+               if (ep->in)
+                       usb_kill_urb(ep->in->urb);
+       }
+}
+
+static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
+{
+       if (ep) {
+               struct urb* urb = ep->urb;
+               urb->dev = ep->umidi->chip->dev;
+               snd_usbmidi_submit_urb(urb, GFP_KERNEL);
+       }
+}
+
+/*
+ * Resume input after a call to snd_usbmidi_input_stop().
+ */
+void snd_usbmidi_input_start(struct list_head* p)
+{
+       snd_usb_midi_t* umidi;
+       int i;
+
+       umidi = list_entry(p, snd_usb_midi_t, list);
+       for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
+               snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+}
+
 /*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
@@ -1156,7 +1197,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
        int out_ports, in_ports;
        int i, err;
 
-       umidi = snd_magic_kcalloc(snd_usb_midi_t, 0, GFP_KERNEL);
+       umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
        if (!umidi)
                return -ENOMEM;
        umidi->chip = chip;
@@ -1189,7 +1230,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
                }
        }
        if (err < 0) {
-               snd_magic_kfree(umidi);
+               kfree(umidi);
                return err;
        }
 
@@ -1202,7 +1243,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
        }
        err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
        if (err < 0) {
-               snd_magic_kfree(umidi);
+               kfree(umidi);
                return err;
        }
 
@@ -1219,8 +1260,11 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
        list_add(&umidi->list, &umidi->chip->midi_list);
 
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-               if (umidi->endpoints[i].in)
-                       snd_usbmidi_submit_urb(umidi->endpoints[i].in->urb,
-                                              GFP_KERNEL);
+               snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
        return 0;
 }
+
+EXPORT_SYMBOL(snd_usb_create_midi_interface);
+EXPORT_SYMBOL(snd_usbmidi_input_stop);
+EXPORT_SYMBOL(snd_usbmidi_input_start);
+EXPORT_SYMBOL(snd_usbmidi_disconnect);