Blame view

sound/usb/midi.c 68.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * usbmidi.c - ALSA USB MIDI driver
   *
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
4
   * Copyright (c) 2002-2009 Clemens Ladisch
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
   * All rights reserved.
   *
   * Based on the OSS usb-midi driver by NAGANO Daisuke,
   *          NetBSD's umidi driver by Takuya SHIOZAKI,
   *          the "USB Device Class Definition for MIDI Devices" by Roland
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. The name of the author may not be used to endorse or promote products
   *    derived from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed and/or modified under the
   * terms of the GNU General Public License as published by the Free Software
   * Foundation; either version 2 of the License, or (at your option) any later
   * version.
   *
   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
44
  #include <linux/kernel.h>
  #include <linux/types.h>
  #include <linux/bitops.h>
  #include <linux/interrupt.h>
  #include <linux/spinlock.h>
  #include <linux/string.h>
  #include <linux/init.h>
  #include <linux/slab.h>
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
45
  #include <linux/timer.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  #include <linux/usb.h>
a65dd997b   Clemens Ladisch   sound: usb-audio:...
47
  #include <linux/wait.h>
de48c7bc6   Daniel Mack   ALSA: usbaudio: c...
48
  #include <linux/usb/audio.h>
da155d5b4   Paul Gortmaker   sound: Add module...
49
  #include <linux/module.h>
de48c7bc6   Daniel Mack   ALSA: usbaudio: c...
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  #include <sound/core.h>
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
52
  #include <sound/control.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  #include <sound/rawmidi.h>
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
54
  #include <sound/asequencer.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  #include "usbaudio.h"
e5779998b   Daniel Mack   ALSA: usb-audio: ...
56
  #include "midi.h"
88a8516a2   Oliver Neukum   ALSA: usbaudio: i...
57
  #include "power.h"
e5779998b   Daniel Mack   ALSA: usb-audio: ...
58
  #include "helper.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
  
  /*
   * define this to log all USB packets
   */
  /* #define DUMP_PACKETS */
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
64
  /*
37ebb5491   Petr Mladek   usb: hub: rename ...
65
   * how long to wait after some USB errors, so that hub_wq can disconnect() us
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
66
67
68
   * without too many spurious errors
   */
  #define ERROR_DELAY_JIFFIES (HZ / 10)
ed4affa53   Clemens Ladisch   sound: usb-audio:...
69
  #define OUTPUT_URBS 7
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
70
  #define INPUT_URBS 7
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  
  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];
  	__le16 wTotalLength;
  } __attribute__ ((packed));
  
  struct usb_ms_endpoint_descriptor {
  	__u8  bLength;
  	__u8  bDescriptorType;
  	__u8  bDescriptorSubtype;
  	__u8  bNumEmbMIDIJack;
  	__u8  baAssocJackID[0];
  } __attribute__ ((packed));
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
92
93
94
  struct snd_usb_midi_in_endpoint;
  struct snd_usb_midi_out_endpoint;
  struct snd_usb_midi_endpoint;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  
  struct usb_protocol_ops {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
97
  	void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int);
ed4affa53   Clemens Ladisch   sound: usb-audio:...
98
  	void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  	void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t);
a509574e5   Adam Goode   ALSA: usb-audio: ...
100
101
  	void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint *);
  	void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
  };
  
  struct snd_usb_midi {
d82af9f9a   Clemens Ladisch   sound: usb: make ...
105
106
  	struct usb_device *dev;
  	struct snd_card *card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  	struct usb_interface *iface;
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
108
109
  	const struct snd_usb_audio_quirk *quirk;
  	struct snd_rawmidi *rmidi;
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
110
  	const struct usb_protocol_ops *usb_protocol_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  	struct list_head list;
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
112
  	struct timer_list error_timer;
c0792e00b   Takashi Iwai   [ALSA] race betwe...
113
  	spinlock_t disc_lock;
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
114
  	struct rw_semaphore disc_rwsem;
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
115
  	struct mutex mutex;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
116
117
  	u32 usb_id;
  	int next_midi_device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  
  	struct snd_usb_midi_endpoint {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
120
121
  		struct snd_usb_midi_out_endpoint *out;
  		struct snd_usb_midi_in_endpoint *in;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
  	} endpoints[MIDI_MAX_ENDPOINTS];
  	unsigned long input_triggered;
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
124
  	unsigned int opened[2];
c0792e00b   Takashi Iwai   [ALSA] race betwe...
125
  	unsigned char disconnected;
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
126
  	unsigned char input_running;
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
127
128
  
  	struct snd_kcontrol *roland_load_ctl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
  };
  
  struct snd_usb_midi_out_endpoint {
a509574e5   Adam Goode   ALSA: usb-audio: ...
132
  	struct snd_usb_midi *umidi;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
133
134
135
136
137
  	struct out_urb_context {
  		struct urb *urb;
  		struct snd_usb_midi_out_endpoint *ep;
  	} urbs[OUTPUT_URBS];
  	unsigned int active_urbs;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
138
  	unsigned int drain_urbs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
  	int max_transfer;		/* size of urb buffer */
  	struct tasklet_struct tasklet;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
141
  	unsigned int next_urb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
  	spinlock_t buffer_lock;
  
  	struct usbmidi_out_port {
a509574e5   Adam Goode   ALSA: usb-audio: ...
145
  		struct snd_usb_midi_out_endpoint *ep;
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
146
  		struct snd_rawmidi_substream *substream;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
155
156
157
158
159
  		int active;
  		uint8_t cable;		/* cable number << 4 */
  		uint8_t state;
  #define STATE_UNKNOWN	0
  #define STATE_1PARAM	1
  #define STATE_2PARAM_1	2
  #define STATE_2PARAM_2	3
  #define STATE_SYSEX_0	4
  #define STATE_SYSEX_1	5
  #define STATE_SYSEX_2	6
  		uint8_t data[2];
  	} ports[0x10];
  	int current_port;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
160
161
  
  	wait_queue_head_t drain_wait;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
  };
  
  struct snd_usb_midi_in_endpoint {
a509574e5   Adam Goode   ALSA: usb-audio: ...
165
166
  	struct snd_usb_midi *umidi;
  	struct urb *urbs[INPUT_URBS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  	struct usbmidi_in_port {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
168
  		struct snd_rawmidi_substream *substream;
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
169
  		u8 running_status_length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  	} ports[0x10];
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
171
  	u8 seen_f5;
a91e627e3   Clemens Ladisch   ALSA: usb-audio: ...
172
173
  	bool in_sysex;
  	u8 last_cin;
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
174
  	u8 error_resubmit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
  	int current_port;
  };
a509574e5   Adam Goode   ALSA: usb-audio: ...
177
  static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
183
184
185
  
  static const uint8_t snd_usbmidi_cin_length[] = {
  	0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
  };
  
  /*
   * Submits the URB, with error handling.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
186
  static int snd_usbmidi_submit_urb(struct urb *urb, gfp_t flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
  {
  	int err = usb_submit_urb(urb, flags);
  	if (err < 0 && err != -ENODEV)
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
190
191
  		dev_err(&urb->dev->dev, "usb_submit_urb: %d
  ", err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
197
  	return err;
  }
  
  /*
   * Error handling for URB completion functions.
   */
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
198
  static int snd_usbmidi_urb_error(const struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
200
  	switch (urb->status) {
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
201
202
203
204
205
206
207
  	/* manually unlinked, or device gone */
  	case -ENOENT:
  	case -ECONNRESET:
  	case -ESHUTDOWN:
  	case -ENODEV:
  		return -ENODEV;
  	/* errors that might occur during unplugging */
38e2bfc94   Pete Zaitcev   USB: Dealias -110...
208
209
210
  	case -EPROTO:
  	case -ETIME:
  	case -EILSEQ:
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
211
212
  		return -EIO;
  	default:
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
213
214
  		dev_err(&urb->dev->dev, "urb status %d
  ", urb->status);
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
215
216
  		return 0; /* continue */
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
221
  }
  
  /*
   * Receives a chunk of MIDI data.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
222
223
  static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint *ep,
  				   int portidx, uint8_t *data, int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
225
  	struct usbmidi_in_port *port = &ep->ports[portidx];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
  
  	if (!port->substream) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
228
229
  		dev_dbg(&ep->umidi->dev->dev, "unexpected port %d!
  ", portidx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
236
237
238
239
240
241
  		return;
  	}
  	if (!test_bit(port->substream->number, &ep->umidi->input_triggered))
  		return;
  	snd_rawmidi_receive(port->substream, data, length);
  }
  
  #ifdef DUMP_PACKETS
  static void dump_urb(const char *type, const u8 *data, int length)
  {
  	snd_printk(KERN_DEBUG "%s packet: [", type);
  	for (; length > 0; ++data, --length)
5659f2445   Takashi Iwai   ALSA: usb-audio: ...
242
243
244
  		printk(KERN_CONT " %02x", *data);
  	printk(KERN_CONT " ]
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
252
  }
  #else
  #define dump_urb(type, data, length) /* nothing */
  #endif
  
  /*
   * Processes the data read from the device.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
253
  static void snd_usbmidi_in_urb_complete(struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
255
  	struct snd_usb_midi_in_endpoint *ep = urb->context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
260
261
  
  	if (urb->status == 0) {
  		dump_urb("received", urb->transfer_buffer, urb->actual_length);
  		ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer,
  						   urb->actual_length);
  	} else {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
262
  		int err = snd_usbmidi_urb_error(urb);
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
263
264
265
266
267
268
  		if (err < 0) {
  			if (err != -ENODEV) {
  				ep->error_resubmit = 1;
  				mod_timer(&ep->umidi->error_timer,
  					  jiffies + ERROR_DELAY_JIFFIES);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  			return;
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
270
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  	}
d82af9f9a   Clemens Ladisch   sound: usb: make ...
272
  	urb->dev = ep->umidi->dev;
3cfc1eb18   Clemens Ladisch   [ALSA] usb-audio:...
273
  	snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
275
  static void snd_usbmidi_out_urb_complete(struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  {
ed4affa53   Clemens Ladisch   sound: usb-audio:...
277
  	struct out_urb_context *context = urb->context;
a509574e5   Adam Goode   ALSA: usb-audio: ...
278
  	struct snd_usb_midi_out_endpoint *ep = context->ep;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
279
  	unsigned int urb_index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
  
  	spin_lock(&ep->buffer_lock);
a65dd997b   Clemens Ladisch   sound: usb-audio:...
282
283
284
285
286
287
  	urb_index = context - ep->urbs;
  	ep->active_urbs &= ~(1 << urb_index);
  	if (unlikely(ep->drain_urbs)) {
  		ep->drain_urbs &= ~(1 << urb_index);
  		wake_up(&ep->drain_wait);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  	spin_unlock(&ep->buffer_lock);
  	if (urb->status < 0) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
290
  		int err = snd_usbmidi_urb_error(urb);
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
291
292
293
294
  		if (err < 0) {
  			if (err != -ENODEV)
  				mod_timer(&ep->umidi->error_timer,
  					  jiffies + ERROR_DELAY_JIFFIES);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  			return;
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
296
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
300
301
302
303
304
  	}
  	snd_usbmidi_do_output(ep);
  }
  
  /*
   * This is called when some data should be transferred to the device
   * (from one or more substreams).
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
305
  static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  {
ed4affa53   Clemens Ladisch   sound: usb-audio:...
307
  	unsigned int urb_index;
a509574e5   Adam Goode   ALSA: usb-audio: ...
308
  	struct urb *urb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
  	unsigned long flags;
  
  	spin_lock_irqsave(&ep->buffer_lock, flags);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
312
  	if (ep->umidi->disconnected) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
315
  		spin_unlock_irqrestore(&ep->buffer_lock, flags);
  		return;
  	}
a65dd997b   Clemens Ladisch   sound: usb-audio:...
316
  	urb_index = ep->next_urb;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
317
  	for (;;) {
a65dd997b   Clemens Ladisch   sound: usb-audio:...
318
319
320
321
322
  		if (!(ep->active_urbs & (1 << urb_index))) {
  			urb = ep->urbs[urb_index].urb;
  			urb->transfer_buffer_length = 0;
  			ep->umidi->usb_protocol_ops->output(ep, urb);
  			if (urb->transfer_buffer_length == 0)
ed4affa53   Clemens Ladisch   sound: usb-audio:...
323
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324

a65dd997b   Clemens Ladisch   sound: usb-audio:...
325
326
  			dump_urb("sending", urb->transfer_buffer,
  				 urb->transfer_buffer_length);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
327
  			urb->dev = ep->umidi->dev;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
328
329
330
331
332
333
334
  			if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0)
  				break;
  			ep->active_urbs |= 1 << urb_index;
  		}
  		if (++urb_index >= OUTPUT_URBS)
  			urb_index = 0;
  		if (urb_index == ep->next_urb)
ed4affa53   Clemens Ladisch   sound: usb-audio:...
335
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  	}
a65dd997b   Clemens Ladisch   sound: usb-audio:...
337
  	ep->next_urb = urb_index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
340
341
342
  	spin_unlock_irqrestore(&ep->buffer_lock, flags);
  }
  
  static void snd_usbmidi_out_tasklet(unsigned long data)
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
343
344
  	struct snd_usb_midi_out_endpoint *ep =
  		(struct snd_usb_midi_out_endpoint *) data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
  
  	snd_usbmidi_do_output(ep);
  }
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
348
349
350
  /* called after transfers had been interrupted due to some USB error */
  static void snd_usbmidi_error_timer(unsigned long data)
  {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
351
  	struct snd_usb_midi *umidi = (struct snd_usb_midi *)data;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
352
  	unsigned int i, j;
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
353

c0792e00b   Takashi Iwai   [ALSA] race betwe...
354
355
356
357
358
  	spin_lock(&umidi->disc_lock);
  	if (umidi->disconnected) {
  		spin_unlock(&umidi->disc_lock);
  		return;
  	}
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
359
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
360
  		struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in;
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
361
362
  		if (in && in->error_resubmit) {
  			in->error_resubmit = 0;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
363
  			for (j = 0; j < INPUT_URBS; ++j) {
66139a48c   Takashi Iwai   ALSA: usb-audio: ...
364
365
  				if (atomic_read(&in->urbs[j]->use_count))
  					continue;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
366
  				in->urbs[j]->dev = umidi->dev;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
367
368
  				snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC);
  			}
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
369
370
371
372
  		}
  		if (umidi->endpoints[i].out)
  			snd_usbmidi_do_output(umidi->endpoints[i].out);
  	}
c0792e00b   Takashi Iwai   [ALSA] race betwe...
373
  	spin_unlock(&umidi->disc_lock);
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
374
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  /* helper function to send static data that may not DMA-able */
a509574e5   Adam Goode   ALSA: usb-audio: ...
376
  static int send_bulk_static_data(struct snd_usb_midi_out_endpoint *ep,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
  				 const void *data, int len)
  {
ed4affa53   Clemens Ladisch   sound: usb-audio:...
379
  	int err = 0;
52978be63   Alexey Dobriyan   [PATCH] kmemdup: ...
380
  	void *buf = kmemdup(data, len, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
  	if (!buf)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  	dump_urb("sending", buf, len);
ed4affa53   Clemens Ladisch   sound: usb-audio:...
384
  	if (ep->urbs[0].urb)
d82af9f9a   Clemens Ladisch   sound: usb: make ...
385
  		err = usb_bulk_msg(ep->umidi->dev, ep->urbs[0].urb->pipe,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
386
  				   buf, len, NULL, 250);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
392
393
394
395
  	kfree(buf);
  	return err;
  }
  
  /*
   * Standard USB MIDI protocol: see the spec.
   * Midiman protocol: like the standard protocol, but the control byte is the
   * fourth byte in each packet, and uses length instead of CIN.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
396
397
  static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint *ep,
  				       uint8_t *buffer, int buffer_length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
403
404
  {
  	int i;
  
  	for (i = 0; i + 3 < buffer_length; i += 4)
  		if (buffer[i] != 0) {
  			int cable = buffer[i] >> 4;
  			int length = snd_usbmidi_cin_length[buffer[i] & 0x0f];
a509574e5   Adam Goode   ALSA: usb-audio: ...
405
406
  			snd_usbmidi_input_data(ep, cable, &buffer[i + 1],
  					       length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  		}
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
409
410
  static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint *ep,
  				      uint8_t *buffer, int buffer_length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
416
417
418
419
420
421
422
  {
  	int i;
  
  	for (i = 0; i + 3 < buffer_length; i += 4)
  		if (buffer[i + 3] != 0) {
  			int port = buffer[i + 3] >> 4;
  			int length = buffer[i + 3] & 3;
  			snd_usbmidi_input_data(ep, port, &buffer[i], length);
  		}
  }
  
  /*
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
423
424
425
426
   * Buggy M-Audio device: running status on input results in a packet that has
   * the data bytes but not the status byte and that is marked with CIN 4.
   */
  static void snd_usbmidi_maudio_broken_running_status_input(
a509574e5   Adam Goode   ALSA: usb-audio: ...
427
428
  					struct snd_usb_midi_in_endpoint *ep,
  					uint8_t *buffer, int buffer_length)
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
429
430
431
432
433
434
435
436
437
  {
  	int i;
  
  	for (i = 0; i + 3 < buffer_length; i += 4)
  		if (buffer[i] != 0) {
  			int cable = buffer[i] >> 4;
  			u8 cin = buffer[i] & 0x0f;
  			struct usbmidi_in_port *port = &ep->ports[cable];
  			int length;
21af7d8c0   Daniel Mack   ALSA: usb-midi: w...
438

d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  			length = snd_usbmidi_cin_length[cin];
  			if (cin == 0xf && buffer[i + 1] >= 0xf8)
  				; /* realtime msg: no running status change */
  			else if (cin >= 0x8 && cin <= 0xe)
  				/* channel msg */
  				port->running_status_length = length - 1;
  			else if (cin == 0x4 &&
  				 port->running_status_length != 0 &&
  				 buffer[i + 1] < 0x80)
  				/* CIN 4 that is not a SysEx */
  				length = port->running_status_length;
  			else
  				/*
  				 * All other msgs cannot begin running status.
  				 * (A channel msg sent as two or three CIN 0xF
  				 * packets could in theory, but this device
  				 * doesn't use this format.)
  				 */
  				port->running_status_length = 0;
a509574e5   Adam Goode   ALSA: usb-audio: ...
458
459
  			snd_usbmidi_input_data(ep, cable, &buffer[i + 1],
  					       length);
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
460
461
462
463
  		}
  }
  
  /*
a91e627e3   Clemens Ladisch   ALSA: usb-audio: ...
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
   * QinHeng CH345 is buggy: every second packet inside a SysEx has not CIN 4
   * but the previously seen CIN, but still with three data bytes.
   */
  static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep,
  				     uint8_t *buffer, int buffer_length)
  {
  	unsigned int i, cin, length;
  
  	for (i = 0; i + 3 < buffer_length; i += 4) {
  		if (buffer[i] == 0 && i > 0)
  			break;
  		cin = buffer[i] & 0x0f;
  		if (ep->in_sysex &&
  		    cin == ep->last_cin &&
  		    (buffer[i + 1 + (cin == 0x6)] & 0x80) == 0)
  			cin = 0x4;
  #if 0
  		if (buffer[i + 1] == 0x90) {
  			/*
  			 * Either a corrupted running status or a real note-on
  			 * message; impossible to detect reliably.
  			 */
  		}
  #endif
  		length = snd_usbmidi_cin_length[cin];
  		snd_usbmidi_input_data(ep, 0, &buffer[i + 1], length);
  		ep->in_sysex = cin == 0x4;
  		if (!ep->in_sysex)
  			ep->last_cin = cin;
  	}
  }
  
  /*
61870aed2   Clemens Ladisch   [ALSA] usb-audio:...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
   * CME protocol: like the standard protocol, but SysEx commands are sent as a
   * single USB packet preceded by a 0x0F byte.
   */
  static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep,
  				  uint8_t *buffer, int buffer_length)
  {
  	if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f)
  		snd_usbmidi_standard_input(ep, buffer, buffer_length);
  	else
  		snd_usbmidi_input_data(ep, buffer[0] >> 4,
  				       &buffer[1], buffer_length - 1);
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
   * Adds one USB MIDI packet to the output buffer.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
513
514
515
  static void snd_usbmidi_output_standard_packet(struct urb *urb, uint8_t p0,
  					       uint8_t p1, uint8_t p2,
  					       uint8_t p3)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
517
518
  	uint8_t *buf =
  		(uint8_t *)urb->transfer_buffer + urb->transfer_buffer_length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
521
522
523
524
525
526
527
528
  	buf[0] = p0;
  	buf[1] = p1;
  	buf[2] = p2;
  	buf[3] = p3;
  	urb->transfer_buffer_length += 4;
  }
  
  /*
   * Adds one Midiman packet to the output buffer.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
529
530
531
  static void snd_usbmidi_output_midiman_packet(struct urb *urb, uint8_t p0,
  					      uint8_t p1, uint8_t p2,
  					      uint8_t p3)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
533
534
  	uint8_t *buf =
  		(uint8_t *)urb->transfer_buffer + urb->transfer_buffer_length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
541
542
543
544
  	buf[0] = p1;
  	buf[1] = p2;
  	buf[2] = p3;
  	buf[3] = (p0 & 0xf0) | snd_usbmidi_cin_length[p0 & 0x0f];
  	urb->transfer_buffer_length += 4;
  }
  
  /*
   * Converts MIDI commands to USB MIDI packets.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
545
546
  static void snd_usbmidi_transmit_byte(struct usbmidi_out_port *port,
  				      uint8_t b, struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
  {
  	uint8_t p0 = port->cable;
  	void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) =
  		port->ep->umidi->usb_protocol_ops->output_packet;
  
  	if (b >= 0xf8) {
  		output_packet(urb, p0 | 0x0f, b, 0, 0);
  	} else if (b >= 0xf0) {
  		switch (b) {
  		case 0xf0:
  			port->data[0] = b;
  			port->state = STATE_SYSEX_1;
  			break;
  		case 0xf1:
  		case 0xf3:
  			port->data[0] = b;
  			port->state = STATE_1PARAM;
  			break;
  		case 0xf2:
  			port->data[0] = b;
  			port->state = STATE_2PARAM_1;
  			break;
  		case 0xf4:
  		case 0xf5:
  			port->state = STATE_UNKNOWN;
  			break;
  		case 0xf6:
  			output_packet(urb, p0 | 0x05, 0xf6, 0, 0);
  			port->state = STATE_UNKNOWN;
  			break;
  		case 0xf7:
  			switch (port->state) {
  			case STATE_SYSEX_0:
  				output_packet(urb, p0 | 0x05, 0xf7, 0, 0);
  				break;
  			case STATE_SYSEX_1:
a509574e5   Adam Goode   ALSA: usb-audio: ...
583
584
  				output_packet(urb, p0 | 0x06, port->data[0],
  					      0xf7, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
  				break;
  			case STATE_SYSEX_2:
a509574e5   Adam Goode   ALSA: usb-audio: ...
587
588
  				output_packet(urb, p0 | 0x07, port->data[0],
  					      port->data[1], 0xf7);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  				break;
  			}
  			port->state = STATE_UNKNOWN;
  			break;
  		}
  	} else if (b >= 0x80) {
  		port->data[0] = b;
  		if (b >= 0xc0 && b <= 0xdf)
  			port->state = STATE_1PARAM;
  		else
  			port->state = STATE_2PARAM_1;
  	} else { /* b < 0x80 */
  		switch (port->state) {
  		case STATE_1PARAM:
  			if (port->data[0] < 0xf0) {
  				p0 |= port->data[0] >> 4;
  			} else {
  				p0 |= 0x02;
  				port->state = STATE_UNKNOWN;
  			}
  			output_packet(urb, p0, port->data[0], b, 0);
  			break;
  		case STATE_2PARAM_1:
  			port->data[1] = b;
  			port->state = STATE_2PARAM_2;
  			break;
  		case STATE_2PARAM_2:
  			if (port->data[0] < 0xf0) {
  				p0 |= port->data[0] >> 4;
  				port->state = STATE_2PARAM_1;
  			} else {
  				p0 |= 0x03;
  				port->state = STATE_UNKNOWN;
  			}
  			output_packet(urb, p0, port->data[0], port->data[1], b);
  			break;
  		case STATE_SYSEX_0:
  			port->data[0] = b;
  			port->state = STATE_SYSEX_1;
  			break;
  		case STATE_SYSEX_1:
  			port->data[1] = b;
  			port->state = STATE_SYSEX_2;
  			break;
  		case STATE_SYSEX_2:
a509574e5   Adam Goode   ALSA: usb-audio: ...
634
635
  			output_packet(urb, p0 | 0x04, port->data[0],
  				      port->data[1], b);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
639
640
  			port->state = STATE_SYSEX_0;
  			break;
  		}
  	}
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
641
  static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
642
  					struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
646
647
  	int p;
  
  	/* FIXME: lower-numbered ports can starve higher-numbered ports */
  	for (p = 0; p < 0x10; ++p) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
648
  		struct usbmidi_out_port *port = &ep->ports[p];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
652
653
654
655
656
657
658
659
660
  		if (!port->active)
  			continue;
  		while (urb->transfer_buffer_length + 3 < ep->max_transfer) {
  			uint8_t b;
  			if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) {
  				port->active = 0;
  				break;
  			}
  			snd_usbmidi_transmit_byte(port, b, urb);
  		}
  	}
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
661
  static const struct usb_protocol_ops snd_usbmidi_standard_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
  	.input = snd_usbmidi_standard_input,
  	.output = snd_usbmidi_standard_output,
  	.output_packet = snd_usbmidi_output_standard_packet,
  };
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
666
  static const struct usb_protocol_ops snd_usbmidi_midiman_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
  	.input = snd_usbmidi_midiman_input,
21af7d8c0   Daniel Mack   ALSA: usb-midi: w...
668
  	.output = snd_usbmidi_standard_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
  	.output_packet = snd_usbmidi_output_midiman_packet,
  };
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
671
672
  static const
  struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
673
  	.input = snd_usbmidi_maudio_broken_running_status_input,
21af7d8c0   Daniel Mack   ALSA: usb-midi: w...
674
  	.output = snd_usbmidi_standard_output,
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
675
676
  	.output_packet = snd_usbmidi_output_standard_packet,
  };
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
677
  static const struct usb_protocol_ops snd_usbmidi_cme_ops = {
61870aed2   Clemens Ladisch   [ALSA] usb-audio:...
678
679
680
681
  	.input = snd_usbmidi_cme_input,
  	.output = snd_usbmidi_standard_output,
  	.output_packet = snd_usbmidi_output_standard_packet,
  };
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
682
  static const struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = {
a91e627e3   Clemens Ladisch   ALSA: usb-audio: ...
683
684
685
686
  	.input = ch345_broken_sysex_input,
  	.output = snd_usbmidi_standard_output,
  	.output_packet = snd_usbmidi_output_standard_packet,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  /*
4434ade8c   Krzysztof Foltman   ALSA: usb-audio: ...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
   * AKAI MPD16 protocol:
   *
   * For control port (endpoint 1):
   * ==============================
   * One or more chunks consisting of first byte of (0x10 | msg_len) and then a
   * SysEx message (msg_len=9 bytes long).
   *
   * For data port (endpoint 2):
   * ===========================
   * One or more chunks consisting of first byte of (0x20 | msg_len) and then a
   * MIDI message (msg_len bytes long)
   *
   * Messages sent: Active Sense, Note On, Poly Pressure, Control Change.
   */
  static void snd_usbmidi_akai_input(struct snd_usb_midi_in_endpoint *ep,
  				   uint8_t *buffer, int buffer_length)
  {
  	unsigned int pos = 0;
  	unsigned int len = (unsigned int)buffer_length;
  	while (pos < len) {
  		unsigned int port = (buffer[pos] >> 4) - 1;
  		unsigned int msg_len = buffer[pos] & 0x0f;
  		pos++;
  		if (pos + msg_len <= len && port < 2)
  			snd_usbmidi_input_data(ep, 0, &buffer[pos], msg_len);
  		pos += msg_len;
  	}
  }
  
  #define MAX_AKAI_SYSEX_LEN 9
  
  static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep,
  				    struct urb *urb)
  {
  	uint8_t *msg;
  	int pos, end, count, buf_end;
  	uint8_t tmp[MAX_AKAI_SYSEX_LEN];
  	struct snd_rawmidi_substream *substream = ep->ports[0].substream;
  
  	if (!ep->ports[0].active)
  		return;
  
  	msg = urb->transfer_buffer + urb->transfer_buffer_length;
  	buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
  
  	/* only try adding more data when there's space for at least 1 SysEx */
  	while (urb->transfer_buffer_length < buf_end) {
  		count = snd_rawmidi_transmit_peek(substream,
  						  tmp, MAX_AKAI_SYSEX_LEN);
  		if (!count) {
  			ep->ports[0].active = 0;
  			return;
  		}
  		/* try to skip non-SysEx data */
  		for (pos = 0; pos < count && tmp[pos] != 0xF0; pos++)
  			;
  
  		if (pos > 0) {
  			snd_rawmidi_transmit_ack(substream, pos);
  			continue;
  		}
  
  		/* look for the start or end marker */
  		for (end = 1; end < count && tmp[end] < 0xF0; end++)
  			;
  
  		/* next SysEx started before the end of current one */
  		if (end < count && tmp[end] == 0xF0) {
  			/* it's incomplete - drop it */
  			snd_rawmidi_transmit_ack(substream, end);
  			continue;
  		}
  		/* SysEx complete */
  		if (end < count && tmp[end] == 0xF7) {
  			/* queue it, ack it, and get the next one */
  			count = end + 1;
  			msg[0] = 0x10 | count;
  			memcpy(&msg[1], tmp, count);
  			snd_rawmidi_transmit_ack(substream, count);
  			urb->transfer_buffer_length += count + 1;
  			msg += count + 1;
  			continue;
  		}
  		/* less than 9 bytes and no end byte - wait for more */
  		if (count < MAX_AKAI_SYSEX_LEN) {
  			ep->ports[0].active = 0;
  			return;
  		}
  		/* 9 bytes and no end marker in sight - malformed, skip it */
  		snd_rawmidi_transmit_ack(substream, count);
  	}
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
780
  static const struct usb_protocol_ops snd_usbmidi_akai_ops = {
4434ade8c   Krzysztof Foltman   ALSA: usb-audio: ...
781
782
783
784
785
  	.input = snd_usbmidi_akai_input,
  	.output = snd_usbmidi_akai_output,
  };
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
787
788
789
   * Novation USB MIDI protocol: number of data bytes is in the first byte
   * (when receiving) (+1!) or in the second byte (when sending); data begins
   * at the third byte.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
790
791
  static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint *ep,
  				       uint8_t *buffer, int buffer_length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
795
796
  {
  	if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1)
  		return;
  	snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1);
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
797
  static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint *ep,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
798
  					struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
800
  	uint8_t *transfer_buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
802
803
804
  	int count;
  
  	if (!ep->ports[0].active)
  		return;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
805
  	transfer_buffer = urb->transfer_buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
810
811
812
813
814
  	count = snd_rawmidi_transmit(ep->ports[0].substream,
  				     &transfer_buffer[2],
  				     ep->max_transfer - 2);
  	if (count < 1) {
  		ep->ports[0].active = 0;
  		return;
  	}
  	transfer_buffer[0] = 0;
  	transfer_buffer[1] = count;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
815
  	urb->transfer_buffer_length = 2 + count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
817
  static const struct usb_protocol_ops snd_usbmidi_novation_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
819
820
821
822
  	.input = snd_usbmidi_novation_input,
  	.output = snd_usbmidi_novation_output,
  };
  
  /*
c7f572168   Clemens Ladisch   ALSA: usb-audio: ...
823
   * "raw" protocol: just move raw MIDI bytes from/to the endpoint
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
825
826
  static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint *ep,
  				  uint8_t *buffer, int buffer_length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
  {
  	snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
830
  static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint *ep,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
831
  				   struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
833
834
835
836
837
  {
  	int count;
  
  	if (!ep->ports[0].active)
  		return;
  	count = snd_rawmidi_transmit(ep->ports[0].substream,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
838
  				     urb->transfer_buffer,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
841
842
843
  				     ep->max_transfer);
  	if (count < 1) {
  		ep->ports[0].active = 0;
  		return;
  	}
ed4affa53   Clemens Ladisch   sound: usb-audio:...
844
  	urb->transfer_buffer_length = count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
846
  static const struct usb_protocol_ops snd_usbmidi_raw_ops = {
6155aff84   Clemens Ladisch   [ALSA] usb-audio ...
847
848
  	.input = snd_usbmidi_raw_input,
  	.output = snd_usbmidi_raw_output,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  };
1ef0e0a05   Kristian Amlie   ALSA: usb-audio: ...
850
851
852
  /*
   * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
853
854
  static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint *ep,
  				   uint8_t *buffer, int buffer_length)
1ef0e0a05   Kristian Amlie   ALSA: usb-audio: ...
855
856
857
858
  {
  	if (buffer_length > 2)
  		snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2);
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
859
  static const struct usb_protocol_ops snd_usbmidi_ftdi_ops = {
1ef0e0a05   Kristian Amlie   ALSA: usb-audio: ...
860
861
862
  	.input = snd_usbmidi_ftdi_input,
  	.output = snd_usbmidi_raw_output,
  };
030a07e44   Karsten Wiese   ALSA: Add USB US1...
863
864
865
866
867
868
869
870
871
872
873
  static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep,
  				     uint8_t *buffer, int buffer_length)
  {
  	if (buffer_length != 9)
  		return;
  	buffer_length = 8;
  	while (buffer_length && buffer[buffer_length - 1] == 0xFD)
  		buffer_length--;
  	if (buffer_length)
  		snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
  }
ed4affa53   Clemens Ladisch   sound: usb-audio:...
874
875
  static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
  				      struct urb *urb)
030a07e44   Karsten Wiese   ALSA: Add USB US1...
876
877
878
879
880
  {
  	int count;
  
  	if (!ep->ports[0].active)
  		return;
4f4e8f698   Paul Zimmerman   ALSA: usb: USB3 S...
881
882
883
  	switch (snd_usb_get_speed(ep->umidi->dev)) {
  	case USB_SPEED_HIGH:
  	case USB_SPEED_SUPER:
89e448b33   Oliver Neukum   ALSA: usb-midi: c...
884
  	case USB_SPEED_SUPER_PLUS:
4f4e8f698   Paul Zimmerman   ALSA: usb: USB3 S...
885
886
887
888
889
  		count = 1;
  		break;
  	default:
  		count = 2;
  	}
030a07e44   Karsten Wiese   ALSA: Add USB US1...
890
  	count = snd_rawmidi_transmit(ep->ports[0].substream,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
891
  				     urb->transfer_buffer,
030a07e44   Karsten Wiese   ALSA: Add USB US1...
892
893
894
895
896
  				     count);
  	if (count < 1) {
  		ep->ports[0].active = 0;
  		return;
  	}
921eebdc1   Karsten Wiese   ALSA: snd-usb-us1...
897
898
  	memset(urb->transfer_buffer + count, 0xFD, ep->max_transfer - count);
  	urb->transfer_buffer_length = ep->max_transfer;
030a07e44   Karsten Wiese   ALSA: Add USB US1...
899
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
900
  static const struct usb_protocol_ops snd_usbmidi_122l_ops = {
030a07e44   Karsten Wiese   ALSA: Add USB US1...
901
902
903
  	.input = snd_usbmidi_us122l_input,
  	.output = snd_usbmidi_us122l_output,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
906
  /*
   * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
907
  static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
  {
  	static const u8 init_data[] = {
  		/* initialization magic: "get version" */
  		0xf0,
  		0x00, 0x20, 0x31,	/* Emagic */
  		0x64,			/* Unitor8 */
  		0x0b,			/* version number request */
  		0x00,			/* command version */
  		0x00,			/* EEPROM, box 0 */
  		0xf7
  	};
  	send_bulk_static_data(ep, init_data, sizeof(init_data));
  	/* while we're at it, pour on more magic */
  	send_bulk_static_data(ep, init_data, sizeof(init_data));
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
923
  static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
925
926
927
928
929
930
931
932
933
934
935
936
937
  {
  	static const u8 finish_data[] = {
  		/* switch to patch mode with last preset */
  		0xf0,
  		0x00, 0x20, 0x31,	/* Emagic */
  		0x64,			/* Unitor8 */
  		0x10,			/* patch switch command */
  		0x00,			/* command version */
  		0x7f,			/* to all boxes */
  		0x40,			/* last preset in EEPROM */
  		0xf7
  	};
  	send_bulk_static_data(ep, finish_data, sizeof(finish_data));
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
938
939
  static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint *ep,
  				     uint8_t *buffer, int buffer_length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
  {
c347e9fca   Clemens Ladisch   [ALSA] usb-audio:...
941
942
943
944
945
946
947
948
  	int i;
  
  	/* FF indicates end of valid data */
  	for (i = 0; i < buffer_length; ++i)
  		if (buffer[i] == 0xff) {
  			buffer_length = i;
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
950
951
952
953
954
  
  	/* handle F5 at end of last buffer */
  	if (ep->seen_f5)
  		goto switch_port;
  
  	while (buffer_length > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
  		/* determine size of data until next F5 */
  		for (i = 0; i < buffer_length; ++i)
  			if (buffer[i] == 0xf5)
  				break;
  		snd_usbmidi_input_data(ep, ep->current_port, buffer, i);
  		buffer += i;
  		buffer_length -= i;
  
  		if (buffer_length <= 0)
  			break;
  		/* assert(buffer[0] == 0xf5); */
  		ep->seen_f5 = 1;
  		++buffer;
  		--buffer_length;
  
  	switch_port:
  		if (buffer_length <= 0)
  			break;
  		if (buffer[0] < 0x80) {
  			ep->current_port = (buffer[0] - 1) & 15;
  			++buffer;
  			--buffer_length;
  		}
  		ep->seen_f5 = 0;
  	}
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
981
  static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint *ep,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
982
  				      struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
  {
  	int port0 = ep->current_port;
a509574e5   Adam Goode   ALSA: usb-audio: ...
985
  	uint8_t *buf = urb->transfer_buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
987
988
989
990
991
  	int buf_free = ep->max_transfer;
  	int length, i;
  
  	for (i = 0; i < 0x10; ++i) {
  		/* round-robin, starting at the last current port */
  		int portnum = (port0 + i) & 15;
a509574e5   Adam Goode   ALSA: usb-audio: ...
992
  		struct usbmidi_out_port *port = &ep->ports[portnum];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
  
  		if (!port->active)
  			continue;
  		if (snd_rawmidi_transmit_peek(port->substream, buf, 1) != 1) {
  			port->active = 0;
  			continue;
  		}
  
  		if (portnum != ep->current_port) {
  			if (buf_free < 2)
  				break;
  			ep->current_port = portnum;
  			buf[0] = 0xf5;
  			buf[1] = (portnum + 1) & 15;
  			buf += 2;
  			buf_free -= 2;
  		}
  
  		if (buf_free < 1)
  			break;
  		length = snd_rawmidi_transmit(port->substream, buf, buf_free);
  		if (length > 0) {
  			buf += length;
  			buf_free -= length;
  			if (buf_free < 1)
  				break;
  		}
  	}
c347e9fca   Clemens Ladisch   [ALSA] usb-audio:...
1021
1022
1023
1024
  	if (buf_free < ep->max_transfer && buf_free > 0) {
  		*buf = 0xff;
  		--buf_free;
  	}
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1025
  	urb->transfer_buffer_length = ep->max_transfer - buf_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
  }
17074c1a5   Julia Lawall   ALSA: usb-audio: ...
1027
  static const struct usb_protocol_ops snd_usbmidi_emagic_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
1030
1031
1032
  	.input = snd_usbmidi_emagic_input,
  	.output = snd_usbmidi_emagic_output,
  	.init_out_endpoint = snd_usbmidi_emagic_init_out,
  	.finish_out_endpoint = snd_usbmidi_emagic_finish_out,
  };
a509574e5   Adam Goode   ALSA: usb-audio: ...
1033
  static void update_roland_altsetting(struct snd_usb_midi *umidi)
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
  {
  	struct usb_interface *intf;
  	struct usb_host_interface *hostif;
  	struct usb_interface_descriptor *intfd;
  	int is_light_load;
  
  	intf = umidi->iface;
  	is_light_load = intf->cur_altsetting != intf->altsetting;
  	if (umidi->roland_load_ctl->private_value == is_light_load)
  		return;
  	hostif = &intf->altsetting[umidi->roland_load_ctl->private_value];
  	intfd = get_iface_desc(hostif);
  	snd_usbmidi_input_stop(&umidi->list);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1047
  	usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1048
1049
1050
  			  intfd->bAlternateSetting);
  	snd_usbmidi_input_start(&umidi->list);
  }
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1051
1052
  static int substream_open(struct snd_rawmidi_substream *substream, int dir,
  			  int open)
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1053
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1054
  	struct snd_usb_midi *umidi = substream->rmidi->private_data;
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1055
  	struct snd_kcontrol *ctl;
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
1056
1057
1058
  	down_read(&umidi->disc_rwsem);
  	if (umidi->disconnected) {
  		up_read(&umidi->disc_rwsem);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1059
  		return open ? -ENODEV : 0;
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
1060
  	}
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1061
1062
  	mutex_lock(&umidi->mutex);
  	if (open) {
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1063
  		if (!umidi->opened[0] && !umidi->opened[1]) {
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1064
1065
  			if (umidi->roland_load_ctl) {
  				ctl = umidi->roland_load_ctl;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1066
1067
  				ctl->vd[0].access |=
  					SNDRV_CTL_ELEM_ACCESS_INACTIVE;
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1068
  				snd_ctl_notify(umidi->card,
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1069
  				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1070
1071
  				update_roland_altsetting(umidi);
  			}
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1072
  		}
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1073
1074
1075
  		umidi->opened[dir]++;
  		if (umidi->opened[1])
  			snd_usbmidi_input_start(&umidi->list);
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1076
  	} else {
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1077
1078
1079
1080
1081
1082
  		umidi->opened[dir]--;
  		if (!umidi->opened[1])
  			snd_usbmidi_input_stop(&umidi->list);
  		if (!umidi->opened[0] && !umidi->opened[1]) {
  			if (umidi->roland_load_ctl) {
  				ctl = umidi->roland_load_ctl;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1083
1084
  				ctl->vd[0].access &=
  					~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1085
  				snd_ctl_notify(umidi->card,
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1086
  				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1087
  			}
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1088
1089
1090
  		}
  	}
  	mutex_unlock(&umidi->mutex);
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
1091
  	up_read(&umidi->disc_rwsem);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1092
  	return 0;
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1093
  }
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
1094
  static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1096
1097
  	struct snd_usb_midi *umidi = substream->rmidi->private_data;
  	struct usbmidi_out_port *port = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
  	int i, j;
  
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
  		if (umidi->endpoints[i].out)
  			for (j = 0; j < 0x10; ++j)
  				if (umidi->endpoints[i].out->ports[j].substream == substream) {
  					port = &umidi->endpoints[i].out->ports[j];
  					break;
  				}
  	if (!port) {
  		snd_BUG();
  		return -ENXIO;
  	}
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
1111

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
1113
  	substream->runtime->private_data = port;
  	port->state = STATE_UNKNOWN;
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1114
  	return substream_open(substream, 0, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
  }
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
1116
  static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1117
  {
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1118
  	return substream_open(substream, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
1120
1121
  static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
  				       int up)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1123
1124
  	struct usbmidi_out_port *port =
  		(struct usbmidi_out_port *)substream->runtime->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
1127
  
  	port->active = up;
  	if (up) {
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1128
  		if (port->ep->umidi->disconnected) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
1130
1131
1132
1133
1134
  			/* gobble up remaining bytes to prevent wait in
  			 * snd_rawmidi_drain_output */
  			while (!snd_rawmidi_transmit_empty(substream))
  				snd_rawmidi_transmit_ack(substream, 1);
  			return;
  		}
1f04128a3   Takashi Iwai   ALSA: hda - Conve...
1135
  		tasklet_schedule(&port->ep->tasklet);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
1137
  	}
  }
a65dd997b   Clemens Ladisch   sound: usb-audio:...
1138
1139
  static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1140
  	struct usbmidi_out_port *port = substream->runtime->private_data;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
1141
1142
1143
1144
  	struct snd_usb_midi_out_endpoint *ep = port->ep;
  	unsigned int drain_urbs;
  	DEFINE_WAIT(wait);
  	long timeout = msecs_to_jiffies(50);
29aac005f   Takashi Iwai   ALSA: usb - Fix O...
1145
1146
  	if (ep->umidi->disconnected)
  		return;
a65dd997b   Clemens Ladisch   sound: usb-audio:...
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
  	/*
  	 * The substream buffer is empty, but some data might still be in the
  	 * currently active URBs, so we have to wait for those to complete.
  	 */
  	spin_lock_irq(&ep->buffer_lock);
  	drain_urbs = ep->active_urbs;
  	if (drain_urbs) {
  		ep->drain_urbs |= drain_urbs;
  		do {
  			prepare_to_wait(&ep->drain_wait, &wait,
  					TASK_UNINTERRUPTIBLE);
  			spin_unlock_irq(&ep->buffer_lock);
  			timeout = schedule_timeout(timeout);
  			spin_lock_irq(&ep->buffer_lock);
  			drain_urbs &= ep->drain_urbs;
  		} while (drain_urbs && timeout);
  		finish_wait(&ep->drain_wait, &wait);
  	}
  	spin_unlock_irq(&ep->buffer_lock);
  }
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
1167
  static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
  {
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1169
  	return substream_open(substream, 1, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  }
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
1171
  static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
  {
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
1173
  	return substream_open(substream, 1, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
1175
1176
  static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream,
  				      int up)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1178
  	struct snd_usb_midi *umidi = substream->rmidi->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
1181
1182
1183
1184
  
  	if (up)
  		set_bit(substream->number, &umidi->input_triggered);
  	else
  		clear_bit(substream->number, &umidi->input_triggered);
  }
f43e5407e   Takashi Iwai   ALSA: usb: Consti...
1185
  static const struct snd_rawmidi_ops snd_usbmidi_output_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
1187
1188
  	.open = snd_usbmidi_output_open,
  	.close = snd_usbmidi_output_close,
  	.trigger = snd_usbmidi_output_trigger,
a65dd997b   Clemens Ladisch   sound: usb-audio:...
1189
  	.drain = snd_usbmidi_output_drain,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
  };
f43e5407e   Takashi Iwai   ALSA: usb: Consti...
1191
  static const struct snd_rawmidi_ops snd_usbmidi_input_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
1194
1195
  	.open = snd_usbmidi_input_open,
  	.close = snd_usbmidi_input_close,
  	.trigger = snd_usbmidi_input_trigger
  };
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1196
1197
1198
  static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb,
  				unsigned int buffer_length)
  {
997ea58eb   Daniel Mack   USB: rename usb_b...
1199
1200
  	usb_free_coherent(umidi->dev, buffer_length,
  			  urb->transfer_buffer, urb->transfer_dma);
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1201
1202
  	usb_free_urb(urb);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203
1204
1205
1206
  /*
   * Frees an input endpoint.
   * May be called when ep hasn't been initialized completely.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1207
  static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  {
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1209
  	unsigned int i;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1210
1211
1212
1213
  	for (i = 0; i < INPUT_URBS; ++i)
  		if (ep->urbs[i])
  			free_urb_and_buffer(ep->umidi, ep->urbs[i],
  					    ep->urbs[i]->transfer_buffer_length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
1217
1218
1219
  	kfree(ep);
  }
  
  /*
   * Creates an input endpoint.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1220
1221
1222
  static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
  					  struct snd_usb_midi_endpoint_info *ep_info,
  					  struct snd_usb_midi_endpoint *rep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1224
1225
  	struct snd_usb_midi_in_endpoint *ep;
  	void *buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
  	unsigned int pipe;
  	int length;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1228
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229
1230
  
  	rep->in = NULL;
561b220a4   Takashi Iwai   [ALSA] Replace wi...
1231
  	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
1233
1234
  	if (!ep)
  		return -ENOMEM;
  	ep->umidi = umidi;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1235
1236
1237
1238
1239
1240
  	for (i = 0; i < INPUT_URBS; ++i) {
  		ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
  		if (!ep->urbs[i]) {
  			snd_usbmidi_in_endpoint_delete(ep);
  			return -ENOMEM;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
  	}
  	if (ep_info->in_interval)
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1243
  		pipe = usb_rcvintpipe(umidi->dev, ep_info->in_ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
  	else
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1245
1246
  		pipe = usb_rcvbulkpipe(umidi->dev, ep_info->in_ep);
  	length = usb_maxpacket(umidi->dev, pipe, 0);
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1247
  	for (i = 0; i < INPUT_URBS; ++i) {
997ea58eb   Daniel Mack   USB: rename usb_b...
1248
1249
  		buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
  					    &ep->urbs[i]->transfer_dma);
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1250
1251
1252
1253
1254
  		if (!buffer) {
  			snd_usbmidi_in_endpoint_delete(ep);
  			return -ENOMEM;
  		}
  		if (ep_info->in_interval)
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1255
  			usb_fill_int_urb(ep->urbs[i], umidi->dev,
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1256
1257
1258
1259
  					 pipe, buffer, length,
  					 snd_usbmidi_in_urb_complete,
  					 ep, ep_info->in_interval);
  		else
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1260
  			usb_fill_bulk_urb(ep->urbs[i], umidi->dev,
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1261
1262
1263
  					  pipe, buffer, length,
  					  snd_usbmidi_in_urb_complete, ep);
  		ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
1266
1267
1268
  
  	rep->in = ep;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
1270
1271
1272
  /*
   * Frees an output endpoint.
   * May be called when ep hasn't been initialized completely.
   */
29aac005f   Takashi Iwai   ALSA: usb - Fix O...
1273
  static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
  {
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1275
1276
1277
  	unsigned int i;
  
  	for (i = 0; i < OUTPUT_URBS; ++i)
29aac005f   Takashi Iwai   ALSA: usb - Fix O...
1278
  		if (ep->urbs[i].urb) {
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1279
1280
  			free_urb_and_buffer(ep->umidi, ep->urbs[i].urb,
  					    ep->max_transfer);
29aac005f   Takashi Iwai   ALSA: usb - Fix O...
1281
1282
1283
1284
1285
1286
1287
  			ep->urbs[i].urb = NULL;
  		}
  }
  
  static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep)
  {
  	snd_usbmidi_out_endpoint_clear(ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
1289
1290
1291
1292
1293
  	kfree(ep);
  }
  
  /*
   * Creates an output endpoint, and initializes output ports.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1294
1295
1296
  static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
  					   struct snd_usb_midi_endpoint_info *ep_info,
  					   struct snd_usb_midi_endpoint *rep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1298
  	struct snd_usb_midi_out_endpoint *ep;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1299
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
  	unsigned int pipe;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1301
  	void *buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
  
  	rep->out = NULL;
561b220a4   Takashi Iwai   [ALSA] Replace wi...
1304
  	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
1306
1307
  	if (!ep)
  		return -ENOMEM;
  	ep->umidi = umidi;
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1308
1309
1310
1311
1312
1313
1314
  	for (i = 0; i < OUTPUT_URBS; ++i) {
  		ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
  		if (!ep->urbs[i].urb) {
  			snd_usbmidi_out_endpoint_delete(ep);
  			return -ENOMEM;
  		}
  		ep->urbs[i].ep = ep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
  	}
a6a712aeb   Clemens Ladisch   [ALSA] usb-audio:...
1316
  	if (ep_info->out_interval)
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1317
  		pipe = usb_sndintpipe(umidi->dev, ep_info->out_ep);
a6a712aeb   Clemens Ladisch   [ALSA] usb-audio:...
1318
  	else
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1319
  		pipe = usb_sndbulkpipe(umidi->dev, ep_info->out_ep);
f167e1d07   Clemens Ladisch   ALSA: usb-audio: ...
1320
1321
  	switch (umidi->usb_id) {
  	default:
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1322
  		ep->max_transfer = usb_maxpacket(umidi->dev, pipe, 1);
f167e1d07   Clemens Ladisch   ALSA: usb-audio: ...
1323
1324
1325
1326
1327
  		break;
  		/*
  		 * Various chips declare a packet size larger than 4 bytes, but
  		 * do not actually work with larger packets:
  		 */
98d362bec   Clemens Ladisch   ALSA: usb-audio: ...
1328
  	case USB_ID(0x0a67, 0x5011): /* Medeli DD305 */
f167e1d07   Clemens Ladisch   ALSA: usb-audio: ...
1329
1330
1331
1332
1333
  	case USB_ID(0x0a92, 0x1020): /* ESI M4U */
  	case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */
  	case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */
  	case USB_ID(0x15ca, 0x1806): /* Textech USB Midi Cable */
  	case USB_ID(0x1a86, 0x752d): /* QinHeng CH345 "USB2.0-MIDI" */
49c039f07   Tarek Soliman   ALSA: usb-audio: ...
1334
  	case USB_ID(0xfc08, 0x0101): /* Unknown vendor Cable */
f167e1d07   Clemens Ladisch   ALSA: usb-audio: ...
1335
1336
  		ep->max_transfer = 4;
  		break;
921eebdc1   Karsten Wiese   ALSA: snd-usb-us1...
1337
1338
1339
1340
1341
1342
1343
  		/*
  		 * Some devices only work with 9 bytes packet size:
  		 */
  	case USB_ID(0x0644, 0x800E): /* Tascam US-122L */
  	case USB_ID(0x0644, 0x800F): /* Tascam US-144 */
  		ep->max_transfer = 9;
  		break;
f167e1d07   Clemens Ladisch   ALSA: usb-audio: ...
1344
  	}
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1345
  	for (i = 0; i < OUTPUT_URBS; ++i) {
997ea58eb   Daniel Mack   USB: rename usb_b...
1346
1347
1348
  		buffer = usb_alloc_coherent(umidi->dev,
  					    ep->max_transfer, GFP_KERNEL,
  					    &ep->urbs[i].urb->transfer_dma);
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1349
1350
1351
1352
1353
  		if (!buffer) {
  			snd_usbmidi_out_endpoint_delete(ep);
  			return -ENOMEM;
  		}
  		if (ep_info->out_interval)
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1354
  			usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1355
1356
1357
1358
  					 pipe, buffer, ep->max_transfer,
  					 snd_usbmidi_out_urb_complete,
  					 &ep->urbs[i], ep_info->out_interval);
  		else
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1359
  			usb_fill_bulk_urb(ep->urbs[i].urb, umidi->dev,
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1360
1361
1362
1363
  					  pipe, buffer, ep->max_transfer,
  					  snd_usbmidi_out_urb_complete,
  					  &ep->urbs[i]);
  		ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
1366
1367
  
  	spin_lock_init(&ep->buffer_lock);
  	tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep);
a65dd997b   Clemens Ladisch   sound: usb-audio:...
1368
  	init_waitqueue_head(&ep->drain_wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
  
  	for (i = 0; i < 0x10; ++i)
  		if (ep_info->out_cables & (1 << i)) {
  			ep->ports[i].ep = ep;
  			ep->ports[i].cable = i << 4;
  		}
  
  	if (umidi->usb_protocol_ops->init_out_endpoint)
  		umidi->usb_protocol_ops->init_out_endpoint(ep);
  
  	rep->out = ep;
  	return 0;
  }
  
  /*
   * Frees everything.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1386
  static void snd_usbmidi_free(struct snd_usb_midi *umidi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
1389
1390
  {
  	int i;
  
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1391
  		struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1392
1393
1394
1395
1396
  		if (ep->out)
  			snd_usbmidi_out_endpoint_delete(ep->out);
  		if (ep->in)
  			snd_usbmidi_in_endpoint_delete(ep->in);
  	}
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1397
  	mutex_destroy(&umidi->mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
1399
1400
1401
1402
1403
  	kfree(umidi);
  }
  
  /*
   * Unlinks all URBs (must be done before the usb_device is deleted).
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1404
  void snd_usbmidi_disconnect(struct list_head *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1406
  	struct snd_usb_midi *umidi;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1407
  	unsigned int i, j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408

86e07d346   Takashi Iwai   [ALSA] Remove xxx...
1409
  	umidi = list_entry(p, struct snd_usb_midi, list);
c0792e00b   Takashi Iwai   [ALSA] race betwe...
1410
1411
1412
1413
1414
  	/*
  	 * an URB's completion handler may start the timer and
  	 * a timer may submit an URB. To reliably break the cycle
  	 * a flag under lock must be used
  	 */
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
1415
  	down_write(&umidi->disc_rwsem);
c0792e00b   Takashi Iwai   [ALSA] race betwe...
1416
1417
1418
  	spin_lock_irq(&umidi->disc_lock);
  	umidi->disconnected = 1;
  	spin_unlock_irq(&umidi->disc_lock);
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
1419
  	up_write(&umidi->disc_rwsem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1421
  		struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
c88469704   Clemens Ladisch   [ALSA] usb-audio:...
1422
1423
  		if (ep->out)
  			tasklet_kill(&ep->out->tasklet);
ed4affa53   Clemens Ladisch   sound: usb-audio:...
1424
1425
1426
  		if (ep->out) {
  			for (j = 0; j < OUTPUT_URBS; ++j)
  				usb_kill_urb(ep->out->urbs[j].urb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
  			if (umidi->usb_protocol_ops->finish_out_endpoint)
  				umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
29aac005f   Takashi Iwai   ALSA: usb - Fix O...
1429
1430
1431
1432
1433
  			ep->out->active_urbs = 0;
  			if (ep->out->drain_urbs) {
  				ep->out->drain_urbs = 0;
  				wake_up(&ep->out->drain_wait);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
  		}
f5e135af8   Mariusz Kozlowski   usb: usbmidi kill...
1435
  		if (ep->in)
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
1436
1437
  			for (j = 0; j < INPUT_URBS; ++j)
  				usb_kill_urb(ep->in->urbs[j]);
7a17daae8   Takashi Iwai   ALSA: usb - Fix p...
1438
  		/* free endpoints here; later call can result in Oops */
29aac005f   Takashi Iwai   ALSA: usb - Fix O...
1439
1440
  		if (ep->out)
  			snd_usbmidi_out_endpoint_clear(ep->out);
7a17daae8   Takashi Iwai   ALSA: usb - Fix p...
1441
1442
1443
1444
  		if (ep->in) {
  			snd_usbmidi_in_endpoint_delete(ep->in);
  			ep->in = NULL;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
  	}
c0792e00b   Takashi Iwai   [ALSA] race betwe...
1446
  	del_timer_sync(&umidi->error_timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
  }
ed136aca7   Eldad Zack   ALSA: usb-audio: ...
1448
  EXPORT_SYMBOL(snd_usbmidi_disconnect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449

86e07d346   Takashi Iwai   [ALSA] Remove xxx...
1450
  static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1452
  	struct snd_usb_midi *umidi = rmidi->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
1454
  	snd_usbmidi_free(umidi);
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
1455
1456
1457
  static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi *umidi,
  								int stream,
  								int number)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
  {
88766f04c   Eldad Zack   ALSA: usb-audio: ...
1459
  	struct snd_rawmidi_substream *substream;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460

a509574e5   Adam Goode   ALSA: usb-audio: ...
1461
1462
  	list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams,
  			    list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
  		if (substream->number == number)
  			return substream;
  	}
  	return NULL;
  }
  
  /*
   * This list specifies names for ports that do not fit into the standard
   * "(product) MIDI (n)" schema because they aren't external MIDI ports,
   * such as internal control or synthesizer ports.
   */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1474
  static struct port_info {
27d10f566   Clemens Ladisch   [ALSA] usb-audio ...
1475
  	u32 id;
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
  	short int port;
  	short int voices;
  	const char *name;
  	unsigned int seq_flags;
  } snd_usbmidi_port_info[] = {
  #define PORT_INFO(vendor, product, num, name_, voices_, flags) \
  	{ .id = USB_ID(vendor, product), \
  	  .port = num, .voices = voices_, \
  	  .name = name_, .seq_flags = flags }
  #define EXTERNAL_PORT(vendor, product, num, name) \
  	PORT_INFO(vendor, product, num, name, 0, \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
  		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
  		  SNDRV_SEQ_PORT_TYPE_PORT)
  #define CONTROL_PORT(vendor, product, num, name) \
  	PORT_INFO(vendor, product, num, name, 0, \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
  		  SNDRV_SEQ_PORT_TYPE_HARDWARE)
49f4b4d15   Clemens Ladisch   ALSA: usb-audio: ...
1494
1495
1496
1497
1498
1499
  #define GM_SYNTH_PORT(vendor, product, num, name, voices) \
  	PORT_INFO(vendor, product, num, name, voices, \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
  		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
  		  SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
  #define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \
  	PORT_INFO(vendor, product, num, name, voices, \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GS | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_XG | \
  		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
  		  SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
  #define SOUNDCANVAS_PORT(vendor, product, num, name, voices) \
  	PORT_INFO(vendor, product, num, name, voices, \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_GS | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_XG | \
  		  SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \
  		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
  		  SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
49f4b4d15   Clemens Ladisch   ALSA: usb-audio: ...
1519
1520
1521
1522
1523
  	/* Yamaha MOTIF XF */
  	GM_SYNTH_PORT(0x0499, 0x105c, 0, "%s Tone Generator", 128),
  	CONTROL_PORT(0x0499, 0x105c, 1, "%s Remote Control"),
  	EXTERNAL_PORT(0x0499, 0x105c, 2, "%s Thru"),
  	CONTROL_PORT(0x0499, 0x105c, 3, "%s Editor"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
  	/* Roland UA-100 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1525
  	CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
  	/* Roland SC-8850 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1527
1528
1529
1530
1531
1532
  	SOUNDCANVAS_PORT(0x0582, 0x0003, 0, "%s Part A", 128),
  	SOUNDCANVAS_PORT(0x0582, 0x0003, 1, "%s Part B", 128),
  	SOUNDCANVAS_PORT(0x0582, 0x0003, 2, "%s Part C", 128),
  	SOUNDCANVAS_PORT(0x0582, 0x0003, 3, "%s Part D", 128),
  	EXTERNAL_PORT(0x0582, 0x0003, 4, "%s MIDI 1"),
  	EXTERNAL_PORT(0x0582, 0x0003, 5, "%s MIDI 2"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1533
  	/* Roland U-8 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1534
1535
  	EXTERNAL_PORT(0x0582, 0x0004, 0, "%s MIDI"),
  	CONTROL_PORT(0x0582, 0x0004, 1, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536
  	/* Roland SC-8820 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1537
1538
1539
  	SOUNDCANVAS_PORT(0x0582, 0x0007, 0, "%s Part A", 64),
  	SOUNDCANVAS_PORT(0x0582, 0x0007, 1, "%s Part B", 64),
  	EXTERNAL_PORT(0x0582, 0x0007, 2, "%s MIDI"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
  	/* Roland SK-500 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1541
1542
1543
  	SOUNDCANVAS_PORT(0x0582, 0x000b, 0, "%s Part A", 64),
  	SOUNDCANVAS_PORT(0x0582, 0x000b, 1, "%s Part B", 64),
  	EXTERNAL_PORT(0x0582, 0x000b, 2, "%s MIDI"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
  	/* Roland SC-D70 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1545
1546
1547
  	SOUNDCANVAS_PORT(0x0582, 0x000c, 0, "%s Part A", 64),
  	SOUNDCANVAS_PORT(0x0582, 0x000c, 1, "%s Part B", 64),
  	EXTERNAL_PORT(0x0582, 0x000c, 2, "%s MIDI"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  	/* Edirol UM-880 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1549
  	CONTROL_PORT(0x0582, 0x0014, 8, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  	/* Edirol SD-90 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1551
1552
1553
1554
  	ROLAND_SYNTH_PORT(0x0582, 0x0016, 0, "%s Part A", 128),
  	ROLAND_SYNTH_PORT(0x0582, 0x0016, 1, "%s Part B", 128),
  	EXTERNAL_PORT(0x0582, 0x0016, 2, "%s MIDI 1"),
  	EXTERNAL_PORT(0x0582, 0x0016, 3, "%s MIDI 2"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555
  	/* Edirol UM-550 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1556
  	CONTROL_PORT(0x0582, 0x0023, 5, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
  	/* Edirol SD-20 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1558
1559
1560
  	ROLAND_SYNTH_PORT(0x0582, 0x0027, 0, "%s Part A", 64),
  	ROLAND_SYNTH_PORT(0x0582, 0x0027, 1, "%s Part B", 64),
  	EXTERNAL_PORT(0x0582, 0x0027, 2, "%s MIDI"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
  	/* Edirol SD-80 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1562
1563
1564
1565
  	ROLAND_SYNTH_PORT(0x0582, 0x0029, 0, "%s Part A", 128),
  	ROLAND_SYNTH_PORT(0x0582, 0x0029, 1, "%s Part B", 128),
  	EXTERNAL_PORT(0x0582, 0x0029, 2, "%s MIDI 1"),
  	EXTERNAL_PORT(0x0582, 0x0029, 3, "%s MIDI 2"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
  	/* Edirol UA-700 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1567
1568
  	EXTERNAL_PORT(0x0582, 0x002b, 0, "%s MIDI"),
  	CONTROL_PORT(0x0582, 0x002b, 1, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569
  	/* Roland VariOS */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1570
1571
1572
  	EXTERNAL_PORT(0x0582, 0x002f, 0, "%s MIDI"),
  	EXTERNAL_PORT(0x0582, 0x002f, 1, "%s External MIDI"),
  	EXTERNAL_PORT(0x0582, 0x002f, 2, "%s Sync"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1573
  	/* Edirol PCR */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1574
1575
1576
  	EXTERNAL_PORT(0x0582, 0x0033, 0, "%s MIDI"),
  	EXTERNAL_PORT(0x0582, 0x0033, 1, "%s 1"),
  	EXTERNAL_PORT(0x0582, 0x0033, 2, "%s 2"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
  	/* BOSS GS-10 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1578
1579
  	EXTERNAL_PORT(0x0582, 0x003b, 0, "%s MIDI"),
  	CONTROL_PORT(0x0582, 0x003b, 1, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1580
  	/* Edirol UA-1000 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1581
1582
  	EXTERNAL_PORT(0x0582, 0x0044, 0, "%s MIDI"),
  	CONTROL_PORT(0x0582, 0x0044, 1, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
  	/* Edirol UR-80 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1584
1585
1586
  	EXTERNAL_PORT(0x0582, 0x0048, 0, "%s MIDI"),
  	EXTERNAL_PORT(0x0582, 0x0048, 1, "%s 1"),
  	EXTERNAL_PORT(0x0582, 0x0048, 2, "%s 2"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
  	/* Edirol PCR-A */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1588
1589
1590
  	EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"),
  	EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"),
  	EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"),
a968782e2   Clemens Ladisch   ALSA: usb-audio: ...
1591
1592
  	/* BOSS GT-PRO */
  	CONTROL_PORT(0x0582, 0x0089, 0, "%s Control"),
7c79b7682   Clemens Ladisch   [ALSA] usb-audio:...
1593
  	/* Edirol UM-3EX */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1594
  	CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"),
a968782e2   Clemens Ladisch   ALSA: usb-audio: ...
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
  	/* 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"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
  	/* M-Audio MidiSport 8x8 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1627
1628
  	CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"),
  	CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
  	/* MOTU Fastlane */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1630
1631
  	EXTERNAL_PORT(0x07fd, 0x0001, 0, "%s MIDI A"),
  	EXTERNAL_PORT(0x07fd, 0x0001, 1, "%s MIDI B"),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632
  	/* Emagic Unitor8/AMT8/MT4 */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1633
1634
1635
  	EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"),
  	EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"),
  	EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"),
4434ade8c   Krzysztof Foltman   ALSA: usb-audio: ...
1636
1637
1638
1639
1640
  	/* Akai MPD16 */
  	CONTROL_PORT(0x09e8, 0x0062, 0, "%s Control"),
  	PORT_INFO(0x09e8, 0x0062, 1, "%s MIDI", 0,
  		SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
  		SNDRV_SEQ_PORT_TYPE_HARDWARE),
d39e82db7   Sebastien Alaiwan   ALSA: USB MIDI su...
1641
1642
1643
1644
1645
1646
  	/* Access Music Virus TI */
  	EXTERNAL_PORT(0x133e, 0x0815, 0, "%s MIDI"),
  	PORT_INFO(0x133e, 0x0815, 1, "%s Synth", 0,
  		SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
  		SNDRV_SEQ_PORT_TYPE_HARDWARE |
  		SNDRV_SEQ_PORT_TYPE_SYNTHESIZER),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1647
  };
a509574e5   Adam Goode   ALSA: usb-audio: ...
1648
  static struct port_info *find_port_info(struct snd_usb_midi *umidi, int number)
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1649
1650
1651
1652
  {
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) {
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1653
  		if (snd_usbmidi_port_info[i].id == umidi->usb_id &&
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
  		    snd_usbmidi_port_info[i].port == number)
  			return &snd_usbmidi_port_info[i];
  	}
  	return NULL;
  }
  
  static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
  				      struct snd_seq_port_info *seq_port_info)
  {
  	struct snd_usb_midi *umidi = rmidi->private_data;
  	struct port_info *port_info;
  
  	/* TODO: read port flags from descriptors */
  	port_info = find_port_info(umidi, number);
  	if (port_info) {
  		seq_port_info->type = port_info->seq_flags;
  		seq_port_info->midi_voices = port_info->voices;
  	}
  }
a509574e5   Adam Goode   ALSA: usb-audio: ...
1673
  static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  				       int stream, int number,
a509574e5   Adam Goode   ALSA: usb-audio: ...
1675
  				       struct snd_rawmidi_substream **rsubstream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
  {
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1677
  	struct port_info *port_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
  	const char *name_format;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1679
1680
  	struct snd_rawmidi_substream *substream =
  		snd_usbmidi_find_substream(umidi, stream, number);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681
  	if (!substream) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1682
1683
1684
  		dev_err(&umidi->dev->dev, "substream %d:%d not found
  ", stream,
  			number);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
1686
1687
1688
  		return;
  	}
  
  	/* TODO: read port name from jack descriptor */
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
1689
1690
  	port_info = find_port_info(umidi, number);
  	name_format = port_info ? port_info->name : "%s MIDI %d";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691
  	snprintf(substream->name, sizeof(substream->name),
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1692
  		 name_format, umidi->card->shortname, number + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
1694
1695
1696
1697
1698
1699
  
  	*rsubstream = substream;
  }
  
  /*
   * Creates the endpoints and their ports.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1700
1701
  static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi,
  					struct snd_usb_midi_endpoint_info *endpoints)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
1703
1704
1705
1706
1707
  {
  	int i, j, err;
  	int out_ports = 0, in_ports = 0;
  
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
  		if (endpoints[i].out_cables) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1708
1709
  			err = snd_usbmidi_out_endpoint_create(umidi,
  							      &endpoints[i],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1710
1711
1712
1713
1714
  							      &umidi->endpoints[i]);
  			if (err < 0)
  				return err;
  		}
  		if (endpoints[i].in_cables) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1715
1716
  			err = snd_usbmidi_in_endpoint_create(umidi,
  							     &endpoints[i],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1717
1718
1719
1720
1721
1722
1723
  							     &umidi->endpoints[i]);
  			if (err < 0)
  				return err;
  		}
  
  		for (j = 0; j < 0x10; ++j) {
  			if (endpoints[i].out_cables & (1 << j)) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1724
1725
1726
  				snd_usbmidi_init_substream(umidi,
  							   SNDRV_RAWMIDI_STREAM_OUTPUT,
  							   out_ports,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
1728
1729
1730
  							   &umidi->endpoints[i].out->ports[j].substream);
  				++out_ports;
  			}
  			if (endpoints[i].in_cables & (1 << j)) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1731
1732
1733
  				snd_usbmidi_init_substream(umidi,
  							   SNDRV_RAWMIDI_STREAM_INPUT,
  							   in_ports,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1734
1735
1736
1737
1738
  							   &umidi->endpoints[i].in->ports[j].substream);
  				++in_ports;
  			}
  		}
  	}
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1739
1740
  	dev_dbg(&umidi->dev->dev, "created %d output and %d input ports
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
1742
1743
1744
1745
1746
1747
  		    out_ports, in_ports);
  	return 0;
  }
  
  /*
   * Returns MIDIStreaming device capabilities.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1748
1749
  static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
  				   struct snd_usb_midi_endpoint_info *endpoints)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1751
  	struct usb_interface *intf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1752
  	struct usb_host_interface *hostif;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1753
1754
  	struct usb_interface_descriptor *intfd;
  	struct usb_ms_header_descriptor *ms_header;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
  	struct usb_host_endpoint *hostep;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1756
1757
  	struct usb_endpoint_descriptor *ep;
  	struct usb_ms_endpoint_descriptor *ms_ep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
1759
1760
1761
1762
1763
1764
  	int i, epidx;
  
  	intf = umidi->iface;
  	if (!intf)
  		return -ENXIO;
  	hostif = &intf->altsetting[0];
  	intfd = get_iface_desc(hostif);
a509574e5   Adam Goode   ALSA: usb-audio: ...
1765
  	ms_header = (struct usb_ms_header_descriptor *)hostif->extra;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
1768
  	if (hostif->extralen >= 7 &&
  	    ms_header->bLength >= 7 &&
  	    ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
de48c7bc6   Daniel Mack   ALSA: usbaudio: c...
1769
  	    ms_header->bDescriptorSubtype == UAC_HEADER)
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1770
1771
  		dev_dbg(&umidi->dev->dev, "MIDIStreaming version %02x.%02x
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
  			    ms_header->bcdMSC[1], ms_header->bcdMSC[0]);
  	else
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1774
1775
1776
  		dev_warn(&umidi->dev->dev,
  			 "MIDIStreaming interface descriptor not found
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
1778
1779
1780
1781
  
  	epidx = 0;
  	for (i = 0; i < intfd->bNumEndpoints; ++i) {
  		hostep = &hostif->endpoint[i];
  		ep = get_ep_desc(hostep);
913ae5a24   Julia Lawall   ALSA: sound/usb: ...
1782
  		if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783
  			continue;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1784
  		ms_ep = (struct usb_ms_endpoint_descriptor *)hostep->extra;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
1786
1787
  		if (hostep->extralen < 4 ||
  		    ms_ep->bLength < 4 ||
  		    ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT ||
de48c7bc6   Daniel Mack   ALSA: usbaudio: c...
1788
  		    ms_ep->bDescriptorSubtype != UAC_MS_GENERAL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1789
  			continue;
42a6e66f1   Julia Lawall   ALSA: sound/usb: ...
1790
  		if (usb_endpoint_dir_out(ep)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
1792
  			if (endpoints[epidx].out_ep) {
  				if (++epidx >= MIDI_MAX_ENDPOINTS) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1793
1794
1795
  					dev_warn(&umidi->dev->dev,
  						 "too many endpoints
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796
1797
1798
  					break;
  				}
  			}
42a6e66f1   Julia Lawall   ALSA: sound/usb: ...
1799
1800
  			endpoints[epidx].out_ep = usb_endpoint_num(ep);
  			if (usb_endpoint_xfer_int(ep))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
  				endpoints[epidx].out_interval = ep->bInterval;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1802
  			else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
56162aabb   Clemens Ladisch   [ALSA] usb-audio:...
1803
1804
1805
1806
1807
1808
  				/*
  				 * Low speed bulk transfers don't exist, so
  				 * force interrupt transfers for devices like
  				 * ESI MIDI Mate that try to use them anyway.
  				 */
  				endpoints[epidx].out_interval = 1;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1809
1810
  			endpoints[epidx].out_cables =
  				(1 << ms_ep->bNumEmbMIDIJack) - 1;
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1811
1812
  			dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)
  ",
a509574e5   Adam Goode   ALSA: usb-audio: ...
1813
  				ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1814
1815
1816
  		} else {
  			if (endpoints[epidx].in_ep) {
  				if (++epidx >= MIDI_MAX_ENDPOINTS) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1817
1818
1819
  					dev_warn(&umidi->dev->dev,
  						 "too many endpoints
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
1821
1822
  					break;
  				}
  			}
42a6e66f1   Julia Lawall   ALSA: sound/usb: ...
1823
1824
  			endpoints[epidx].in_ep = usb_endpoint_num(ep);
  			if (usb_endpoint_xfer_int(ep))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
  				endpoints[epidx].in_interval = ep->bInterval;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1826
  			else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
56162aabb   Clemens Ladisch   [ALSA] usb-audio:...
1827
  				endpoints[epidx].in_interval = 1;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1828
1829
  			endpoints[epidx].in_cables =
  				(1 << ms_ep->bNumEmbMIDIJack) - 1;
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1830
1831
  			dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)
  ",
a509574e5   Adam Goode   ALSA: usb-audio: ...
1832
  				ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
1834
1835
1836
  		}
  	}
  	return 0;
  }
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1837
1838
1839
1840
  static int roland_load_info(struct snd_kcontrol *kcontrol,
  			    struct snd_ctl_elem_info *info)
  {
  	static const char *const names[] = { "High Load", "Light Load" };
2a1803a72   Clemens Ladisch   ALSA: usb-audio: ...
1841
  	return snd_ctl_enum_info(info, 1, 2, names);
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
  }
  
  static int roland_load_get(struct snd_kcontrol *kcontrol,
  			   struct snd_ctl_elem_value *value)
  {
  	value->value.enumerated.item[0] = kcontrol->private_value;
  	return 0;
  }
  
  static int roland_load_put(struct snd_kcontrol *kcontrol,
  			   struct snd_ctl_elem_value *value)
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1854
  	struct snd_usb_midi *umidi = kcontrol->private_data;
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
  	int changed;
  
  	if (value->value.enumerated.item[0] > 1)
  		return -EINVAL;
  	mutex_lock(&umidi->mutex);
  	changed = value->value.enumerated.item[0] != kcontrol->private_value;
  	if (changed)
  		kcontrol->private_value = value->value.enumerated.item[0];
  	mutex_unlock(&umidi->mutex);
  	return changed;
  }
8fdaebbb8   Bhumika Goyal   ALSA: usb-audio: ...
1866
  static const struct snd_kcontrol_new roland_load_ctl = {
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1867
1868
1869
1870
1871
1872
1873
  	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  	.name = "MIDI Input Mode",
  	.info = roland_load_info,
  	.get = roland_load_get,
  	.put = roland_load_put,
  	.private_value = 1,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
1875
1876
1877
  /*
   * On Roland devices, use the second alternate setting to be able to use
   * the interrupt input endpoint.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1878
  static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi *umidi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1879
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1880
  	struct usb_interface *intf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
  	struct usb_host_interface *hostif;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1882
  	struct usb_interface_descriptor *intfd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
1884
1885
1886
1887
1888
1889
  
  	intf = umidi->iface;
  	if (!intf || intf->num_altsetting != 2)
  		return;
  
  	hostif = &intf->altsetting[1];
  	intfd = get_iface_desc(hostif);
ac7742360   Keith A. Milner   ALSA: usb-audio: ...
1890
1891
1892
         /* If either or both of the endpoints support interrupt transfer,
          * then use the alternate setting
          */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1893
  	if (intfd->bNumEndpoints != 2 ||
ac7742360   Keith A. Milner   ALSA: usb-audio: ...
1894
1895
1896
1897
  	    !((get_endpoint(hostif, 0)->bmAttributes &
  	       USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT ||
  	      (get_endpoint(hostif, 1)->bmAttributes &
  	       USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1898
  		return;
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
1899
1900
  	dev_dbg(&umidi->dev->dev, "switching to altsetting %d with int ep
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
  		    intfd->bAlternateSetting);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1902
  	usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1903
  			  intfd->bAlternateSetting);
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1904
1905
  
  	umidi->roland_load_ctl = snd_ctl_new1(&roland_load_ctl, umidi);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1906
  	if (snd_ctl_add(umidi->card, umidi->roland_load_ctl) < 0)
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
1907
  		umidi->roland_load_ctl = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1908
1909
1910
1911
1912
  }
  
  /*
   * Try to find any usable endpoints in the interface.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1913
1914
  static int snd_usbmidi_detect_endpoints(struct snd_usb_midi *umidi,
  					struct snd_usb_midi_endpoint_info *endpoint,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1915
1916
  					int max_endpoints)
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1917
  	struct usb_interface *intf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1918
  	struct usb_host_interface *hostif;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1919
1920
  	struct usb_interface_descriptor *intfd;
  	struct usb_endpoint_descriptor *epd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
  	int i, out_eps = 0, in_eps = 0;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
1922
  	if (USB_ID_VENDOR(umidi->usb_id) == 0x0582)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
  		snd_usbmidi_switch_roland_altsetting(umidi);
c1ab5d59a   Clemens Ladisch   [ALSA] usb-audio ...
1924
  	if (endpoint[0].out_ep || endpoint[0].in_ep)
21af7d8c0   Daniel Mack   ALSA: usb-midi: w...
1925
  		return 0;
c1ab5d59a   Clemens Ladisch   [ALSA] usb-audio ...
1926

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
1928
1929
1930
1931
1932
1933
1934
  	intf = umidi->iface;
  	if (!intf || intf->num_altsetting < 1)
  		return -ENOENT;
  	hostif = intf->cur_altsetting;
  	intfd = get_iface_desc(hostif);
  
  	for (i = 0; i < intfd->bNumEndpoints; ++i) {
  		epd = get_endpoint(hostif, i);
913ae5a24   Julia Lawall   ALSA: sound/usb: ...
1935
1936
  		if (!usb_endpoint_xfer_bulk(epd) &&
  		    !usb_endpoint_xfer_int(epd))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1937
1938
  			continue;
  		if (out_eps < max_endpoints &&
42a6e66f1   Julia Lawall   ALSA: sound/usb: ...
1939
1940
1941
  		    usb_endpoint_dir_out(epd)) {
  			endpoint[out_eps].out_ep = usb_endpoint_num(epd);
  			if (usb_endpoint_xfer_int(epd))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942
1943
1944
1945
  				endpoint[out_eps].out_interval = epd->bInterval;
  			++out_eps;
  		}
  		if (in_eps < max_endpoints &&
42a6e66f1   Julia Lawall   ALSA: sound/usb: ...
1946
1947
1948
  		    usb_endpoint_dir_in(epd)) {
  			endpoint[in_eps].in_ep = usb_endpoint_num(epd);
  			if (usb_endpoint_xfer_int(epd))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
  				endpoint[in_eps].in_interval = epd->bInterval;
  			++in_eps;
  		}
  	}
  	return (out_eps || in_eps) ? 0 : -ENOENT;
  }
  
  /*
   * Detects the endpoints for one-port-per-endpoint protocols.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1959
1960
  static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi *umidi,
  						 struct snd_usb_midi_endpoint_info *endpoints)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1961
1962
  {
  	int err, i;
21af7d8c0   Daniel Mack   ALSA: usb-midi: w...
1963

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
  	err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
  		if (endpoints[i].out_ep)
  			endpoints[i].out_cables = 0x0001;
  		if (endpoints[i].in_ep)
  			endpoints[i].in_cables = 0x0001;
  	}
  	return err;
  }
  
  /*
   * Detects the endpoints and ports of Yamaha devices.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
1977
1978
  static int snd_usbmidi_detect_yamaha(struct snd_usb_midi *umidi,
  				     struct snd_usb_midi_endpoint_info *endpoint)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1979
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
1980
  	struct usb_interface *intf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1981
  	struct usb_host_interface *hostif;
a509574e5   Adam Goode   ALSA: usb-audio: ...
1982
1983
  	struct usb_interface_descriptor *intfd;
  	uint8_t *cs_desc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
  
  	intf = umidi->iface;
  	if (!intf)
  		return -ENOENT;
  	hostif = intf->altsetting;
  	intfd = get_iface_desc(hostif);
  	if (intfd->bNumEndpoints < 1)
  		return -ENOENT;
  
  	/*
  	 * For each port there is one MIDI_IN/OUT_JACK descriptor, not
  	 * necessarily with any useful contents.  So simply count 'em.
  	 */
  	for (cs_desc = hostif->extra;
  	     cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
  	     cs_desc += cs_desc[0]) {
c4a87ef4d   Ben Williamson   [ALSA] USB midi: ...
2000
  		if (cs_desc[1] == USB_DT_CS_INTERFACE) {
de48c7bc6   Daniel Mack   ALSA: usbaudio: c...
2001
  			if (cs_desc[2] == UAC_MIDI_IN_JACK)
a509574e5   Adam Goode   ALSA: usb-audio: ...
2002
2003
  				endpoint->in_cables =
  					(endpoint->in_cables << 1) | 1;
de48c7bc6   Daniel Mack   ALSA: usbaudio: c...
2004
  			else if (cs_desc[2] == UAC_MIDI_OUT_JACK)
a509574e5   Adam Goode   ALSA: usb-audio: ...
2005
2006
  				endpoint->out_cables =
  					(endpoint->out_cables << 1) | 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
2008
2009
2010
2011
2012
2013
2014
2015
  		}
  	}
  	if (!endpoint->in_cables && !endpoint->out_cables)
  		return -ENOENT;
  
  	return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
  }
  
  /*
aafe77cc4   Clemens Ladisch   ALSA: usb-audio: ...
2016
2017
   * Detects the endpoints and ports of Roland devices.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
2018
2019
  static int snd_usbmidi_detect_roland(struct snd_usb_midi *umidi,
  				     struct snd_usb_midi_endpoint_info *endpoint)
aafe77cc4   Clemens Ladisch   ALSA: usb-audio: ...
2020
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2021
  	struct usb_interface *intf;
aafe77cc4   Clemens Ladisch   ALSA: usb-audio: ...
2022
  	struct usb_host_interface *hostif;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2023
  	u8 *cs_desc;
aafe77cc4   Clemens Ladisch   ALSA: usb-audio: ...
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
  
  	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;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2054
2055
   * Creates the endpoints and their ports for Midiman devices.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
2056
2057
  static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi *umidi,
  						struct snd_usb_midi_endpoint_info *endpoint)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
  {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2059
  	struct snd_usb_midi_endpoint_info ep_info;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2060
  	struct usb_interface *intf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2061
  	struct usb_host_interface *hostif;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2062
2063
  	struct usb_interface_descriptor *intfd;
  	struct usb_endpoint_descriptor *epd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
  	int cable, err;
  
  	intf = umidi->iface;
  	if (!intf)
  		return -ENOENT;
  	hostif = intf->altsetting;
  	intfd = get_iface_desc(hostif);
  	/*
  	 * The various MidiSport devices have more or less random endpoint
  	 * numbers, so we have to identify the endpoints by their index in
  	 * the descriptor array, like the driver for that other OS does.
  	 *
  	 * There is one interrupt input endpoint for all input ports, one
  	 * bulk output endpoint for even-numbered ports, and one for odd-
  	 * numbered ports.  Both bulk output endpoints have corresponding
  	 * input bulk endpoints (at indices 1 and 3) which aren't used.
  	 */
  	if (intfd->bNumEndpoints < (endpoint->out_cables > 0x0001 ? 5 : 3)) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
2082
2083
  		dev_dbg(&umidi->dev->dev, "not enough endpoints
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2084
2085
2086
2087
  		return -ENOENT;
  	}
  
  	epd = get_endpoint(hostif, 0);
913ae5a24   Julia Lawall   ALSA: sound/usb: ...
2088
  	if (!usb_endpoint_dir_in(epd) || !usb_endpoint_xfer_int(epd)) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
2089
2090
  		dev_dbg(&umidi->dev->dev, "endpoint[0] isn't interrupt
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2091
2092
2093
  		return -ENXIO;
  	}
  	epd = get_endpoint(hostif, 2);
913ae5a24   Julia Lawall   ALSA: sound/usb: ...
2094
  	if (!usb_endpoint_dir_out(epd) || !usb_endpoint_xfer_bulk(epd)) {
0ba41d917   Takashi Iwai   ALSA: usb-audio: ...
2095
2096
  		dev_dbg(&umidi->dev->dev, "endpoint[2] isn't bulk output
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
2098
2099
2100
  		return -ENXIO;
  	}
  	if (endpoint->out_cables > 0x0001) {
  		epd = get_endpoint(hostif, 4);
913ae5a24   Julia Lawall   ALSA: sound/usb: ...
2101
2102
  		if (!usb_endpoint_dir_out(epd) ||
  		    !usb_endpoint_xfer_bulk(epd)) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2103
2104
2105
  			dev_dbg(&umidi->dev->dev,
  				"endpoint[4] isn't bulk output
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2106
2107
2108
  			return -ENXIO;
  		}
  	}
a509574e5   Adam Goode   ALSA: usb-audio: ...
2109
2110
  	ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress &
  		USB_ENDPOINT_NUMBER_MASK;
e156ac4c5   Clemens Ladisch   sound: usb-audio:...
2111
  	ep_info.out_interval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2112
  	ep_info.out_cables = endpoint->out_cables & 0x5555;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2113
2114
  	err = snd_usbmidi_out_endpoint_create(umidi, &ep_info,
  					      &umidi->endpoints[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2115
2116
  	if (err < 0)
  		return err;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2117
2118
  	ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress &
  		USB_ENDPOINT_NUMBER_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2119
2120
  	ep_info.in_interval = get_endpoint(hostif, 0)->bInterval;
  	ep_info.in_cables = endpoint->in_cables;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2121
2122
  	err = snd_usbmidi_in_endpoint_create(umidi, &ep_info,
  					     &umidi->endpoints[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2123
2124
2125
2126
  	if (err < 0)
  		return err;
  
  	if (endpoint->out_cables > 0x0001) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2127
2128
  		ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress &
  			USB_ENDPOINT_NUMBER_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2129
  		ep_info.out_cables = endpoint->out_cables & 0xaaaa;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2130
2131
  		err = snd_usbmidi_out_endpoint_create(umidi, &ep_info,
  						      &umidi->endpoints[1]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2132
2133
2134
2135
2136
2137
  		if (err < 0)
  			return err;
  	}
  
  	for (cable = 0; cable < 0x10; ++cable) {
  		if (endpoint->out_cables & (1 << cable))
a509574e5   Adam Goode   ALSA: usb-audio: ...
2138
2139
2140
  			snd_usbmidi_init_substream(umidi,
  						   SNDRV_RAWMIDI_STREAM_OUTPUT,
  						   cable,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141
2142
  						   &umidi->endpoints[cable & 1].out->ports[cable].substream);
  		if (endpoint->in_cables & (1 << cable))
a509574e5   Adam Goode   ALSA: usb-audio: ...
2143
2144
2145
  			snd_usbmidi_init_substream(umidi,
  						   SNDRV_RAWMIDI_STREAM_INPUT,
  						   cable,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2146
2147
2148
2149
  						   &umidi->endpoints[0].in->ports[cable].substream);
  	}
  	return 0;
  }
efdbe3c3e   Julia Lawall   ALSA: midi: const...
2150
  static const struct snd_rawmidi_global_ops snd_usbmidi_ops = {
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
2151
2152
  	.get_port_info = snd_usbmidi_get_port_info,
  };
a509574e5   Adam Goode   ALSA: usb-audio: ...
2153
  static int snd_usbmidi_create_rawmidi(struct snd_usb_midi *umidi,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2154
2155
  				      int out_ports, int in_ports)
  {
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2156
  	struct snd_rawmidi *rmidi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2157
  	int err;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2158
2159
  	err = snd_rawmidi_new(umidi->card, "USB MIDI",
  			      umidi->next_midi_device++,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
2161
2162
  			      out_ports, in_ports, &rmidi);
  	if (err < 0)
  		return err;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2163
  	strcpy(rmidi->name, umidi->card->shortname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
2165
2166
  	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
  			    SNDRV_RAWMIDI_INFO_INPUT |
  			    SNDRV_RAWMIDI_INFO_DUPLEX;
a7b928ac5   Clemens Ladisch   [ALSA] rawmidi: a...
2167
  	rmidi->ops = &snd_usbmidi_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2168
2169
  	rmidi->private_data = umidi;
  	rmidi->private_free = snd_usbmidi_rawmidi_free;
a509574e5   Adam Goode   ALSA: usb-audio: ...
2170
2171
2172
2173
  	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  			    &snd_usbmidi_output_ops);
  	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  			    &snd_usbmidi_input_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2174
2175
2176
2177
2178
2179
2180
2181
  
  	umidi->rmidi = rmidi;
  	return 0;
  }
  
  /*
   * Temporarily stop input.
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
2182
  void snd_usbmidi_input_stop(struct list_head *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2183
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2184
  	struct snd_usb_midi *umidi;
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
2185
  	unsigned int i, j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2186

86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2187
  	umidi = list_entry(p, struct snd_usb_midi, list);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
2188
2189
  	if (!umidi->input_running)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2190
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2191
  		struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2192
  		if (ep->in)
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
2193
2194
  			for (j = 0; j < INPUT_URBS; ++j)
  				usb_kill_urb(ep->in->urbs[j]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2195
  	}
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
2196
  	umidi->input_running = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2197
  }
ed136aca7   Eldad Zack   ALSA: usb-audio: ...
2198
  EXPORT_SYMBOL(snd_usbmidi_input_stop);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2199

a509574e5   Adam Goode   ALSA: usb-audio: ...
2200
  static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2201
  {
4773d1fb8   Clemens Ladisch   sound: usb-audio:...
2202
2203
2204
2205
2206
  	unsigned int i;
  
  	if (!ep)
  		return;
  	for (i = 0; i < INPUT_URBS; ++i) {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2207
  		struct urb *urb = ep->urbs[i];
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2208
  		urb->dev = ep->umidi->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2209
2210
2211
2212
2213
2214
2215
  		snd_usbmidi_submit_urb(urb, GFP_KERNEL);
  	}
  }
  
  /*
   * Resume input after a call to snd_usbmidi_input_stop().
   */
a509574e5   Adam Goode   ALSA: usb-audio: ...
2216
  void snd_usbmidi_input_start(struct list_head *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2217
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2218
  	struct snd_usb_midi *umidi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2219
  	int i;
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2220
  	umidi = list_entry(p, struct snd_usb_midi, list);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
2221
2222
  	if (umidi->input_running || !umidi->opened[1])
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2223
2224
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
  		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
f5f165418   Takashi Iwai   ALSA: usb-audio: ...
2225
  	umidi->input_running = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2226
  }
ed136aca7   Eldad Zack   ALSA: usb-audio: ...
2227
  EXPORT_SYMBOL(snd_usbmidi_input_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2228
2229
  
  /*
f7881e5e8   Adam Goode   ALSA: usb-audio: ...
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
   * Prepare for suspend. Typically called from the USB suspend callback.
   */
  void snd_usbmidi_suspend(struct list_head *p)
  {
  	struct snd_usb_midi *umidi;
  
  	umidi = list_entry(p, struct snd_usb_midi, list);
  	mutex_lock(&umidi->mutex);
  	snd_usbmidi_input_stop(p);
  	mutex_unlock(&umidi->mutex);
  }
  EXPORT_SYMBOL(snd_usbmidi_suspend);
  
  /*
   * Resume. Typically called from the USB resume callback.
   */
  void snd_usbmidi_resume(struct list_head *p)
  {
  	struct snd_usb_midi *umidi;
  
  	umidi = list_entry(p, struct snd_usb_midi, list);
  	mutex_lock(&umidi->mutex);
  	snd_usbmidi_input_start(p);
  	mutex_unlock(&umidi->mutex);
  }
  EXPORT_SYMBOL(snd_usbmidi_resume);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2258
2259
   * Creates and registers everything needed for a MIDI streaming interface.
   */
79289e241   Takashi Iwai   ALSA: usb-audio: ...
2260
2261
2262
2263
2264
  int __snd_usbmidi_create(struct snd_card *card,
  			 struct usb_interface *iface,
  			 struct list_head *midi_list,
  			 const struct snd_usb_audio_quirk *quirk,
  			 unsigned int usb_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2265
  {
a509574e5   Adam Goode   ALSA: usb-audio: ...
2266
  	struct snd_usb_midi *umidi;
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2267
  	struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2268
2269
  	int out_ports, in_ports;
  	int i, err;
561b220a4   Takashi Iwai   [ALSA] Replace wi...
2270
  	umidi = kzalloc(sizeof(*umidi), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2271
2272
  	if (!umidi)
  		return -ENOMEM;
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2273
2274
  	umidi->dev = interface_to_usbdev(iface);
  	umidi->card = card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2275
2276
2277
  	umidi->iface = iface;
  	umidi->quirk = quirk;
  	umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
c0792e00b   Takashi Iwai   [ALSA] race betwe...
2278
  	spin_lock_init(&umidi->disc_lock);
59866da9e   Takashi Iwai   ALSA: usb-audio: ...
2279
  	init_rwsem(&umidi->disc_rwsem);
96f61d9ad   Clemens Ladisch   sound: usb-audio:...
2280
  	mutex_init(&umidi->mutex);
79289e241   Takashi Iwai   ALSA: usb-audio: ...
2281
2282
  	if (!usb_id)
  		usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2283
  			       le16_to_cpu(umidi->dev->descriptor.idProduct));
79289e241   Takashi Iwai   ALSA: usb-audio: ...
2284
  	umidi->usb_id = usb_id;
28e237a9b   Takashi Iwai   ALSA: usb-audio: ...
2285
2286
  	setup_timer(&umidi->error_timer, snd_usbmidi_error_timer,
  		    (unsigned long)umidi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287
2288
2289
  
  	/* detect the endpoint(s) to use */
  	memset(endpoints, 0, sizeof(endpoints));
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2290
2291
  	switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) {
  	case QUIRK_MIDI_STANDARD_INTERFACE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2292
  		err = snd_usbmidi_get_ms_info(umidi, endpoints);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2293
  		if (umidi->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */
d05cc1043   Clemens Ladisch   [ALSA] usb-audio:...
2294
2295
  			umidi->usb_protocol_ops =
  				&snd_usbmidi_maudio_broken_running_status_ops;
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2296
  		break;
030a07e44   Karsten Wiese   ALSA: Add USB US1...
2297
2298
2299
  	case QUIRK_MIDI_US122L:
  		umidi->usb_protocol_ops = &snd_usbmidi_122l_ops;
  		/* fall through */
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2300
2301
  	case QUIRK_MIDI_FIXED_ENDPOINT:
  		memcpy(&endpoints[0], quirk->data,
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2302
  		       sizeof(struct snd_usb_midi_endpoint_info));
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2303
2304
2305
2306
2307
  		err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
  		break;
  	case QUIRK_MIDI_YAMAHA:
  		err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
  		break;
aafe77cc4   Clemens Ladisch   ALSA: usb-audio: ...
2308
2309
2310
  	case QUIRK_MIDI_ROLAND:
  		err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
  		break;
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2311
2312
2313
  	case QUIRK_MIDI_MIDIMAN:
  		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
  		memcpy(&endpoints[0], quirk->data,
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2314
  		       sizeof(struct snd_usb_midi_endpoint_info));
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2315
2316
2317
2318
2319
2320
  		err = 0;
  		break;
  	case QUIRK_MIDI_NOVATION:
  		umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
  		break;
c7f572168   Clemens Ladisch   ALSA: usb-audio: ...
2321
  	case QUIRK_MIDI_RAW_BYTES:
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2322
  		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
55de5ef97   Clemens Ladisch   sound: usb-audio:...
2323
2324
2325
2326
2327
2328
2329
2330
2331
  		/*
  		 * Interface 1 contains isochronous endpoints, but with the same
  		 * numbers as in interface 0.  Since it is interface 1 that the
  		 * USB core has most recently seen, these descriptors are now
  		 * associated with the endpoint numbers.  This will foul up our
  		 * attempts to submit bulk/interrupt URBs to the endpoints in
  		 * interface 0, so we have to make sure that the USB core looks
  		 * again at interface 0 by calling usb_set_interface() on it.
  		 */
c7f572168   Clemens Ladisch   ALSA: usb-audio: ...
2332
2333
  		if (umidi->usb_id == USB_ID(0x07fd, 0x0001)) /* MOTU Fastlane */
  			usb_set_interface(umidi->dev, 0, 0);
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2334
2335
2336
2337
2338
  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
  		break;
  	case QUIRK_MIDI_EMAGIC:
  		umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops;
  		memcpy(&endpoints[0], quirk->data,
86e07d346   Takashi Iwai   [ALSA] Remove xxx...
2339
  		       sizeof(struct snd_usb_midi_endpoint_info));
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2340
2341
  		err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
  		break;
cc7a59bd8   Clemens Ladisch   [ALSA] usb-audio:...
2342
  	case QUIRK_MIDI_CME:
61870aed2   Clemens Ladisch   [ALSA] usb-audio:...
2343
  		umidi->usb_protocol_ops = &snd_usbmidi_cme_ops;
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2344
2345
  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
  		break;
4434ade8c   Krzysztof Foltman   ALSA: usb-audio: ...
2346
2347
2348
2349
2350
2351
  	case QUIRK_MIDI_AKAI:
  		umidi->usb_protocol_ops = &snd_usbmidi_akai_ops;
  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
  		/* endpoint 1 is input-only */
  		endpoints[1].out_cables = 0;
  		break;
1ef0e0a05   Kristian Amlie   ALSA: usb-audio: ...
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
  	case QUIRK_MIDI_FTDI:
  		umidi->usb_protocol_ops = &snd_usbmidi_ftdi_ops;
  
  		/* set baud rate to 31250 (48 MHz / 16 / 96) */
  		err = usb_control_msg(umidi->dev, usb_sndctrlpipe(umidi->dev, 0),
  				      3, 0x40, 0x60, 0, NULL, 0, 1000);
  		if (err < 0)
  			break;
  
  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
  		break;
1ca8b2013   Clemens Ladisch   ALSA: usb-audio: ...
2363
  	case QUIRK_MIDI_CH345:
a91e627e3   Clemens Ladisch   ALSA: usb-audio: ...
2364
  		umidi->usb_protocol_ops = &snd_usbmidi_ch345_broken_sysex_ops;
1ca8b2013   Clemens Ladisch   ALSA: usb-audio: ...
2365
2366
  		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
  		break;
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2367
  	default:
a509574e5   Adam Goode   ALSA: usb-audio: ...
2368
2369
2370
  		dev_err(&umidi->dev->dev, "invalid quirk type %d
  ",
  			quirk->type);
d1bda0455   Clemens Ladisch   [ALSA] usb-audio:...
2371
2372
  		err = -ENXIO;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2373
  	}
731209cc0   Markus Elfring   ALSA: usb-midi: U...
2374
2375
  	if (err < 0)
  		goto free_midi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2376
2377
2378
2379
2380
  
  	/* create rawmidi device */
  	out_ports = 0;
  	in_ports = 0;
  	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
fbc543915   Akinobu Mita   ALSA: sound: usbm...
2381
2382
  		out_ports += hweight16(endpoints[i].out_cables);
  		in_ports += hweight16(endpoints[i].in_cables);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2383
2384
  	}
  	err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
731209cc0   Markus Elfring   ALSA: usb-midi: U...
2385
2386
  	if (err < 0)
  		goto free_midi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2387
2388
2389
2390
2391
2392
  
  	/* create endpoint/port structures */
  	if (quirk && quirk->type == QUIRK_MIDI_MIDIMAN)
  		err = snd_usbmidi_create_endpoints_midiman(umidi, &endpoints[0]);
  	else
  		err = snd_usbmidi_create_endpoints(umidi, endpoints);
731209cc0   Markus Elfring   ALSA: usb-midi: U...
2393
2394
  	if (err < 0)
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2395

cbc200bca   Clemens Ladisch   ALSA: usb-audio: ...
2396
  	usb_autopm_get_interface_no_resume(umidi->iface);
d82af9f9a   Clemens Ladisch   sound: usb: make ...
2397
  	list_add_tail(&umidi->list, midi_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2398
  	return 0;
731209cc0   Markus Elfring   ALSA: usb-midi: U...
2399
2400
2401
2402
2403
  
  free_midi:
  	kfree(umidi);
  exit:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2404
  }
79289e241   Takashi Iwai   ALSA: usb-audio: ...
2405
  EXPORT_SYMBOL(__snd_usbmidi_create);