]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - sound/usb/midi.c
ALSA: usb-audio: add MIDI port names for some Roland devices
[linux-imx.git] / sound / usb / midi.c
index 34b9bb7fe87c8eabed83df8b7b77f510bedbc2b1..b901f468b67ada579739828b382e165713de324e 100644 (file)
@@ -126,7 +126,6 @@ struct snd_usb_midi {
                struct snd_usb_midi_in_endpoint *in;
        } endpoints[MIDI_MAX_ENDPOINTS];
        unsigned long input_triggered;
-       bool autopm_reference;
        unsigned int opened[2];
        unsigned char disconnected;
        unsigned char input_running;
@@ -1040,7 +1039,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
 {
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
        struct snd_kcontrol *ctl;
-       int err;
 
        down_read(&umidi->disc_rwsem);
        if (umidi->disconnected) {
@@ -1051,13 +1049,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
        mutex_lock(&umidi->mutex);
        if (open) {
                if (!umidi->opened[0] && !umidi->opened[1]) {
-                       err = usb_autopm_get_interface(umidi->iface);
-                       umidi->autopm_reference = err >= 0;
-                       if (err < 0 && err != -EACCES) {
-                               mutex_unlock(&umidi->mutex);
-                               up_read(&umidi->disc_rwsem);
-                               return -EIO;
-                       }
                        if (umidi->roland_load_ctl) {
                                ctl = umidi->roland_load_ctl;
                                ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -1080,8 +1071,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
                                snd_ctl_notify(umidi->card,
                                       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
                        }
-                       if (umidi->autopm_reference)
-                               usb_autopm_put_interface(umidi->iface);
                }
        }
        mutex_unlock(&umidi->mutex);
@@ -1455,6 +1444,7 @@ void snd_usbmidi_disconnect(struct list_head* p)
        }
        del_timer_sync(&umidi->error_timer);
 }
+EXPORT_SYMBOL(snd_usbmidi_disconnect);
 
 static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
 {
@@ -1465,10 +1455,9 @@ static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
 static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
                                                                int stream, int number)
 {
-       struct list_head* list;
+       struct snd_rawmidi_substream *substream;
 
-       list_for_each(list, &umidi->rmidi->streams[stream].substreams) {
-               struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list);
+       list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams, list) {
                if (substream->number == number)
                        return substream;
        }
@@ -1586,8 +1575,41 @@ static struct port_info {
        EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"),
        EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"),
        EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"),
+       /* BOSS GT-PRO */
+       CONTROL_PORT(0x0582, 0x0089, 0, "%s Control"),
        /* Edirol UM-3EX */
        CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"),
+       /* Roland VG-99 */
+       CONTROL_PORT(0x0582, 0x00b2, 0, "%s Control"),
+       EXTERNAL_PORT(0x0582, 0x00b2, 1, "%s MIDI"),
+       /* Cakewalk Sonar V-Studio 100 */
+       EXTERNAL_PORT(0x0582, 0x00eb, 0, "%s MIDI"),
+       CONTROL_PORT(0x0582, 0x00eb, 1, "%s Control"),
+       /* Roland VB-99 */
+       CONTROL_PORT(0x0582, 0x0102, 0, "%s Control"),
+       EXTERNAL_PORT(0x0582, 0x0102, 1, "%s MIDI"),
+       /* Roland A-PRO */
+       EXTERNAL_PORT(0x0582, 0x010f, 0, "%s MIDI"),
+       CONTROL_PORT(0x0582, 0x010f, 1, "%s 1"),
+       CONTROL_PORT(0x0582, 0x010f, 2, "%s 2"),
+       /* Roland SD-50 */
+       ROLAND_SYNTH_PORT(0x0582, 0x0114, 0, "%s Synth", 128),
+       EXTERNAL_PORT(0x0582, 0x0114, 1, "%s MIDI"),
+       CONTROL_PORT(0x0582, 0x0114, 2, "%s Control"),
+       /* Roland OCTA-CAPTURE */
+       EXTERNAL_PORT(0x0582, 0x0120, 0, "%s MIDI"),
+       CONTROL_PORT(0x0582, 0x0120, 1, "%s Control"),
+       EXTERNAL_PORT(0x0582, 0x0121, 0, "%s MIDI"),
+       CONTROL_PORT(0x0582, 0x0121, 1, "%s Control"),
+       /* Roland SPD-SX */
+       CONTROL_PORT(0x0582, 0x0145, 0, "%s Control"),
+       EXTERNAL_PORT(0x0582, 0x0145, 1, "%s MIDI"),
+       /* Roland A-Series */
+       CONTROL_PORT(0x0582, 0x0156, 0, "%s Keyboard"),
+       EXTERNAL_PORT(0x0582, 0x0156, 1, "%s MIDI"),
+       /* Roland INTEGRA-7 */
+       ROLAND_SYNTH_PORT(0x0582, 0x015b, 0, "%s Synth", 128),
+       CONTROL_PORT(0x0582, 0x015b, 1, "%s Control"),
        /* M-Audio MidiSport 8x8 */
        CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"),
        CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"),
@@ -1958,6 +1980,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
        return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
 }
 
+/*
+ * Detects the endpoints and ports of Roland devices.
+ */
+static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi,
+                                    struct snd_usb_midi_endpoint_info* endpoint)
+{
+       struct usb_interface* intf;
+       struct usb_host_interface *hostif;
+       u8* cs_desc;
+
+       intf = umidi->iface;
+       if (!intf)
+               return -ENOENT;
+       hostif = intf->altsetting;
+       /*
+        * Some devices have a descriptor <06 24 F1 02 <inputs> <outputs>>,
+        * some have standard class descriptors, or both kinds, or neither.
+        */
+       for (cs_desc = hostif->extra;
+            cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
+            cs_desc += cs_desc[0]) {
+               if (cs_desc[0] >= 6 &&
+                   cs_desc[1] == USB_DT_CS_INTERFACE &&
+                   cs_desc[2] == 0xf1 &&
+                   cs_desc[3] == 0x02) {
+                       endpoint->in_cables  = (1 << cs_desc[4]) - 1;
+                       endpoint->out_cables = (1 << cs_desc[5]) - 1;
+                       return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
+               } else if (cs_desc[0] >= 7 &&
+                          cs_desc[1] == USB_DT_CS_INTERFACE &&
+                          cs_desc[2] == UAC_HEADER) {
+                       return snd_usbmidi_get_ms_info(umidi, endpoint);
+               }
+       }
+
+       return -ENODEV;
+}
+
 /*
  * Creates the endpoints and their ports for Midiman devices.
  */
@@ -2091,6 +2151,7 @@ void snd_usbmidi_input_stop(struct list_head* p)
        }
        umidi->input_running = 0;
 }
+EXPORT_SYMBOL(snd_usbmidi_input_stop);
 
 static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
 {
@@ -2120,6 +2181,7 @@ void snd_usbmidi_input_start(struct list_head* p)
                snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
        umidi->input_running = 1;
 }
+EXPORT_SYMBOL(snd_usbmidi_input_start);
 
 /*
  * Creates and registers everything needed for a MIDI streaming interface.
@@ -2171,6 +2233,9 @@ int snd_usbmidi_create(struct snd_card *card,
        case QUIRK_MIDI_YAMAHA:
                err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
                break;
+       case QUIRK_MIDI_ROLAND:
+               err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
+               break;
        case QUIRK_MIDI_MIDIMAN:
                umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
                memcpy(&endpoints[0], quirk->data,
@@ -2256,11 +2321,9 @@ int snd_usbmidi_create(struct snd_card *card,
                return err;
        }
 
+       usb_autopm_get_interface_no_resume(umidi->iface);
+
        list_add_tail(&umidi->list, midi_list);
        return 0;
 }
-
 EXPORT_SYMBOL(snd_usbmidi_create);
-EXPORT_SYMBOL(snd_usbmidi_input_stop);
-EXPORT_SYMBOL(snd_usbmidi_input_start);
-EXPORT_SYMBOL(snd_usbmidi_disconnect);