1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Line 6 Linux USB driver 4 * 5 * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.at) 6 */ 7 8 #include <linux/slab.h> 9 #include <linux/usb.h> 10 #include <linux/export.h> 11 #include <sound/core.h> 12 #include <sound/rawmidi.h> 13 14 #include "driver.h" 15 #include "midi.h" 16 17 #define line6_rawmidi_substream_midi(substream) \ 18 ((struct snd_line6_midi *)((substream)->rmidi->private_data)) 19 20 static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 21 int length); 22 23 /* 24 Pass data received via USB to MIDI. 25 */ 26 void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, 27 int length) 28 { 29 if (line6->line6midi->substream_receive) 30 snd_rawmidi_receive(line6->line6midi->substream_receive, 31 data, length); 32 } 33 34 /* 35 Read data from MIDI buffer and transmit them via USB. 36 */ 37 static void line6_midi_transmit(struct snd_rawmidi_substream *substream) 38 { 39 struct usb_line6 *line6 = 40 line6_rawmidi_substream_midi(substream)->line6; 41 struct snd_line6_midi *line6midi = line6->line6midi; 42 struct midi_buffer *mb = &line6midi->midibuf_out; 43 unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE]; 44 int req, done; 45 46 for (;;) { 47 req = min3(line6_midibuf_bytes_free(mb), line6->max_packet_size, 48 LINE6_FALLBACK_MAXPACKETSIZE); 49 done = snd_rawmidi_transmit_peek(substream, chunk, req); 50 51 if (done == 0) 52 break; 53 54 line6_midibuf_write(mb, chunk, done); 55 snd_rawmidi_transmit_ack(substream, done); 56 } 57 58 for (;;) { 59 done = line6_midibuf_read(mb, chunk, 60 LINE6_FALLBACK_MAXPACKETSIZE, 61 LINE6_MIDIBUF_READ_TX); 62 63 if (done == 0) 64 break; 65 66 send_midi_async(line6, chunk, done); 67 } 68 } 69 70 /* 71 Notification of completion of MIDI transmission. 72 */ 73 static void midi_sent(struct urb *urb) 74 { 75 int status; 76 int num; 77 struct usb_line6 *line6 = (struct usb_line6 *)urb->context; 78 79 status = urb->status; 80 kfree(urb->transfer_buffer); 81 usb_free_urb(urb); 82 83 if (status == -ESHUTDOWN) 84 return; 85 86 guard(spinlock_irqsave)(&line6->line6midi->lock); 87 num = --line6->line6midi->num_active_send_urbs; 88 89 if (num == 0) { 90 line6_midi_transmit(line6->line6midi->substream_transmit); 91 num = line6->line6midi->num_active_send_urbs; 92 } 93 94 if (num == 0) 95 wake_up(&line6->line6midi->send_wait); 96 } 97 98 /* 99 Send an asynchronous MIDI message. 100 Assumes that line6->line6midi->lock is held 101 (i.e., this function is serialized). 102 */ 103 static int send_midi_async(struct usb_line6 *line6, unsigned char *data, 104 int length) 105 { 106 struct urb *urb; 107 int retval; 108 unsigned char *transfer_buffer; 109 110 urb = usb_alloc_urb(0, GFP_ATOMIC); 111 112 if (urb == NULL) 113 return -ENOMEM; 114 115 transfer_buffer = kmemdup(data, length, GFP_ATOMIC); 116 117 if (transfer_buffer == NULL) { 118 usb_free_urb(urb); 119 return -ENOMEM; 120 } 121 122 usb_fill_int_urb(urb, line6->usbdev, 123 usb_sndintpipe(line6->usbdev, 124 line6->properties->ep_ctrl_w), 125 transfer_buffer, length, midi_sent, line6, 126 line6->interval); 127 urb->actual_length = 0; 128 retval = usb_urb_ep_type_check(urb); 129 if (retval < 0) 130 goto error; 131 132 retval = usb_submit_urb(urb, GFP_ATOMIC); 133 if (retval < 0) 134 goto error; 135 136 ++line6->line6midi->num_active_send_urbs; 137 return 0; 138 139 error: 140 dev_err(line6->ifcdev, "usb_submit_urb failed\n"); 141 usb_free_urb(urb); 142 return retval; 143 } 144 145 static int line6_midi_output_open(struct snd_rawmidi_substream *substream) 146 { 147 return 0; 148 } 149 150 static int line6_midi_output_close(struct snd_rawmidi_substream *substream) 151 { 152 return 0; 153 } 154 155 static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, 156 int up) 157 { 158 struct usb_line6 *line6 = 159 line6_rawmidi_substream_midi(substream)->line6; 160 161 line6->line6midi->substream_transmit = substream; 162 guard(spinlock_irqsave)(&line6->line6midi->lock); 163 164 if (line6->line6midi->num_active_send_urbs == 0) 165 line6_midi_transmit(substream); 166 } 167 168 static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) 169 { 170 struct usb_line6 *line6 = 171 line6_rawmidi_substream_midi(substream)->line6; 172 struct snd_line6_midi *midi = line6->line6midi; 173 174 wait_event_interruptible(midi->send_wait, 175 midi->num_active_send_urbs == 0); 176 } 177 178 static int line6_midi_input_open(struct snd_rawmidi_substream *substream) 179 { 180 return 0; 181 } 182 183 static int line6_midi_input_close(struct snd_rawmidi_substream *substream) 184 { 185 return 0; 186 } 187 188 static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, 189 int up) 190 { 191 struct usb_line6 *line6 = 192 line6_rawmidi_substream_midi(substream)->line6; 193 194 if (up) 195 line6->line6midi->substream_receive = substream; 196 else 197 line6->line6midi->substream_receive = NULL; 198 } 199 200 static const struct snd_rawmidi_ops line6_midi_output_ops = { 201 .open = line6_midi_output_open, 202 .close = line6_midi_output_close, 203 .trigger = line6_midi_output_trigger, 204 .drain = line6_midi_output_drain, 205 }; 206 207 static const struct snd_rawmidi_ops line6_midi_input_ops = { 208 .open = line6_midi_input_open, 209 .close = line6_midi_input_close, 210 .trigger = line6_midi_input_trigger, 211 }; 212 213 /* Create a MIDI device */ 214 static int snd_line6_new_midi(struct usb_line6 *line6, 215 struct snd_rawmidi **rmidi_ret) 216 { 217 struct snd_rawmidi *rmidi; 218 int err; 219 220 err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret); 221 if (err < 0) 222 return err; 223 224 rmidi = *rmidi_ret; 225 strscpy(rmidi->id, line6->properties->id); 226 strscpy(rmidi->name, line6->properties->name); 227 228 rmidi->info_flags = 229 SNDRV_RAWMIDI_INFO_OUTPUT | 230 SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; 231 232 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 233 &line6_midi_output_ops); 234 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 235 &line6_midi_input_ops); 236 return 0; 237 } 238 239 /* MIDI device destructor */ 240 static void snd_line6_midi_free(struct snd_rawmidi *rmidi) 241 { 242 struct snd_line6_midi *line6midi = rmidi->private_data; 243 244 line6_midibuf_destroy(&line6midi->midibuf_in); 245 line6_midibuf_destroy(&line6midi->midibuf_out); 246 kfree(line6midi); 247 } 248 249 /* 250 Initialize the Line 6 MIDI subsystem. 251 */ 252 int line6_init_midi(struct usb_line6 *line6) 253 { 254 int err; 255 struct snd_rawmidi *rmidi; 256 struct snd_line6_midi *line6midi; 257 258 if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) { 259 /* skip MIDI initialization and report success */ 260 return 0; 261 } 262 263 err = snd_line6_new_midi(line6, &rmidi); 264 if (err < 0) 265 return err; 266 267 line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); 268 if (!line6midi) 269 return -ENOMEM; 270 271 rmidi->private_data = line6midi; 272 rmidi->private_free = snd_line6_midi_free; 273 274 init_waitqueue_head(&line6midi->send_wait); 275 spin_lock_init(&line6midi->lock); 276 line6midi->line6 = line6; 277 278 err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); 279 if (err < 0) 280 return err; 281 282 err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); 283 if (err < 0) 284 return err; 285 286 line6->line6midi = line6midi; 287 return 0; 288 } 289 EXPORT_SYMBOL_GPL(line6_init_midi); 290