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 26static 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*/ 32void 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*/ 43static 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 midi_buffer *mb = &line6midi->midibuf_out; 49 unsigned long flags; 50 unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE]; 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, 68 LINE6_FALLBACK_MAXPACKETSIZE); 69 70 if (done == 0) 71 break; 72 73 send_midi_async(line6, chunk, done); 74 } 75 76 spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags); 77} 78 79/* 80 Notification of completion of MIDI transmission. 81*/ 82static void midi_sent(struct urb *urb) 83{ 84 unsigned long flags; 85 int status; 86 int num; 87 struct usb_line6 *line6 = (struct usb_line6 *)urb->context; 88 89 status = urb->status; 90 kfree(urb->transfer_buffer); 91 usb_free_urb(urb); 92 93 if (status == -ESHUTDOWN) 94 return; 95 96 spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); 97 num = --line6->line6midi->num_active_send_urbs; 98 99 if (num == 0) { 100 line6_midi_transmit(line6->line6midi->substream_transmit); 101 num = line6->line6midi->num_active_send_urbs; 102 } 103 104 if (num == 0) 105 wake_up(&line6->line6midi->send_wait); 106 107 spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags); 108} 109 110/* 111 Send an asynchronous MIDI message. 112 Assumes that line6->line6midi->send_urb_lock is held 113 (i.e., this function is serialized). 114*/ 115static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 116 int length) 117{ 118 struct urb *urb; 119 int retval; 120 unsigned char *transfer_buffer; 121 122 urb = usb_alloc_urb(0, GFP_ATOMIC); 123 124 if (urb == NULL) { 125 dev_err(line6->ifcdev, "Out of memory\n"); 126 return -ENOMEM; 127 } 128 129 transfer_buffer = kmemdup(data, length, GFP_ATOMIC); 130 131 if (transfer_buffer == NULL) { 132 usb_free_urb(urb); 133 dev_err(line6->ifcdev, "Out of memory\n"); 134 return -ENOMEM; 135 } 136 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, 141 line6->interval); 142 urb->actual_length = 0; 143 retval = usb_submit_urb(urb, GFP_ATOMIC); 144 145 if (retval < 0) { 146 dev_err(line6->ifcdev, "usb_submit_urb failed\n"); 147 usb_free_urb(urb); 148 return retval; 149 } 150 151 ++line6->line6midi->num_active_send_urbs; 152 return 0; 153} 154 155static int line6_midi_output_open(struct snd_rawmidi_substream *substream) 156{ 157 return 0; 158} 159 160static int line6_midi_output_close(struct snd_rawmidi_substream *substream) 161{ 162 return 0; 163} 164 165static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, 166 int up) 167{ 168 unsigned long flags; 169 struct usb_line6 *line6 = 170 line6_rawmidi_substream_midi(substream)->line6; 171 172 line6->line6midi->substream_transmit = substream; 173 spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); 174 175 if (line6->line6midi->num_active_send_urbs == 0) 176 line6_midi_transmit(substream); 177 178 spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags); 179} 180 181static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) 182{ 183 struct usb_line6 *line6 = 184 line6_rawmidi_substream_midi(substream)->line6; 185 struct snd_line6_midi *midi = line6->line6midi; 186 187 wait_event_interruptible(midi->send_wait, 188 midi->num_active_send_urbs == 0); 189} 190 191static int line6_midi_input_open(struct snd_rawmidi_substream *substream) 192{ 193 return 0; 194} 195 196static int line6_midi_input_close(struct snd_rawmidi_substream *substream) 197{ 198 return 0; 199} 200 201static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, 202 int up) 203{ 204 struct usb_line6 *line6 = 205 line6_rawmidi_substream_midi(substream)->line6; 206 207 if (up) 208 line6->line6midi->substream_receive = substream; 209 else 210 line6->line6midi->substream_receive = NULL; 211} 212 213static struct snd_rawmidi_ops line6_midi_output_ops = { 214 .open = line6_midi_output_open, 215 .close = line6_midi_output_close, 216 .trigger = line6_midi_output_trigger, 217 .drain = line6_midi_output_drain, 218}; 219 220static struct snd_rawmidi_ops line6_midi_input_ops = { 221 .open = line6_midi_input_open, 222 .close = line6_midi_input_close, 223 .trigger = line6_midi_input_trigger, 224}; 225 226/* 227 Cleanup the Line6 MIDI device. 228*/ 229static void line6_cleanup_midi(struct snd_rawmidi *rmidi) 230{ 231} 232 233/* Create a MIDI device */ 234static int snd_line6_new_midi(struct snd_line6_midi *line6midi) 235{ 236 struct snd_rawmidi *rmidi; 237 int err; 238 239 err = snd_rawmidi_new(line6midi->line6->card, "Line6 MIDI", 0, 1, 1, 240 &rmidi); 241 if (err < 0) 242 return err; 243 244 rmidi->private_data = line6midi; 245 rmidi->private_free = line6_cleanup_midi; 246 strcpy(rmidi->id, line6midi->line6->properties->id); 247 strcpy(rmidi->name, line6midi->line6->properties->name); 248 249 rmidi->info_flags = 250 SNDRV_RAWMIDI_INFO_OUTPUT | 251 SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 252 253 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 254 &line6_midi_output_ops); 255 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 256 &line6_midi_input_ops); 257 return 0; 258} 259 260/* MIDI device destructor */ 261static int snd_line6_midi_free(struct snd_device *device) 262{ 263 struct snd_line6_midi *line6midi = device->device_data; 264 265 line6_midibuf_destroy(&line6midi->midibuf_in); 266 line6_midibuf_destroy(&line6midi->midibuf_out); 267 return 0; 268} 269 270/* 271 Initialize the Line6 MIDI subsystem. 272*/ 273int line6_init_midi(struct usb_line6 *line6) 274{ 275 static struct snd_device_ops midi_ops = { 276 .dev_free = snd_line6_midi_free, 277 }; 278 279 int err; 280 struct snd_line6_midi *line6midi; 281 282 if (!(line6->properties->capabilities & LINE6_BIT_CONTROL)) { 283 /* skip MIDI initialization and report success */ 284 return 0; 285 } 286 287 line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); 288 289 if (line6midi == NULL) 290 return -ENOMEM; 291 292 err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); 293 if (err < 0) { 294 kfree(line6midi); 295 return err; 296 } 297 298 err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); 299 if (err < 0) { 300 kfree(line6midi->midibuf_in.buf); 301 kfree(line6midi); 302 return err; 303 } 304 305 line6midi->line6 = line6; 306 line6->line6midi = line6midi; 307 308 err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi, 309 &midi_ops); 310 if (err < 0) 311 return err; 312 313 err = snd_line6_new_midi(line6midi); 314 if (err < 0) 315 return err; 316 317 init_waitqueue_head(&line6midi->send_wait); 318 spin_lock_init(&line6midi->send_urb_lock); 319 spin_lock_init(&line6midi->midi_transmit_lock); 320 return 0; 321} 322