1*a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 261864d84STakashi Iwai /* 3c078a4aaSChris Rorvick * Line 6 Linux USB driver 461864d84STakashi Iwai * 561864d84STakashi Iwai * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 661864d84STakashi Iwai */ 761864d84STakashi Iwai 861864d84STakashi Iwai #include <linux/slab.h> 961864d84STakashi Iwai #include <linux/usb.h> 10ccddbe4aSTakashi Iwai #include <linux/export.h> 1161864d84STakashi Iwai #include <sound/core.h> 1261864d84STakashi Iwai #include <sound/rawmidi.h> 1361864d84STakashi Iwai 1461864d84STakashi Iwai #include "driver.h" 1561864d84STakashi Iwai #include "midi.h" 1661864d84STakashi Iwai 1761864d84STakashi Iwai #define line6_rawmidi_substream_midi(substream) \ 1861864d84STakashi Iwai ((struct snd_line6_midi *)((substream)->rmidi->private_data)) 1961864d84STakashi Iwai 2061864d84STakashi Iwai static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 2161864d84STakashi Iwai int length); 2261864d84STakashi Iwai 2361864d84STakashi Iwai /* 2461864d84STakashi Iwai Pass data received via USB to MIDI. 2561864d84STakashi Iwai */ 2661864d84STakashi Iwai void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, 2761864d84STakashi Iwai int length) 2861864d84STakashi Iwai { 2961864d84STakashi Iwai if (line6->line6midi->substream_receive) 3061864d84STakashi Iwai snd_rawmidi_receive(line6->line6midi->substream_receive, 3161864d84STakashi Iwai data, length); 3261864d84STakashi Iwai } 3361864d84STakashi Iwai 3461864d84STakashi Iwai /* 3561864d84STakashi Iwai Read data from MIDI buffer and transmit them via USB. 3661864d84STakashi Iwai */ 3761864d84STakashi Iwai static void line6_midi_transmit(struct snd_rawmidi_substream *substream) 3861864d84STakashi Iwai { 3961864d84STakashi Iwai struct usb_line6 *line6 = 4061864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 4161864d84STakashi Iwai struct snd_line6_midi *line6midi = line6->line6midi; 4261864d84STakashi Iwai struct midi_buffer *mb = &line6midi->midibuf_out; 4361864d84STakashi Iwai unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE]; 4461864d84STakashi Iwai int req, done; 4561864d84STakashi Iwai 4661864d84STakashi Iwai for (;;) { 4761864d84STakashi Iwai req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size); 4861864d84STakashi Iwai done = snd_rawmidi_transmit_peek(substream, chunk, req); 4961864d84STakashi Iwai 5061864d84STakashi Iwai if (done == 0) 5161864d84STakashi Iwai break; 5261864d84STakashi Iwai 5361864d84STakashi Iwai line6_midibuf_write(mb, chunk, done); 5461864d84STakashi Iwai snd_rawmidi_transmit_ack(substream, done); 5561864d84STakashi Iwai } 5661864d84STakashi Iwai 5761864d84STakashi Iwai for (;;) { 5861864d84STakashi Iwai done = line6_midibuf_read(mb, chunk, 5961864d84STakashi Iwai LINE6_FALLBACK_MAXPACKETSIZE); 6061864d84STakashi Iwai 6161864d84STakashi Iwai if (done == 0) 6261864d84STakashi Iwai break; 6361864d84STakashi Iwai 6461864d84STakashi Iwai send_midi_async(line6, chunk, done); 6561864d84STakashi Iwai } 6661864d84STakashi Iwai } 6761864d84STakashi Iwai 6861864d84STakashi Iwai /* 6961864d84STakashi Iwai Notification of completion of MIDI transmission. 7061864d84STakashi Iwai */ 7161864d84STakashi Iwai static void midi_sent(struct urb *urb) 7261864d84STakashi Iwai { 7361864d84STakashi Iwai unsigned long flags; 7461864d84STakashi Iwai int status; 7561864d84STakashi Iwai int num; 7661864d84STakashi Iwai struct usb_line6 *line6 = (struct usb_line6 *)urb->context; 7761864d84STakashi Iwai 7861864d84STakashi Iwai status = urb->status; 7961864d84STakashi Iwai kfree(urb->transfer_buffer); 8061864d84STakashi Iwai usb_free_urb(urb); 8161864d84STakashi Iwai 8261864d84STakashi Iwai if (status == -ESHUTDOWN) 8361864d84STakashi Iwai return; 8461864d84STakashi Iwai 85bc518ba4STakashi Iwai spin_lock_irqsave(&line6->line6midi->lock, flags); 8661864d84STakashi Iwai num = --line6->line6midi->num_active_send_urbs; 8761864d84STakashi Iwai 8861864d84STakashi Iwai if (num == 0) { 8961864d84STakashi Iwai line6_midi_transmit(line6->line6midi->substream_transmit); 9061864d84STakashi Iwai num = line6->line6midi->num_active_send_urbs; 9161864d84STakashi Iwai } 9261864d84STakashi Iwai 9361864d84STakashi Iwai if (num == 0) 9461864d84STakashi Iwai wake_up(&line6->line6midi->send_wait); 9561864d84STakashi Iwai 96bc518ba4STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->lock, flags); 9761864d84STakashi Iwai } 9861864d84STakashi Iwai 9961864d84STakashi Iwai /* 10061864d84STakashi Iwai Send an asynchronous MIDI message. 101bc518ba4STakashi Iwai Assumes that line6->line6midi->lock is held 10261864d84STakashi Iwai (i.e., this function is serialized). 10361864d84STakashi Iwai */ 10461864d84STakashi Iwai static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 10561864d84STakashi Iwai int length) 10661864d84STakashi Iwai { 10761864d84STakashi Iwai struct urb *urb; 10861864d84STakashi Iwai int retval; 10961864d84STakashi Iwai unsigned char *transfer_buffer; 11061864d84STakashi Iwai 11161864d84STakashi Iwai urb = usb_alloc_urb(0, GFP_ATOMIC); 11261864d84STakashi Iwai 113a019f5e8STakashi Iwai if (urb == NULL) 11461864d84STakashi Iwai return -ENOMEM; 11561864d84STakashi Iwai 11661864d84STakashi Iwai transfer_buffer = kmemdup(data, length, GFP_ATOMIC); 11761864d84STakashi Iwai 11861864d84STakashi Iwai if (transfer_buffer == NULL) { 11961864d84STakashi Iwai usb_free_urb(urb); 12061864d84STakashi Iwai return -ENOMEM; 12161864d84STakashi Iwai } 12261864d84STakashi Iwai 12361864d84STakashi Iwai usb_fill_int_urb(urb, line6->usbdev, 1247ecb46e9SFabián Inostroza usb_sndintpipe(line6->usbdev, 12561864d84STakashi Iwai line6->properties->ep_ctrl_w), 12661864d84STakashi Iwai transfer_buffer, length, midi_sent, line6, 12761864d84STakashi Iwai line6->interval); 12861864d84STakashi Iwai urb->actual_length = 0; 1294f95646cSTakashi Iwai retval = usb_urb_ep_type_check(urb); 1304f95646cSTakashi Iwai if (retval < 0) 1314f95646cSTakashi Iwai goto error; 13261864d84STakashi Iwai 1334f95646cSTakashi Iwai retval = usb_submit_urb(urb, GFP_ATOMIC); 1344f95646cSTakashi Iwai if (retval < 0) 1354f95646cSTakashi Iwai goto error; 13661864d84STakashi Iwai 13761864d84STakashi Iwai ++line6->line6midi->num_active_send_urbs; 13861864d84STakashi Iwai return 0; 1394f95646cSTakashi Iwai 1404f95646cSTakashi Iwai error: 1414f95646cSTakashi Iwai dev_err(line6->ifcdev, "usb_submit_urb failed\n"); 1424f95646cSTakashi Iwai usb_free_urb(urb); 1434f95646cSTakashi Iwai return retval; 14461864d84STakashi Iwai } 14561864d84STakashi Iwai 14661864d84STakashi Iwai static int line6_midi_output_open(struct snd_rawmidi_substream *substream) 14761864d84STakashi Iwai { 14861864d84STakashi Iwai return 0; 14961864d84STakashi Iwai } 15061864d84STakashi Iwai 15161864d84STakashi Iwai static int line6_midi_output_close(struct snd_rawmidi_substream *substream) 15261864d84STakashi Iwai { 15361864d84STakashi Iwai return 0; 15461864d84STakashi Iwai } 15561864d84STakashi Iwai 15661864d84STakashi Iwai static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, 15761864d84STakashi Iwai int up) 15861864d84STakashi Iwai { 15961864d84STakashi Iwai unsigned long flags; 16061864d84STakashi Iwai struct usb_line6 *line6 = 16161864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 16261864d84STakashi Iwai 16361864d84STakashi Iwai line6->line6midi->substream_transmit = substream; 164bc518ba4STakashi Iwai spin_lock_irqsave(&line6->line6midi->lock, flags); 16561864d84STakashi Iwai 16661864d84STakashi Iwai if (line6->line6midi->num_active_send_urbs == 0) 16761864d84STakashi Iwai line6_midi_transmit(substream); 16861864d84STakashi Iwai 169bc518ba4STakashi Iwai spin_unlock_irqrestore(&line6->line6midi->lock, flags); 17061864d84STakashi Iwai } 17161864d84STakashi Iwai 17261864d84STakashi Iwai static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) 17361864d84STakashi Iwai { 17461864d84STakashi Iwai struct usb_line6 *line6 = 17561864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 17661864d84STakashi Iwai struct snd_line6_midi *midi = line6->line6midi; 17761864d84STakashi Iwai 17861864d84STakashi Iwai wait_event_interruptible(midi->send_wait, 17961864d84STakashi Iwai midi->num_active_send_urbs == 0); 18061864d84STakashi Iwai } 18161864d84STakashi Iwai 18261864d84STakashi Iwai static int line6_midi_input_open(struct snd_rawmidi_substream *substream) 18361864d84STakashi Iwai { 18461864d84STakashi Iwai return 0; 18561864d84STakashi Iwai } 18661864d84STakashi Iwai 18761864d84STakashi Iwai static int line6_midi_input_close(struct snd_rawmidi_substream *substream) 18861864d84STakashi Iwai { 18961864d84STakashi Iwai return 0; 19061864d84STakashi Iwai } 19161864d84STakashi Iwai 19261864d84STakashi Iwai static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, 19361864d84STakashi Iwai int up) 19461864d84STakashi Iwai { 19561864d84STakashi Iwai struct usb_line6 *line6 = 19661864d84STakashi Iwai line6_rawmidi_substream_midi(substream)->line6; 19761864d84STakashi Iwai 19861864d84STakashi Iwai if (up) 19961864d84STakashi Iwai line6->line6midi->substream_receive = substream; 20061864d84STakashi Iwai else 20161864d84STakashi Iwai line6->line6midi->substream_receive = NULL; 20261864d84STakashi Iwai } 20361864d84STakashi Iwai 204f43e5407STakashi Iwai static const struct snd_rawmidi_ops line6_midi_output_ops = { 20561864d84STakashi Iwai .open = line6_midi_output_open, 20661864d84STakashi Iwai .close = line6_midi_output_close, 20761864d84STakashi Iwai .trigger = line6_midi_output_trigger, 20861864d84STakashi Iwai .drain = line6_midi_output_drain, 20961864d84STakashi Iwai }; 21061864d84STakashi Iwai 211f43e5407STakashi Iwai static const struct snd_rawmidi_ops line6_midi_input_ops = { 21261864d84STakashi Iwai .open = line6_midi_input_open, 21361864d84STakashi Iwai .close = line6_midi_input_close, 21461864d84STakashi Iwai .trigger = line6_midi_input_trigger, 21561864d84STakashi Iwai }; 21661864d84STakashi Iwai 21761864d84STakashi Iwai /* Create a MIDI device */ 218aaa68d2fSTakashi Iwai static int snd_line6_new_midi(struct usb_line6 *line6, 219aaa68d2fSTakashi Iwai struct snd_rawmidi **rmidi_ret) 22061864d84STakashi Iwai { 22161864d84STakashi Iwai struct snd_rawmidi *rmidi; 22261864d84STakashi Iwai int err; 22361864d84STakashi Iwai 224aaa68d2fSTakashi Iwai err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret); 22561864d84STakashi Iwai if (err < 0) 22661864d84STakashi Iwai return err; 22761864d84STakashi Iwai 228aaa68d2fSTakashi Iwai rmidi = *rmidi_ret; 229aaa68d2fSTakashi Iwai strcpy(rmidi->id, line6->properties->id); 230aaa68d2fSTakashi Iwai strcpy(rmidi->name, line6->properties->name); 23161864d84STakashi Iwai 23261864d84STakashi Iwai rmidi->info_flags = 23361864d84STakashi Iwai SNDRV_RAWMIDI_INFO_OUTPUT | 23461864d84STakashi Iwai SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 23561864d84STakashi Iwai 23661864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 23761864d84STakashi Iwai &line6_midi_output_ops); 23861864d84STakashi Iwai snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 23961864d84STakashi Iwai &line6_midi_input_ops); 24061864d84STakashi Iwai return 0; 24161864d84STakashi Iwai } 24261864d84STakashi Iwai 24361864d84STakashi Iwai /* MIDI device destructor */ 244aaa68d2fSTakashi Iwai static void snd_line6_midi_free(struct snd_rawmidi *rmidi) 24561864d84STakashi Iwai { 246aaa68d2fSTakashi Iwai struct snd_line6_midi *line6midi = rmidi->private_data; 24761864d84STakashi Iwai 24861864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_in); 24961864d84STakashi Iwai line6_midibuf_destroy(&line6midi->midibuf_out); 250aaa68d2fSTakashi Iwai kfree(line6midi); 25161864d84STakashi Iwai } 25261864d84STakashi Iwai 25361864d84STakashi Iwai /* 25461864d84STakashi Iwai Initialize the Line 6 MIDI subsystem. 25561864d84STakashi Iwai */ 25661864d84STakashi Iwai int line6_init_midi(struct usb_line6 *line6) 25761864d84STakashi Iwai { 25861864d84STakashi Iwai int err; 259aaa68d2fSTakashi Iwai struct snd_rawmidi *rmidi; 26061864d84STakashi Iwai struct snd_line6_midi *line6midi; 26161864d84STakashi Iwai 2627811a3adSAndrej Krutak if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) { 26361864d84STakashi Iwai /* skip MIDI initialization and report success */ 26461864d84STakashi Iwai return 0; 26561864d84STakashi Iwai } 26661864d84STakashi Iwai 267aaa68d2fSTakashi Iwai err = snd_line6_new_midi(line6, &rmidi); 268aaa68d2fSTakashi Iwai if (err < 0) 269aaa68d2fSTakashi Iwai return err; 27061864d84STakashi Iwai 271aaa68d2fSTakashi Iwai line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); 272aaa68d2fSTakashi Iwai if (!line6midi) 27361864d84STakashi Iwai return -ENOMEM; 27461864d84STakashi Iwai 275aaa68d2fSTakashi Iwai rmidi->private_data = line6midi; 276aaa68d2fSTakashi Iwai rmidi->private_free = snd_line6_midi_free; 27761864d84STakashi Iwai 27861864d84STakashi Iwai init_waitqueue_head(&line6midi->send_wait); 279bc518ba4STakashi Iwai spin_lock_init(&line6midi->lock); 280aaa68d2fSTakashi Iwai line6midi->line6 = line6; 281aaa68d2fSTakashi Iwai 282aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); 283aaa68d2fSTakashi Iwai if (err < 0) 284aaa68d2fSTakashi Iwai return err; 285aaa68d2fSTakashi Iwai 286aaa68d2fSTakashi Iwai err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); 287aaa68d2fSTakashi Iwai if (err < 0) 288aaa68d2fSTakashi Iwai return err; 289aaa68d2fSTakashi Iwai 290aaa68d2fSTakashi Iwai line6->line6midi = line6midi; 29161864d84STakashi Iwai return 0; 29261864d84STakashi Iwai } 293ccddbe4aSTakashi Iwai EXPORT_SYMBOL_GPL(line6_init_midi); 294