161864d84STakashi Iwai /* 2c078a4aaSChris Rorvick * Line 6 Linux USB driver 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 "driver.h" 1961864d84STakashi Iwai #include "midi.h" 2061864d84STakashi Iwai 2161864d84STakashi Iwai #define line6_rawmidi_substream_midi(substream) \ 2261864d84STakashi Iwai ((struct snd_line6_midi *)((substream)->rmidi->private_data)) 2361864d84STakashi Iwai 2461864d84STakashi Iwai static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 2561864d84STakashi Iwai int length); 2661864d84STakashi Iwai 2761864d84STakashi Iwai /* 2861864d84STakashi Iwai Pass data received via USB to MIDI. 2961864d84STakashi Iwai */ 3061864d84STakashi Iwai void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, 3161864d84STakashi Iwai int length) 3261864d84STakashi Iwai { 3361864d84STakashi Iwai if (line6->line6midi->substream_receive) 3461864d84STakashi Iwai snd_rawmidi_receive(line6->line6midi->substream_receive, 3561864d84STakashi Iwai data, length); 3661864d84STakashi Iwai } 3761864d84STakashi Iwai 3861864d84STakashi Iwai /* 3961864d84STakashi Iwai Read data from MIDI buffer and transmit them via USB. 4061864d84STakashi Iwai */ 4161864d84STakashi Iwai static void line6_midi_transmit(struct snd_rawmidi_substream *substream) 4261864d84STakashi Iwai { 4361864d84STakashi Iwai struct usb_line6 *line6 = 4461864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 4561864d84STakashi Iwai struct snd_line6_midi *line6midi = line6->line6midi; 4661864d84STakashi Iwai struct midi_buffer *mb = &line6midi->midibuf_out; 4761864d84STakashi Iwai unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE]; 4861864d84STakashi Iwai int req, done; 4961864d84STakashi Iwai 5061864d84STakashi Iwai for (;;) { 5161864d84STakashi Iwai req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size); 5261864d84STakashi Iwai done = snd_rawmidi_transmit_peek(substream, chunk, req); 5361864d84STakashi Iwai 5461864d84STakashi Iwai if (done == 0) 5561864d84STakashi Iwai break; 5661864d84STakashi Iwai 5761864d84STakashi Iwai line6_midibuf_write(mb, chunk, done); 5861864d84STakashi Iwai snd_rawmidi_transmit_ack(substream, done); 5961864d84STakashi Iwai } 6061864d84STakashi Iwai 6161864d84STakashi Iwai for (;;) { 6261864d84STakashi Iwai done = line6_midibuf_read(mb, chunk, 6361864d84STakashi Iwai LINE6_FALLBACK_MAXPACKETSIZE); 6461864d84STakashi Iwai 6561864d84STakashi Iwai if (done == 0) 6661864d84STakashi Iwai break; 6761864d84STakashi Iwai 6861864d84STakashi Iwai send_midi_async(line6, chunk, done); 6961864d84STakashi Iwai } 7061864d84STakashi Iwai } 7161864d84STakashi Iwai 7261864d84STakashi Iwai /* 7361864d84STakashi Iwai Notification of completion of MIDI transmission. 7461864d84STakashi Iwai */ 7561864d84STakashi Iwai static void midi_sent(struct urb *urb) 7661864d84STakashi Iwai { 7761864d84STakashi Iwai unsigned long flags; 7861864d84STakashi Iwai int status; 7961864d84STakashi Iwai int num; 8061864d84STakashi Iwai struct usb_line6 *line6 = (struct usb_line6 *)urb->context; 8161864d84STakashi Iwai 8261864d84STakashi Iwai status = urb->status; 8361864d84STakashi Iwai kfree(urb->transfer_buffer); 8461864d84STakashi Iwai usb_free_urb(urb); 8561864d84STakashi Iwai 8661864d84STakashi Iwai if (status == -ESHUTDOWN) 8761864d84STakashi Iwai return; 8861864d84STakashi Iwai 89bc518ba4STakashi Iwai spin_lock_irqsave(&line6->line6midi->lock, flags); 9061864d84STakashi Iwai num = --line6->line6midi->num_active_send_urbs; 9161864d84STakashi Iwai 9261864d84STakashi Iwai if (num == 0) { 9361864d84STakashi Iwai line6_midi_transmit(line6->line6midi->substream_transmit); 9461864d84STakashi Iwai num = line6->line6midi->num_active_send_urbs; 9561864d84STakashi Iwai } 9661864d84STakashi Iwai 9761864d84STakashi Iwai if (num == 0) 9861864d84STakashi Iwai wake_up(&line6->line6midi->send_wait); 9961864d84STakashi Iwai 100bc518ba4STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->lock, flags); 10161864d84STakashi Iwai } 10261864d84STakashi Iwai 10361864d84STakashi Iwai /* 10461864d84STakashi Iwai Send an asynchronous MIDI message. 105bc518ba4STakashi Iwai Assumes that line6->line6midi->lock is held 10661864d84STakashi Iwai (i.e., this function is serialized). 10761864d84STakashi Iwai */ 10861864d84STakashi Iwai static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 10961864d84STakashi Iwai int length) 11061864d84STakashi Iwai { 11161864d84STakashi Iwai struct urb *urb; 11261864d84STakashi Iwai int retval; 11361864d84STakashi Iwai unsigned char *transfer_buffer; 11461864d84STakashi Iwai 11561864d84STakashi Iwai urb = usb_alloc_urb(0, GFP_ATOMIC); 11661864d84STakashi Iwai 117a019f5e8STakashi Iwai if (urb == NULL) 11861864d84STakashi Iwai return -ENOMEM; 11961864d84STakashi Iwai 12061864d84STakashi Iwai transfer_buffer = kmemdup(data, length, GFP_ATOMIC); 12161864d84STakashi Iwai 12261864d84STakashi Iwai if (transfer_buffer == NULL) { 12361864d84STakashi Iwai usb_free_urb(urb); 12461864d84STakashi Iwai return -ENOMEM; 12561864d84STakashi Iwai } 12661864d84STakashi Iwai 12761864d84STakashi Iwai usb_fill_int_urb(urb, line6->usbdev, 12861864d84STakashi Iwai usb_sndbulkpipe(line6->usbdev, 12961864d84STakashi Iwai line6->properties->ep_ctrl_w), 13061864d84STakashi Iwai transfer_buffer, length, midi_sent, line6, 13161864d84STakashi Iwai line6->interval); 13261864d84STakashi Iwai urb->actual_length = 0; 13361864d84STakashi Iwai retval = usb_submit_urb(urb, GFP_ATOMIC); 13461864d84STakashi Iwai 13561864d84STakashi Iwai if (retval < 0) { 13661864d84STakashi Iwai dev_err(line6->ifcdev, "usb_submit_urb failed\n"); 13761864d84STakashi Iwai usb_free_urb(urb); 13861864d84STakashi Iwai return retval; 13961864d84STakashi Iwai } 14061864d84STakashi Iwai 14161864d84STakashi Iwai ++line6->line6midi->num_active_send_urbs; 14261864d84STakashi Iwai return 0; 14361864d84STakashi Iwai } 14461864d84STakashi Iwai 14561864d84STakashi Iwai static int line6_midi_output_open(struct snd_rawmidi_substream *substream) 14661864d84STakashi Iwai { 14761864d84STakashi Iwai return 0; 14861864d84STakashi Iwai } 14961864d84STakashi Iwai 15061864d84STakashi Iwai static int line6_midi_output_close(struct snd_rawmidi_substream *substream) 15161864d84STakashi Iwai { 15261864d84STakashi Iwai return 0; 15361864d84STakashi Iwai } 15461864d84STakashi Iwai 15561864d84STakashi Iwai static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, 15661864d84STakashi Iwai int up) 15761864d84STakashi Iwai { 15861864d84STakashi Iwai unsigned long flags; 15961864d84STakashi Iwai struct usb_line6 *line6 = 16061864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 16161864d84STakashi Iwai 16261864d84STakashi Iwai line6->line6midi->substream_transmit = substream; 163bc518ba4STakashi Iwai spin_lock_irqsave(&line6->line6midi->lock, flags); 16461864d84STakashi Iwai 16561864d84STakashi Iwai if (line6->line6midi->num_active_send_urbs == 0) 16661864d84STakashi Iwai line6_midi_transmit(substream); 16761864d84STakashi Iwai 168bc518ba4STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->lock, flags); 16961864d84STakashi Iwai } 17061864d84STakashi Iwai 17161864d84STakashi Iwai static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) 17261864d84STakashi Iwai { 17361864d84STakashi Iwai struct usb_line6 *line6 = 17461864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 17561864d84STakashi Iwai struct snd_line6_midi *midi = line6->line6midi; 17661864d84STakashi Iwai 17761864d84STakashi Iwai wait_event_interruptible(midi->send_wait, 17861864d84STakashi Iwai midi->num_active_send_urbs == 0); 17961864d84STakashi Iwai } 18061864d84STakashi Iwai 18161864d84STakashi Iwai static int line6_midi_input_open(struct snd_rawmidi_substream *substream) 18261864d84STakashi Iwai { 18361864d84STakashi Iwai return 0; 18461864d84STakashi Iwai } 18561864d84STakashi Iwai 18661864d84STakashi Iwai static int line6_midi_input_close(struct snd_rawmidi_substream *substream) 18761864d84STakashi Iwai { 18861864d84STakashi Iwai return 0; 18961864d84STakashi Iwai } 19061864d84STakashi Iwai 19161864d84STakashi Iwai static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, 19261864d84STakashi Iwai int up) 19361864d84STakashi Iwai { 19461864d84STakashi Iwai struct usb_line6 *line6 = 19561864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 19661864d84STakashi Iwai 19761864d84STakashi Iwai if (up) 19861864d84STakashi Iwai line6->line6midi->substream_receive = substream; 19961864d84STakashi Iwai else 20061864d84STakashi Iwai line6->line6midi->substream_receive = NULL; 20161864d84STakashi Iwai } 20261864d84STakashi Iwai 203*f43e5407STakashi Iwai static const struct snd_rawmidi_ops line6_midi_output_ops = { 20461864d84STakashi Iwai .open = line6_midi_output_open, 20561864d84STakashi Iwai .close = line6_midi_output_close, 20661864d84STakashi Iwai .trigger = line6_midi_output_trigger, 20761864d84STakashi Iwai .drain = line6_midi_output_drain, 20861864d84STakashi Iwai }; 20961864d84STakashi Iwai 210*f43e5407STakashi Iwai static const struct snd_rawmidi_ops line6_midi_input_ops = { 21161864d84STakashi Iwai .open = line6_midi_input_open, 21261864d84STakashi Iwai .close = line6_midi_input_close, 21361864d84STakashi Iwai .trigger = line6_midi_input_trigger, 21461864d84STakashi Iwai }; 21561864d84STakashi Iwai 21661864d84STakashi Iwai /* Create a MIDI device */ 217aaa68d2fSTakashi Iwai static int snd_line6_new_midi(struct usb_line6 *line6, 218aaa68d2fSTakashi Iwai struct snd_rawmidi **rmidi_ret) 21961864d84STakashi Iwai { 22061864d84STakashi Iwai struct snd_rawmidi *rmidi; 22161864d84STakashi Iwai int err; 22261864d84STakashi Iwai 223aaa68d2fSTakashi Iwai err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret); 22461864d84STakashi Iwai if (err < 0) 22561864d84STakashi Iwai return err; 22661864d84STakashi Iwai 227aaa68d2fSTakashi Iwai rmidi = *rmidi_ret; 228aaa68d2fSTakashi Iwai strcpy(rmidi->id, line6->properties->id); 229aaa68d2fSTakashi Iwai strcpy(rmidi->name, line6->properties->name); 23061864d84STakashi Iwai 23161864d84STakashi Iwai rmidi->info_flags = 23261864d84STakashi Iwai SNDRV_RAWMIDI_INFO_OUTPUT | 23361864d84STakashi Iwai SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 23461864d84STakashi Iwai 23561864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 23661864d84STakashi Iwai &line6_midi_output_ops); 23761864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 23861864d84STakashi Iwai &line6_midi_input_ops); 23961864d84STakashi Iwai return 0; 24061864d84STakashi Iwai } 24161864d84STakashi Iwai 24261864d84STakashi Iwai /* MIDI device destructor */ 243aaa68d2fSTakashi Iwai static void snd_line6_midi_free(struct snd_rawmidi *rmidi) 24461864d84STakashi Iwai { 245aaa68d2fSTakashi Iwai struct snd_line6_midi *line6midi = rmidi->private_data; 24661864d84STakashi Iwai 24761864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_in); 24861864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_out); 249aaa68d2fSTakashi Iwai kfree(line6midi); 25061864d84STakashi Iwai } 25161864d84STakashi Iwai 25261864d84STakashi Iwai /* 25361864d84STakashi Iwai Initialize the Line 6 MIDI subsystem. 25461864d84STakashi Iwai */ 25561864d84STakashi Iwai int line6_init_midi(struct usb_line6 *line6) 25661864d84STakashi Iwai { 25761864d84STakashi Iwai int err; 258aaa68d2fSTakashi Iwai struct snd_rawmidi *rmidi; 25961864d84STakashi Iwai struct snd_line6_midi *line6midi; 26061864d84STakashi Iwai 2617811a3adSAndrej Krutak if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) { 26261864d84STakashi Iwai /* skip MIDI initialization and report success */ 26361864d84STakashi Iwai return 0; 26461864d84STakashi Iwai } 26561864d84STakashi Iwai 266aaa68d2fSTakashi Iwai err = snd_line6_new_midi(line6, &rmidi); 267aaa68d2fSTakashi Iwai if (err < 0) 268aaa68d2fSTakashi Iwai return err; 26961864d84STakashi Iwai 270aaa68d2fSTakashi Iwai line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); 271aaa68d2fSTakashi Iwai if (!line6midi) 27261864d84STakashi Iwai return -ENOMEM; 27361864d84STakashi Iwai 274aaa68d2fSTakashi Iwai rmidi->private_data = line6midi; 275aaa68d2fSTakashi Iwai rmidi->private_free = snd_line6_midi_free; 27661864d84STakashi Iwai 27761864d84STakashi Iwai init_waitqueue_head(&line6midi->send_wait); 278bc518ba4STakashi Iwai spin_lock_init(&line6midi->lock); 279aaa68d2fSTakashi Iwai line6midi->line6 = line6; 280aaa68d2fSTakashi Iwai 281aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); 282aaa68d2fSTakashi Iwai if (err < 0) 283aaa68d2fSTakashi Iwai return err; 284aaa68d2fSTakashi Iwai 285aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); 286aaa68d2fSTakashi Iwai if (err < 0) 287aaa68d2fSTakashi Iwai return err; 288aaa68d2fSTakashi Iwai 289aaa68d2fSTakashi Iwai line6->line6midi = line6midi; 29061864d84STakashi Iwai return 0; 29161864d84STakashi Iwai } 292ccddbe4aSTakashi Iwai EXPORT_SYMBOL_GPL(line6_init_midi); 293