2 * Line6 Linux USB driver - 0.9.1beta
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
12 #include <linux/slab.h>
13 #include <linux/usb.h>
14 #include <sound/core.h>
15 #include <sound/rawmidi.h>
23 #define line6_rawmidi_substream_midi(substream) \
24 ((struct snd_line6_midi *)((substream)->rmidi->private_data))
26 static int send_midi_async(struct usb_line6
*line6
, unsigned char *data
,
30 Pass data received via USB to MIDI.
32 void line6_midi_receive(struct usb_line6
*line6
, unsigned char *data
,
35 if (line6
->line6midi
->substream_receive
)
36 snd_rawmidi_receive(line6
->line6midi
->substream_receive
,
41 Read data from MIDI buffer and transmit them via USB.
43 static void line6_midi_transmit(struct snd_rawmidi_substream
*substream
)
45 struct usb_line6
*line6
=
46 line6_rawmidi_substream_midi(substream
)->line6
;
47 struct snd_line6_midi
*line6midi
= line6
->line6midi
;
48 struct midi_buffer
*mb
= &line6midi
->midibuf_out
;
50 unsigned char chunk
[LINE6_FALLBACK_MAXPACKETSIZE
];
53 spin_lock_irqsave(&line6
->line6midi
->midi_transmit_lock
, flags
);
56 req
= min(line6_midibuf_bytes_free(mb
), line6
->max_packet_size
);
57 done
= snd_rawmidi_transmit_peek(substream
, chunk
, req
);
62 line6_midibuf_write(mb
, chunk
, done
);
63 snd_rawmidi_transmit_ack(substream
, done
);
67 done
= line6_midibuf_read(mb
, chunk
,
68 LINE6_FALLBACK_MAXPACKETSIZE
);
73 send_midi_async(line6
, chunk
, done
);
76 spin_unlock_irqrestore(&line6
->line6midi
->midi_transmit_lock
, flags
);
80 Notification of completion of MIDI transmission.
82 static void midi_sent(struct urb
*urb
)
87 struct usb_line6
*line6
= (struct usb_line6
*)urb
->context
;
90 kfree(urb
->transfer_buffer
);
93 if (status
== -ESHUTDOWN
)
96 spin_lock_irqsave(&line6
->line6midi
->send_urb_lock
, flags
);
97 num
= --line6
->line6midi
->num_active_send_urbs
;
100 line6_midi_transmit(line6
->line6midi
->substream_transmit
);
101 num
= line6
->line6midi
->num_active_send_urbs
;
105 wake_up(&line6
->line6midi
->send_wait
);
107 spin_unlock_irqrestore(&line6
->line6midi
->send_urb_lock
, flags
);
111 Send an asynchronous MIDI message.
112 Assumes that line6->line6midi->send_urb_lock is held
113 (i.e., this function is serialized).
115 static int send_midi_async(struct usb_line6
*line6
, unsigned char *data
,
120 unsigned char *transfer_buffer
;
122 urb
= usb_alloc_urb(0, GFP_ATOMIC
);
125 dev_err(line6
->ifcdev
, "Out of memory\n");
129 transfer_buffer
= kmemdup(data
, length
, GFP_ATOMIC
);
131 if (transfer_buffer
== NULL
) {
133 dev_err(line6
->ifcdev
, "Out of memory\n");
137 usb_fill_int_urb(urb
, line6
->usbdev
,
138 usb_sndbulkpipe(line6
->usbdev
,
139 line6
->ep_control_write
),
140 transfer_buffer
, length
, midi_sent
, line6
,
142 urb
->actual_length
= 0;
143 retval
= usb_submit_urb(urb
, GFP_ATOMIC
);
146 dev_err(line6
->ifcdev
, "usb_submit_urb failed\n");
151 ++line6
->line6midi
->num_active_send_urbs
;
155 static int line6_midi_output_open(struct snd_rawmidi_substream
*substream
)
160 static int line6_midi_output_close(struct snd_rawmidi_substream
*substream
)
165 static void line6_midi_output_trigger(struct snd_rawmidi_substream
*substream
,
169 struct usb_line6
*line6
=
170 line6_rawmidi_substream_midi(substream
)->line6
;
172 line6
->line6midi
->substream_transmit
= substream
;
173 spin_lock_irqsave(&line6
->line6midi
->send_urb_lock
, flags
);
175 if (line6
->line6midi
->num_active_send_urbs
== 0)
176 line6_midi_transmit(substream
);
178 spin_unlock_irqrestore(&line6
->line6midi
->send_urb_lock
, flags
);
181 static void line6_midi_output_drain(struct snd_rawmidi_substream
*substream
)
183 struct usb_line6
*line6
=
184 line6_rawmidi_substream_midi(substream
)->line6
;
185 struct snd_line6_midi
*midi
= line6
->line6midi
;
186 wait_event_interruptible(midi
->send_wait
,
187 midi
->num_active_send_urbs
== 0);
190 static int line6_midi_input_open(struct snd_rawmidi_substream
*substream
)
195 static int line6_midi_input_close(struct snd_rawmidi_substream
*substream
)
200 static void line6_midi_input_trigger(struct snd_rawmidi_substream
*substream
,
203 struct usb_line6
*line6
=
204 line6_rawmidi_substream_midi(substream
)->line6
;
207 line6
->line6midi
->substream_receive
= substream
;
209 line6
->line6midi
->substream_receive
= NULL
;
212 static struct snd_rawmidi_ops line6_midi_output_ops
= {
213 .open
= line6_midi_output_open
,
214 .close
= line6_midi_output_close
,
215 .trigger
= line6_midi_output_trigger
,
216 .drain
= line6_midi_output_drain
,
219 static struct snd_rawmidi_ops line6_midi_input_ops
= {
220 .open
= line6_midi_input_open
,
221 .close
= line6_midi_input_close
,
222 .trigger
= line6_midi_input_trigger
,
226 Cleanup the Line6 MIDI device.
228 static void line6_cleanup_midi(struct snd_rawmidi
*rmidi
)
232 /* Create a MIDI device */
233 static int snd_line6_new_midi(struct snd_line6_midi
*line6midi
)
235 struct snd_rawmidi
*rmidi
;
238 err
= snd_rawmidi_new(line6midi
->line6
->card
, "Line6 MIDI", 0, 1, 1,
243 rmidi
->private_data
= line6midi
;
244 rmidi
->private_free
= line6_cleanup_midi
;
245 strcpy(rmidi
->id
, line6midi
->line6
->properties
->id
);
246 strcpy(rmidi
->name
, line6midi
->line6
->properties
->name
);
249 SNDRV_RAWMIDI_INFO_OUTPUT
|
250 SNDRV_RAWMIDI_INFO_INPUT
| SNDRV_RAWMIDI_INFO_DUPLEX
;
252 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
253 &line6_midi_output_ops
);
254 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
255 &line6_midi_input_ops
);
259 /* MIDI device destructor */
260 static int snd_line6_midi_free(struct snd_device
*device
)
262 struct snd_line6_midi
*line6midi
= device
->device_data
;
263 line6_midibuf_destroy(&line6midi
->midibuf_in
);
264 line6_midibuf_destroy(&line6midi
->midibuf_out
);
269 Initialize the Line6 MIDI subsystem.
271 int line6_init_midi(struct usb_line6
*line6
)
273 static struct snd_device_ops midi_ops
= {
274 .dev_free
= snd_line6_midi_free
,
278 struct snd_line6_midi
*line6midi
;
280 if (!(line6
->properties
->capabilities
& LINE6_BIT_CONTROL
)) {
281 /* skip MIDI initialization and report success */
285 line6midi
= kzalloc(sizeof(struct snd_line6_midi
), GFP_KERNEL
);
287 if (line6midi
== NULL
)
290 err
= line6_midibuf_init(&line6midi
->midibuf_in
, MIDI_BUFFER_SIZE
, 0);
296 err
= line6_midibuf_init(&line6midi
->midibuf_out
, MIDI_BUFFER_SIZE
, 1);
298 kfree(line6midi
->midibuf_in
.buf
);
303 line6midi
->line6
= line6
;
304 line6
->line6midi
= line6midi
;
306 err
= snd_device_new(line6
->card
, SNDRV_DEV_RAWMIDI
, line6midi
,
311 snd_card_set_dev(line6
->card
, line6
->ifcdev
);
313 err
= snd_line6_new_midi(line6midi
);
317 init_waitqueue_head(&line6midi
->send_wait
);
318 spin_lock_init(&line6midi
->send_urb_lock
);
319 spin_lock_init(&line6midi
->midi_transmit_lock
);