staging: line6: drop midi_mask_transmit
[linux-2.6-microblaze.git] / drivers / staging / line6 / midi.c
1 /*
2  * Line6 Linux USB driver - 0.9.1beta
3  *
4  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5  *
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.
9  *
10  */
11
12 #include <linux/slab.h>
13 #include <linux/usb.h>
14 #include <sound/core.h>
15 #include <sound/rawmidi.h>
16
17 #include "audio.h"
18 #include "driver.h"
19 #include "midi.h"
20 #include "pod.h"
21 #include "usbdefs.h"
22
23 #define line6_rawmidi_substream_midi(substream) \
24         ((struct snd_line6_midi *)((substream)->rmidi->private_data))
25
26 static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
27                            int length);
28
29 /*
30         Pass data received via USB to MIDI.
31 */
32 void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
33                         int length)
34 {
35         if (line6->line6midi->substream_receive)
36                 snd_rawmidi_receive(line6->line6midi->substream_receive,
37                                     data, length);
38 }
39
40 /*
41         Read data from MIDI buffer and transmit them via USB.
42 */
43 static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
44 {
45         struct usb_line6 *line6 =
46             line6_rawmidi_substream_midi(substream)->line6;
47         struct snd_line6_midi *line6midi = line6->line6midi;
48         struct MidiBuffer *mb = &line6midi->midibuf_out;
49         unsigned long flags;
50         unsigned char chunk[line6->max_packet_size];
51         int req, done;
52
53         spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);
54
55         for (;;) {
56                 req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
57                 done = snd_rawmidi_transmit_peek(substream, chunk, req);
58
59                 if (done == 0)
60                         break;
61
62                 line6_midibuf_write(mb, chunk, done);
63                 snd_rawmidi_transmit_ack(substream, done);
64         }
65
66         for (;;) {
67                 done = line6_midibuf_read(mb, chunk, line6->max_packet_size);
68
69                 if (done == 0)
70                         break;
71
72                 send_midi_async(line6, chunk, done);
73         }
74
75         spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags);
76 }
77
78 /*
79         Notification of completion of MIDI transmission.
80 */
81 static void midi_sent(struct urb *urb)
82 {
83         unsigned long flags;
84         int status;
85         int num;
86         struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
87
88         status = urb->status;
89         kfree(urb->transfer_buffer);
90         usb_free_urb(urb);
91
92         if (status == -ESHUTDOWN)
93                 return;
94
95         spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
96         num = --line6->line6midi->num_active_send_urbs;
97
98         if (num == 0) {
99                 line6_midi_transmit(line6->line6midi->substream_transmit);
100                 num = line6->line6midi->num_active_send_urbs;
101         }
102
103         if (num == 0)
104                 wake_up(&line6->line6midi->send_wait);
105
106         spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
107 }
108
109 /*
110         Send an asynchronous MIDI message.
111         Assumes that line6->line6midi->send_urb_lock is held
112         (i.e., this function is serialized).
113 */
114 static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
115                            int length)
116 {
117         struct urb *urb;
118         int retval;
119         unsigned char *transfer_buffer;
120
121         urb = usb_alloc_urb(0, GFP_ATOMIC);
122
123         if (urb == NULL) {
124                 dev_err(line6->ifcdev, "Out of memory\n");
125                 return -ENOMEM;
126         }
127
128         transfer_buffer = kmemdup(data, length, GFP_ATOMIC);
129
130         if (transfer_buffer == NULL) {
131                 usb_free_urb(urb);
132                 dev_err(line6->ifcdev, "Out of memory\n");
133                 return -ENOMEM;
134         }
135
136         usb_fill_int_urb(urb, line6->usbdev,
137                          usb_sndbulkpipe(line6->usbdev,
138                                          line6->ep_control_write),
139                          transfer_buffer, length, midi_sent, line6,
140                          line6->interval);
141         urb->actual_length = 0;
142         retval = usb_submit_urb(urb, GFP_ATOMIC);
143
144         if (retval < 0) {
145                 dev_err(line6->ifcdev, "usb_submit_urb failed\n");
146                 usb_free_urb(urb);
147                 return -EINVAL;
148         }
149
150         ++line6->line6midi->num_active_send_urbs;
151
152         switch (line6->usbdev->descriptor.idProduct) {
153         case LINE6_DEVID_BASSPODXT:
154         case LINE6_DEVID_BASSPODXTLIVE:
155         case LINE6_DEVID_BASSPODXTPRO:
156         case LINE6_DEVID_PODXT:
157         case LINE6_DEVID_PODXTLIVE:
158         case LINE6_DEVID_PODXTPRO:
159         case LINE6_DEVID_POCKETPOD:
160                 line6_pod_midi_postprocess((struct usb_line6_pod *)line6, data,
161                                            length);
162                 break;
163
164         case LINE6_DEVID_VARIAX:
165         case LINE6_DEVID_PODHD300:
166         case LINE6_DEVID_PODHD500:
167                 break;
168
169         default:
170                 MISSING_CASE;
171         }
172
173         return 0;
174 }
175
176 static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
177 {
178         return 0;
179 }
180
181 static int line6_midi_output_close(struct snd_rawmidi_substream *substream)
182 {
183         return 0;
184 }
185
186 static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream,
187                                       int up)
188 {
189         unsigned long flags;
190         struct usb_line6 *line6 =
191             line6_rawmidi_substream_midi(substream)->line6;
192
193         line6->line6midi->substream_transmit = substream;
194         spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
195
196         if (line6->line6midi->num_active_send_urbs == 0)
197                 line6_midi_transmit(substream);
198
199         spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
200 }
201
202 static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)
203 {
204         struct usb_line6 *line6 =
205             line6_rawmidi_substream_midi(substream)->line6;
206         struct snd_line6_midi *midi = line6->line6midi;
207         wait_event_interruptible(midi->send_wait,
208                                  midi->num_active_send_urbs == 0);
209 }
210
211 static int line6_midi_input_open(struct snd_rawmidi_substream *substream)
212 {
213         return 0;
214 }
215
216 static int line6_midi_input_close(struct snd_rawmidi_substream *substream)
217 {
218         return 0;
219 }
220
221 static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
222                                      int up)
223 {
224         struct usb_line6 *line6 =
225             line6_rawmidi_substream_midi(substream)->line6;
226
227         if (up)
228                 line6->line6midi->substream_receive = substream;
229         else
230                 line6->line6midi->substream_receive = 0;
231 }
232
233 static struct snd_rawmidi_ops line6_midi_output_ops = {
234         .open = line6_midi_output_open,
235         .close = line6_midi_output_close,
236         .trigger = line6_midi_output_trigger,
237         .drain = line6_midi_output_drain,
238 };
239
240 static struct snd_rawmidi_ops line6_midi_input_ops = {
241         .open = line6_midi_input_open,
242         .close = line6_midi_input_close,
243         .trigger = line6_midi_input_trigger,
244 };
245
246 /*
247         Cleanup the Line6 MIDI device.
248 */
249 static void line6_cleanup_midi(struct snd_rawmidi *rmidi)
250 {
251 }
252
253 /* Create a MIDI device */
254 static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
255 {
256         struct snd_rawmidi *rmidi;
257         int err;
258
259         err = snd_rawmidi_new(line6midi->line6->card, "Line6 MIDI", 0, 1, 1,
260                               &rmidi);
261         if (err < 0)
262                 return err;
263
264         rmidi->private_data = line6midi;
265         rmidi->private_free = line6_cleanup_midi;
266         strcpy(rmidi->id, line6midi->line6->properties->id);
267         strcpy(rmidi->name, line6midi->line6->properties->name);
268
269         rmidi->info_flags =
270             SNDRV_RAWMIDI_INFO_OUTPUT |
271             SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
272
273         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
274                             &line6_midi_output_ops);
275         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
276                             &line6_midi_input_ops);
277         return 0;
278 }
279
280 /* MIDI device destructor */
281 static int snd_line6_midi_free(struct snd_device *device)
282 {
283         struct snd_line6_midi *line6midi = device->device_data;
284         line6_midibuf_destroy(&line6midi->midibuf_in);
285         line6_midibuf_destroy(&line6midi->midibuf_out);
286         return 0;
287 }
288
289 /*
290         Initialize the Line6 MIDI subsystem.
291 */
292 int line6_init_midi(struct usb_line6 *line6)
293 {
294         static struct snd_device_ops midi_ops = {
295                 .dev_free = snd_line6_midi_free,
296         };
297
298         int err;
299         struct snd_line6_midi *line6midi;
300
301         if (!(line6->properties->capabilities & LINE6_BIT_CONTROL)) {
302                 /* skip MIDI initialization and report success */
303                 return 0;
304         }
305
306         line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL);
307
308         if (line6midi == NULL)
309                 return -ENOMEM;
310
311         err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
312         if (err < 0) {
313                 kfree(line6midi);
314                 return err;
315         }
316
317         err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
318         if (err < 0) {
319                 kfree(line6midi->midibuf_in.buf);
320                 kfree(line6midi);
321                 return err;
322         }
323
324         line6midi->line6 = line6;
325         line6->line6midi = line6midi;
326
327         err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi,
328                              &midi_ops);
329         if (err < 0)
330                 return err;
331
332         snd_card_set_dev(line6->card, line6->ifcdev);
333
334         err = snd_line6_new_midi(line6midi);
335         if (err < 0)
336                 return err;
337
338         init_waitqueue_head(&line6midi->send_wait);
339         spin_lock_init(&line6midi->send_urb_lock);
340         spin_lock_init(&line6midi->midi_transmit_lock);
341         return 0;
342 }