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; 133*4f95646cSTakashi Iwai retval = usb_urb_ep_type_check(urb); 134*4f95646cSTakashi Iwai if (retval < 0) 135*4f95646cSTakashi Iwai goto error; 13661864d84STakashi Iwai 137*4f95646cSTakashi Iwai retval = usb_submit_urb(urb, GFP_ATOMIC); 138*4f95646cSTakashi Iwai if (retval < 0) 139*4f95646cSTakashi Iwai goto error; 14061864d84STakashi Iwai 14161864d84STakashi Iwai ++line6->line6midi->num_active_send_urbs; 14261864d84STakashi Iwai return 0; 143*4f95646cSTakashi Iwai 144*4f95646cSTakashi Iwai error: 145*4f95646cSTakashi Iwai dev_err(line6->ifcdev, "usb_submit_urb failed\n"); 146*4f95646cSTakashi Iwai usb_free_urb(urb); 147*4f95646cSTakashi Iwai return retval; 14861864d84STakashi Iwai } 14961864d84STakashi Iwai 15061864d84STakashi Iwai static int line6_midi_output_open(struct snd_rawmidi_substream *substream) 15161864d84STakashi Iwai { 15261864d84STakashi Iwai return 0; 15361864d84STakashi Iwai } 15461864d84STakashi Iwai 15561864d84STakashi Iwai static int line6_midi_output_close(struct snd_rawmidi_substream *substream) 15661864d84STakashi Iwai { 15761864d84STakashi Iwai return 0; 15861864d84STakashi Iwai } 15961864d84STakashi Iwai 16061864d84STakashi Iwai static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, 16161864d84STakashi Iwai int up) 16261864d84STakashi Iwai { 16361864d84STakashi Iwai unsigned long flags; 16461864d84STakashi Iwai struct usb_line6 *line6 = 16561864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 16661864d84STakashi Iwai 16761864d84STakashi Iwai line6->line6midi->substream_transmit = substream; 168bc518ba4STakashi Iwai spin_lock_irqsave(&line6->line6midi->lock, flags); 16961864d84STakashi Iwai 17061864d84STakashi Iwai if (line6->line6midi->num_active_send_urbs == 0) 17161864d84STakashi Iwai line6_midi_transmit(substream); 17261864d84STakashi Iwai 173bc518ba4STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->lock, flags); 17461864d84STakashi Iwai } 17561864d84STakashi Iwai 17661864d84STakashi Iwai static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) 17761864d84STakashi Iwai { 17861864d84STakashi Iwai struct usb_line6 *line6 = 17961864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 18061864d84STakashi Iwai struct snd_line6_midi *midi = line6->line6midi; 18161864d84STakashi Iwai 18261864d84STakashi Iwai wait_event_interruptible(midi->send_wait, 18361864d84STakashi Iwai midi->num_active_send_urbs == 0); 18461864d84STakashi Iwai } 18561864d84STakashi Iwai 18661864d84STakashi Iwai static int line6_midi_input_open(struct snd_rawmidi_substream *substream) 18761864d84STakashi Iwai { 18861864d84STakashi Iwai return 0; 18961864d84STakashi Iwai } 19061864d84STakashi Iwai 19161864d84STakashi Iwai static int line6_midi_input_close(struct snd_rawmidi_substream *substream) 19261864d84STakashi Iwai { 19361864d84STakashi Iwai return 0; 19461864d84STakashi Iwai } 19561864d84STakashi Iwai 19661864d84STakashi Iwai static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, 19761864d84STakashi Iwai int up) 19861864d84STakashi Iwai { 19961864d84STakashi Iwai struct usb_line6 *line6 = 20061864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 20161864d84STakashi Iwai 20261864d84STakashi Iwai if (up) 20361864d84STakashi Iwai line6->line6midi->substream_receive = substream; 20461864d84STakashi Iwai else 20561864d84STakashi Iwai line6->line6midi->substream_receive = NULL; 20661864d84STakashi Iwai } 20761864d84STakashi Iwai 208f43e5407STakashi Iwai static const struct snd_rawmidi_ops line6_midi_output_ops = { 20961864d84STakashi Iwai .open = line6_midi_output_open, 21061864d84STakashi Iwai .close = line6_midi_output_close, 21161864d84STakashi Iwai .trigger = line6_midi_output_trigger, 21261864d84STakashi Iwai .drain = line6_midi_output_drain, 21361864d84STakashi Iwai }; 21461864d84STakashi Iwai 215f43e5407STakashi Iwai static const struct snd_rawmidi_ops line6_midi_input_ops = { 21661864d84STakashi Iwai .open = line6_midi_input_open, 21761864d84STakashi Iwai .close = line6_midi_input_close, 21861864d84STakashi Iwai .trigger = line6_midi_input_trigger, 21961864d84STakashi Iwai }; 22061864d84STakashi Iwai 22161864d84STakashi Iwai /* Create a MIDI device */ 222aaa68d2fSTakashi Iwai static int snd_line6_new_midi(struct usb_line6 *line6, 223aaa68d2fSTakashi Iwai struct snd_rawmidi **rmidi_ret) 22461864d84STakashi Iwai { 22561864d84STakashi Iwai struct snd_rawmidi *rmidi; 22661864d84STakashi Iwai int err; 22761864d84STakashi Iwai 228aaa68d2fSTakashi Iwai err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret); 22961864d84STakashi Iwai if (err < 0) 23061864d84STakashi Iwai return err; 23161864d84STakashi Iwai 232aaa68d2fSTakashi Iwai rmidi = *rmidi_ret; 233aaa68d2fSTakashi Iwai strcpy(rmidi->id, line6->properties->id); 234aaa68d2fSTakashi Iwai strcpy(rmidi->name, line6->properties->name); 23561864d84STakashi Iwai 23661864d84STakashi Iwai rmidi->info_flags = 23761864d84STakashi Iwai SNDRV_RAWMIDI_INFO_OUTPUT | 23861864d84STakashi Iwai SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 23961864d84STakashi Iwai 24061864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 24161864d84STakashi Iwai &line6_midi_output_ops); 24261864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 24361864d84STakashi Iwai &line6_midi_input_ops); 24461864d84STakashi Iwai return 0; 24561864d84STakashi Iwai } 24661864d84STakashi Iwai 24761864d84STakashi Iwai /* MIDI device destructor */ 248aaa68d2fSTakashi Iwai static void snd_line6_midi_free(struct snd_rawmidi *rmidi) 24961864d84STakashi Iwai { 250aaa68d2fSTakashi Iwai struct snd_line6_midi *line6midi = rmidi->private_data; 25161864d84STakashi Iwai 25261864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_in); 25361864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_out); 254aaa68d2fSTakashi Iwai kfree(line6midi); 25561864d84STakashi Iwai } 25661864d84STakashi Iwai 25761864d84STakashi Iwai /* 25861864d84STakashi Iwai Initialize the Line 6 MIDI subsystem. 25961864d84STakashi Iwai */ 26061864d84STakashi Iwai int line6_init_midi(struct usb_line6 *line6) 26161864d84STakashi Iwai { 26261864d84STakashi Iwai int err; 263aaa68d2fSTakashi Iwai struct snd_rawmidi *rmidi; 26461864d84STakashi Iwai struct snd_line6_midi *line6midi; 26561864d84STakashi Iwai 2667811a3adSAndrej Krutak if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) { 26761864d84STakashi Iwai /* skip MIDI initialization and report success */ 26861864d84STakashi Iwai return 0; 26961864d84STakashi Iwai } 27061864d84STakashi Iwai 271aaa68d2fSTakashi Iwai err = snd_line6_new_midi(line6, &rmidi); 272aaa68d2fSTakashi Iwai if (err < 0) 273aaa68d2fSTakashi Iwai return err; 27461864d84STakashi Iwai 275aaa68d2fSTakashi Iwai line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); 276aaa68d2fSTakashi Iwai if (!line6midi) 27761864d84STakashi Iwai return -ENOMEM; 27861864d84STakashi Iwai 279aaa68d2fSTakashi Iwai rmidi->private_data = line6midi; 280aaa68d2fSTakashi Iwai rmidi->private_free = snd_line6_midi_free; 28161864d84STakashi Iwai 28261864d84STakashi Iwai init_waitqueue_head(&line6midi->send_wait); 283bc518ba4STakashi Iwai spin_lock_init(&line6midi->lock); 284aaa68d2fSTakashi Iwai line6midi->line6 = line6; 285aaa68d2fSTakashi Iwai 286aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); 287aaa68d2fSTakashi Iwai if (err < 0) 288aaa68d2fSTakashi Iwai return err; 289aaa68d2fSTakashi Iwai 290aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); 291aaa68d2fSTakashi Iwai if (err < 0) 292aaa68d2fSTakashi Iwai return err; 293aaa68d2fSTakashi Iwai 294aaa68d2fSTakashi Iwai line6->line6midi = line6midi; 29561864d84STakashi Iwai return 0; 29661864d84STakashi Iwai } 297ccddbe4aSTakashi Iwai EXPORT_SYMBOL_GPL(line6_init_midi); 298