161864d84STakashi Iwai /* 261864d84STakashi Iwai * Line6 Linux USB driver - 0.9.1beta 361864d84STakashi Iwai * 461864d84STakashi Iwai * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 561864d84STakashi Iwai * 661864d84STakashi Iwai * This program is free software; you can redistribute it and/or 761864d84STakashi Iwai * modify it under the terms of the GNU General Public License as 861864d84STakashi Iwai * published by the Free Software Foundation, version 2. 961864d84STakashi Iwai * 1061864d84STakashi Iwai */ 1161864d84STakashi Iwai 1261864d84STakashi Iwai #include <linux/slab.h> 1361864d84STakashi Iwai #include <linux/usb.h> 14ccddbe4aSTakashi Iwai #include <linux/export.h> 1561864d84STakashi Iwai #include <sound/core.h> 1661864d84STakashi Iwai #include <sound/rawmidi.h> 1761864d84STakashi Iwai 1861864d84STakashi Iwai #include "audio.h" 1961864d84STakashi Iwai #include "driver.h" 2061864d84STakashi Iwai #include "midi.h" 2161864d84STakashi Iwai #include "usbdefs.h" 2261864d84STakashi Iwai 2361864d84STakashi Iwai #define line6_rawmidi_substream_midi(substream) \ 2461864d84STakashi Iwai ((struct snd_line6_midi *)((substream)->rmidi->private_data)) 2561864d84STakashi Iwai 2661864d84STakashi Iwai static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 2761864d84STakashi Iwai int length); 2861864d84STakashi Iwai 2961864d84STakashi Iwai /* 3061864d84STakashi Iwai Pass data received via USB to MIDI. 3161864d84STakashi Iwai */ 3261864d84STakashi Iwai void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, 3361864d84STakashi Iwai int length) 3461864d84STakashi Iwai { 3561864d84STakashi Iwai if (line6->line6midi->substream_receive) 3661864d84STakashi Iwai snd_rawmidi_receive(line6->line6midi->substream_receive, 3761864d84STakashi Iwai data, length); 3861864d84STakashi Iwai } 3961864d84STakashi Iwai 4061864d84STakashi Iwai /* 4161864d84STakashi Iwai Read data from MIDI buffer and transmit them via USB. 4261864d84STakashi Iwai */ 4361864d84STakashi Iwai static void line6_midi_transmit(struct snd_rawmidi_substream *substream) 4461864d84STakashi Iwai { 4561864d84STakashi Iwai struct usb_line6 *line6 = 4661864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 4761864d84STakashi Iwai struct snd_line6_midi *line6midi = line6->line6midi; 4861864d84STakashi Iwai struct midi_buffer *mb = &line6midi->midibuf_out; 4961864d84STakashi Iwai unsigned long flags; 5061864d84STakashi Iwai unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE]; 5161864d84STakashi Iwai int req, done; 5261864d84STakashi Iwai 5361864d84STakashi Iwai spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags); 5461864d84STakashi Iwai 5561864d84STakashi Iwai for (;;) { 5661864d84STakashi Iwai req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size); 5761864d84STakashi Iwai done = snd_rawmidi_transmit_peek(substream, chunk, req); 5861864d84STakashi Iwai 5961864d84STakashi Iwai if (done == 0) 6061864d84STakashi Iwai break; 6161864d84STakashi Iwai 6261864d84STakashi Iwai line6_midibuf_write(mb, chunk, done); 6361864d84STakashi Iwai snd_rawmidi_transmit_ack(substream, done); 6461864d84STakashi Iwai } 6561864d84STakashi Iwai 6661864d84STakashi Iwai for (;;) { 6761864d84STakashi Iwai done = line6_midibuf_read(mb, chunk, 6861864d84STakashi Iwai LINE6_FALLBACK_MAXPACKETSIZE); 6961864d84STakashi Iwai 7061864d84STakashi Iwai if (done == 0) 7161864d84STakashi Iwai break; 7261864d84STakashi Iwai 7361864d84STakashi Iwai send_midi_async(line6, chunk, done); 7461864d84STakashi Iwai } 7561864d84STakashi Iwai 7661864d84STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags); 7761864d84STakashi Iwai } 7861864d84STakashi Iwai 7961864d84STakashi Iwai /* 8061864d84STakashi Iwai Notification of completion of MIDI transmission. 8161864d84STakashi Iwai */ 8261864d84STakashi Iwai static void midi_sent(struct urb *urb) 8361864d84STakashi Iwai { 8461864d84STakashi Iwai unsigned long flags; 8561864d84STakashi Iwai int status; 8661864d84STakashi Iwai int num; 8761864d84STakashi Iwai struct usb_line6 *line6 = (struct usb_line6 *)urb->context; 8861864d84STakashi Iwai 8961864d84STakashi Iwai status = urb->status; 9061864d84STakashi Iwai kfree(urb->transfer_buffer); 9161864d84STakashi Iwai usb_free_urb(urb); 9261864d84STakashi Iwai 9361864d84STakashi Iwai if (status == -ESHUTDOWN) 9461864d84STakashi Iwai return; 9561864d84STakashi Iwai 9661864d84STakashi Iwai spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); 9761864d84STakashi Iwai num = --line6->line6midi->num_active_send_urbs; 9861864d84STakashi Iwai 9961864d84STakashi Iwai if (num == 0) { 10061864d84STakashi Iwai line6_midi_transmit(line6->line6midi->substream_transmit); 10161864d84STakashi Iwai num = line6->line6midi->num_active_send_urbs; 10261864d84STakashi Iwai } 10361864d84STakashi Iwai 10461864d84STakashi Iwai if (num == 0) 10561864d84STakashi Iwai wake_up(&line6->line6midi->send_wait); 10661864d84STakashi Iwai 10761864d84STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags); 10861864d84STakashi Iwai } 10961864d84STakashi Iwai 11061864d84STakashi Iwai /* 11161864d84STakashi Iwai Send an asynchronous MIDI message. 11261864d84STakashi Iwai Assumes that line6->line6midi->send_urb_lock is held 11361864d84STakashi Iwai (i.e., this function is serialized). 11461864d84STakashi Iwai */ 11561864d84STakashi Iwai static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 11661864d84STakashi Iwai int length) 11761864d84STakashi Iwai { 11861864d84STakashi Iwai struct urb *urb; 11961864d84STakashi Iwai int retval; 12061864d84STakashi Iwai unsigned char *transfer_buffer; 12161864d84STakashi Iwai 12261864d84STakashi Iwai urb = usb_alloc_urb(0, GFP_ATOMIC); 12361864d84STakashi Iwai 12461864d84STakashi Iwai if (urb == NULL) { 12561864d84STakashi Iwai dev_err(line6->ifcdev, "Out of memory\n"); 12661864d84STakashi Iwai return -ENOMEM; 12761864d84STakashi Iwai } 12861864d84STakashi Iwai 12961864d84STakashi Iwai transfer_buffer = kmemdup(data, length, GFP_ATOMIC); 13061864d84STakashi Iwai 13161864d84STakashi Iwai if (transfer_buffer == NULL) { 13261864d84STakashi Iwai usb_free_urb(urb); 13361864d84STakashi Iwai dev_err(line6->ifcdev, "Out of memory\n"); 13461864d84STakashi Iwai return -ENOMEM; 13561864d84STakashi Iwai } 13661864d84STakashi Iwai 13761864d84STakashi Iwai usb_fill_int_urb(urb, line6->usbdev, 13861864d84STakashi Iwai usb_sndbulkpipe(line6->usbdev, 13961864d84STakashi Iwai line6->properties->ep_ctrl_w), 14061864d84STakashi Iwai transfer_buffer, length, midi_sent, line6, 14161864d84STakashi Iwai line6->interval); 14261864d84STakashi Iwai urb->actual_length = 0; 14361864d84STakashi Iwai retval = usb_submit_urb(urb, GFP_ATOMIC); 14461864d84STakashi Iwai 14561864d84STakashi Iwai if (retval < 0) { 14661864d84STakashi Iwai dev_err(line6->ifcdev, "usb_submit_urb failed\n"); 14761864d84STakashi Iwai usb_free_urb(urb); 14861864d84STakashi Iwai return retval; 14961864d84STakashi Iwai } 15061864d84STakashi Iwai 15161864d84STakashi Iwai ++line6->line6midi->num_active_send_urbs; 15261864d84STakashi Iwai return 0; 15361864d84STakashi Iwai } 15461864d84STakashi Iwai 15561864d84STakashi Iwai static int line6_midi_output_open(struct snd_rawmidi_substream *substream) 15661864d84STakashi Iwai { 15761864d84STakashi Iwai return 0; 15861864d84STakashi Iwai } 15961864d84STakashi Iwai 16061864d84STakashi Iwai static int line6_midi_output_close(struct snd_rawmidi_substream *substream) 16161864d84STakashi Iwai { 16261864d84STakashi Iwai return 0; 16361864d84STakashi Iwai } 16461864d84STakashi Iwai 16561864d84STakashi Iwai static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, 16661864d84STakashi Iwai int up) 16761864d84STakashi Iwai { 16861864d84STakashi Iwai unsigned long flags; 16961864d84STakashi Iwai struct usb_line6 *line6 = 17061864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 17161864d84STakashi Iwai 17261864d84STakashi Iwai line6->line6midi->substream_transmit = substream; 17361864d84STakashi Iwai spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); 17461864d84STakashi Iwai 17561864d84STakashi Iwai if (line6->line6midi->num_active_send_urbs == 0) 17661864d84STakashi Iwai line6_midi_transmit(substream); 17761864d84STakashi Iwai 17861864d84STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags); 17961864d84STakashi Iwai } 18061864d84STakashi Iwai 18161864d84STakashi Iwai static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) 18261864d84STakashi Iwai { 18361864d84STakashi Iwai struct usb_line6 *line6 = 18461864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 18561864d84STakashi Iwai struct snd_line6_midi *midi = line6->line6midi; 18661864d84STakashi Iwai 18761864d84STakashi Iwai wait_event_interruptible(midi->send_wait, 18861864d84STakashi Iwai midi->num_active_send_urbs == 0); 18961864d84STakashi Iwai } 19061864d84STakashi Iwai 19161864d84STakashi Iwai static int line6_midi_input_open(struct snd_rawmidi_substream *substream) 19261864d84STakashi Iwai { 19361864d84STakashi Iwai return 0; 19461864d84STakashi Iwai } 19561864d84STakashi Iwai 19661864d84STakashi Iwai static int line6_midi_input_close(struct snd_rawmidi_substream *substream) 19761864d84STakashi Iwai { 19861864d84STakashi Iwai return 0; 19961864d84STakashi Iwai } 20061864d84STakashi Iwai 20161864d84STakashi Iwai static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, 20261864d84STakashi Iwai int up) 20361864d84STakashi Iwai { 20461864d84STakashi Iwai struct usb_line6 *line6 = 20561864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 20661864d84STakashi Iwai 20761864d84STakashi Iwai if (up) 20861864d84STakashi Iwai line6->line6midi->substream_receive = substream; 20961864d84STakashi Iwai else 21061864d84STakashi Iwai line6->line6midi->substream_receive = NULL; 21161864d84STakashi Iwai } 21261864d84STakashi Iwai 21361864d84STakashi Iwai static struct snd_rawmidi_ops line6_midi_output_ops = { 21461864d84STakashi Iwai .open = line6_midi_output_open, 21561864d84STakashi Iwai .close = line6_midi_output_close, 21661864d84STakashi Iwai .trigger = line6_midi_output_trigger, 21761864d84STakashi Iwai .drain = line6_midi_output_drain, 21861864d84STakashi Iwai }; 21961864d84STakashi Iwai 22061864d84STakashi Iwai static struct snd_rawmidi_ops line6_midi_input_ops = { 22161864d84STakashi Iwai .open = line6_midi_input_open, 22261864d84STakashi Iwai .close = line6_midi_input_close, 22361864d84STakashi Iwai .trigger = line6_midi_input_trigger, 22461864d84STakashi Iwai }; 22561864d84STakashi Iwai 22661864d84STakashi Iwai /* Create a MIDI device */ 227*aaa68d2fSTakashi Iwai static int snd_line6_new_midi(struct usb_line6 *line6, 228*aaa68d2fSTakashi Iwai struct snd_rawmidi **rmidi_ret) 22961864d84STakashi Iwai { 23061864d84STakashi Iwai struct snd_rawmidi *rmidi; 23161864d84STakashi Iwai int err; 23261864d84STakashi Iwai 233*aaa68d2fSTakashi Iwai err = snd_rawmidi_new(line6->card, "Line6 MIDI", 0, 1, 1, rmidi_ret); 23461864d84STakashi Iwai if (err < 0) 23561864d84STakashi Iwai return err; 23661864d84STakashi Iwai 237*aaa68d2fSTakashi Iwai rmidi = *rmidi_ret; 238*aaa68d2fSTakashi Iwai strcpy(rmidi->id, line6->properties->id); 239*aaa68d2fSTakashi Iwai strcpy(rmidi->name, line6->properties->name); 24061864d84STakashi Iwai 24161864d84STakashi Iwai rmidi->info_flags = 24261864d84STakashi Iwai SNDRV_RAWMIDI_INFO_OUTPUT | 24361864d84STakashi Iwai SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 24461864d84STakashi Iwai 24561864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 24661864d84STakashi Iwai &line6_midi_output_ops); 24761864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 24861864d84STakashi Iwai &line6_midi_input_ops); 24961864d84STakashi Iwai return 0; 25061864d84STakashi Iwai } 25161864d84STakashi Iwai 25261864d84STakashi Iwai /* MIDI device destructor */ 253*aaa68d2fSTakashi Iwai static void snd_line6_midi_free(struct snd_rawmidi *rmidi) 25461864d84STakashi Iwai { 255*aaa68d2fSTakashi Iwai struct snd_line6_midi *line6midi = rmidi->private_data; 25661864d84STakashi Iwai 25761864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_in); 25861864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_out); 259*aaa68d2fSTakashi Iwai kfree(line6midi); 26061864d84STakashi Iwai } 26161864d84STakashi Iwai 26261864d84STakashi Iwai /* 26361864d84STakashi Iwai Initialize the Line6 MIDI subsystem. 26461864d84STakashi Iwai */ 26561864d84STakashi Iwai int line6_init_midi(struct usb_line6 *line6) 26661864d84STakashi Iwai { 26761864d84STakashi Iwai int err; 268*aaa68d2fSTakashi Iwai struct snd_rawmidi *rmidi; 26961864d84STakashi Iwai struct snd_line6_midi *line6midi; 27061864d84STakashi Iwai 27161864d84STakashi Iwai if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) { 27261864d84STakashi Iwai /* skip MIDI initialization and report success */ 27361864d84STakashi Iwai return 0; 27461864d84STakashi Iwai } 27561864d84STakashi Iwai 276*aaa68d2fSTakashi Iwai err = snd_line6_new_midi(line6, &rmidi); 277*aaa68d2fSTakashi Iwai if (err < 0) 278*aaa68d2fSTakashi Iwai return err; 27961864d84STakashi Iwai 280*aaa68d2fSTakashi Iwai line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); 281*aaa68d2fSTakashi Iwai if (!line6midi) 28261864d84STakashi Iwai return -ENOMEM; 28361864d84STakashi Iwai 284*aaa68d2fSTakashi Iwai rmidi->private_data = line6midi; 285*aaa68d2fSTakashi Iwai rmidi->private_free = snd_line6_midi_free; 28661864d84STakashi Iwai 28761864d84STakashi Iwai init_waitqueue_head(&line6midi->send_wait); 28861864d84STakashi Iwai spin_lock_init(&line6midi->send_urb_lock); 28961864d84STakashi Iwai spin_lock_init(&line6midi->midi_transmit_lock); 290*aaa68d2fSTakashi Iwai line6midi->line6 = line6; 291*aaa68d2fSTakashi Iwai 292*aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); 293*aaa68d2fSTakashi Iwai if (err < 0) 294*aaa68d2fSTakashi Iwai return err; 295*aaa68d2fSTakashi Iwai 296*aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); 297*aaa68d2fSTakashi Iwai if (err < 0) 298*aaa68d2fSTakashi Iwai return err; 299*aaa68d2fSTakashi Iwai 300*aaa68d2fSTakashi Iwai line6->line6midi = line6midi; 30161864d84STakashi Iwai return 0; 30261864d84STakashi Iwai } 303ccddbe4aSTakashi Iwai EXPORT_SYMBOL_GPL(line6_init_midi); 304