Commit | Line | Data |
---|---|---|
5fd54ace | 1 | // SPDX-License-Identifier: GPL-2.0+ |
d5daf49b DM |
2 | /* |
3 | * f_midi.c -- USB MIDI class function driver | |
4 | * | |
5 | * Copyright (C) 2006 Thumtronics Pty Ltd. | |
6 | * Developed for Thumtronics by Grey Innovation | |
7 | * Ben Williamson <ben.williamson@greyinnovation.com> | |
8 | * | |
9 | * Rewritten for the composite framework | |
10 | * Copyright (C) 2011 Daniel Mack <zonque@gmail.com> | |
11 | * | |
12 | * Based on drivers/usb/gadget/f_audio.c, | |
13 | * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> | |
14 | * Copyright (C) 2008 Analog Devices, Inc | |
15 | * | |
16 | * and drivers/usb/gadget/midi.c, | |
17 | * Copyright (C) 2006 Thumtronics Pty Ltd. | |
18 | * Ben Williamson <ben.williamson@greyinnovation.com> | |
d5daf49b DM |
19 | */ |
20 | ||
21 | #include <linux/kernel.h> | |
b85e9de9 | 22 | #include <linux/module.h> |
d5daf49b | 23 | #include <linux/slab.h> |
d5daf49b | 24 | #include <linux/device.h> |
e1e3d7ec | 25 | #include <linux/kfifo.h> |
9acdf4df | 26 | #include <linux/spinlock.h> |
d5daf49b DM |
27 | |
28 | #include <sound/core.h> | |
29 | #include <sound/initval.h> | |
30 | #include <sound/rawmidi.h> | |
31 | ||
32 | #include <linux/usb/ch9.h> | |
33 | #include <linux/usb/gadget.h> | |
34 | #include <linux/usb/audio.h> | |
35 | #include <linux/usb/midi.h> | |
36 | ||
1efd54ea | 37 | #include "u_f.h" |
b85e9de9 | 38 | #include "u_midi.h" |
1efd54ea | 39 | |
d5daf49b DM |
40 | MODULE_AUTHOR("Ben Williamson"); |
41 | MODULE_LICENSE("GPL v2"); | |
42 | ||
43 | static const char f_midi_shortname[] = "f_midi"; | |
44 | static const char f_midi_longname[] = "MIDI Gadget"; | |
45 | ||
c8933c3f DM |
46 | /* |
47 | * We can only handle 16 cables on one single endpoint, as cable numbers are | |
48 | * stored in 4-bit fields. And as the interface currently only holds one | |
49 | * single endpoint, this is the maximum number of ports we can allow. | |
50 | */ | |
51 | #define MAX_PORTS 16 | |
52 | ||
f42ab18c FT |
53 | /* MIDI message states */ |
54 | enum { | |
55 | STATE_INITIAL = 0, /* pseudo state */ | |
56 | STATE_1PARAM, | |
57 | STATE_2PARAM_1, | |
58 | STATE_2PARAM_2, | |
59 | STATE_SYSEX_0, | |
60 | STATE_SYSEX_1, | |
61 | STATE_SYSEX_2, | |
62 | STATE_REAL_TIME, | |
63 | STATE_FINISHED, /* pseudo state */ | |
64 | }; | |
65 | ||
d5daf49b DM |
66 | /* |
67 | * This is a gadget, and the IN/OUT naming is from the host's perspective. | |
68 | * USB -> OUT endpoint -> rawmidi | |
69 | * USB <- IN endpoint <- rawmidi | |
70 | */ | |
71 | struct gmidi_in_port { | |
4111d494 | 72 | struct snd_rawmidi_substream *substream; |
d5daf49b | 73 | int active; |
c8933c3f | 74 | uint8_t cable; |
d5daf49b | 75 | uint8_t state; |
d5daf49b DM |
76 | uint8_t data[2]; |
77 | }; | |
78 | ||
79 | struct f_midi { | |
80 | struct usb_function func; | |
81 | struct usb_gadget *gadget; | |
82 | struct usb_ep *in_ep, *out_ep; | |
83 | struct snd_card *card; | |
84 | struct snd_rawmidi *rmidi; | |
919de443 | 85 | u8 ms_id; |
d5daf49b | 86 | |
c8933c3f | 87 | struct snd_rawmidi_substream *out_substream[MAX_PORTS]; |
c8933c3f | 88 | |
d5daf49b | 89 | unsigned long out_triggered; |
8653d71c | 90 | struct work_struct work; |
c8933c3f DM |
91 | unsigned int in_ports; |
92 | unsigned int out_ports; | |
d5daf49b DM |
93 | int index; |
94 | char *id; | |
95 | unsigned int buflen, qlen; | |
e1e3d7ec FT |
96 | /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ |
97 | DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); | |
9acdf4df | 98 | spinlock_t transmit_lock; |
e1e3d7ec | 99 | unsigned int in_last_port; |
2d19cdc1 | 100 | unsigned char free_ref; |
bf0028f8 | 101 | |
18271702 | 102 | struct gmidi_in_port in_ports_array[] __counted_by(in_ports); |
d5daf49b DM |
103 | }; |
104 | ||
105 | static inline struct f_midi *func_to_midi(struct usb_function *f) | |
106 | { | |
107 | return container_of(f, struct f_midi, func); | |
108 | } | |
109 | ||
e1e3d7ec | 110 | static void f_midi_transmit(struct f_midi *midi); |
2d19cdc1 | 111 | static void f_midi_rmidi_free(struct snd_rawmidi *rmidi); |
9286e24b | 112 | static void f_midi_free_inst(struct usb_function_instance *f); |
d5daf49b DM |
113 | |
114 | DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); | |
115 | DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); | |
c8933c3f | 116 | DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); |
d5daf49b DM |
117 | |
118 | /* B.3.1 Standard AC Interface Descriptor */ | |
b85e9de9 | 119 | static struct usb_interface_descriptor ac_interface_desc = { |
d5daf49b DM |
120 | .bLength = USB_DT_INTERFACE_SIZE, |
121 | .bDescriptorType = USB_DT_INTERFACE, | |
122 | /* .bInterfaceNumber = DYNAMIC */ | |
123 | /* .bNumEndpoints = DYNAMIC */ | |
124 | .bInterfaceClass = USB_CLASS_AUDIO, | |
125 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, | |
126 | /* .iInterface = DYNAMIC */ | |
127 | }; | |
128 | ||
129 | /* B.3.2 Class-Specific AC Interface Descriptor */ | |
b85e9de9 | 130 | static struct uac1_ac_header_descriptor_1 ac_header_desc = { |
d5daf49b DM |
131 | .bLength = UAC_DT_AC_HEADER_SIZE(1), |
132 | .bDescriptorType = USB_DT_CS_INTERFACE, | |
133 | .bDescriptorSubtype = USB_MS_HEADER, | |
134 | .bcdADC = cpu_to_le16(0x0100), | |
135 | .wTotalLength = cpu_to_le16(UAC_DT_AC_HEADER_SIZE(1)), | |
136 | .bInCollection = 1, | |
137 | /* .baInterfaceNr = DYNAMIC */ | |
138 | }; | |
139 | ||
140 | /* B.4.1 Standard MS Interface Descriptor */ | |
b85e9de9 | 141 | static struct usb_interface_descriptor ms_interface_desc = { |
d5daf49b DM |
142 | .bLength = USB_DT_INTERFACE_SIZE, |
143 | .bDescriptorType = USB_DT_INTERFACE, | |
144 | /* .bInterfaceNumber = DYNAMIC */ | |
145 | .bNumEndpoints = 2, | |
146 | .bInterfaceClass = USB_CLASS_AUDIO, | |
147 | .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, | |
148 | /* .iInterface = DYNAMIC */ | |
149 | }; | |
150 | ||
151 | /* B.4.2 Class-Specific MS Interface Descriptor */ | |
b85e9de9 | 152 | static struct usb_ms_header_descriptor ms_header_desc = { |
d5daf49b DM |
153 | .bLength = USB_DT_MS_HEADER_SIZE, |
154 | .bDescriptorType = USB_DT_CS_INTERFACE, | |
155 | .bDescriptorSubtype = USB_MS_HEADER, | |
156 | .bcdMSC = cpu_to_le16(0x0100), | |
c8933c3f | 157 | /* .wTotalLength = DYNAMIC */ |
d5daf49b DM |
158 | }; |
159 | ||
d5daf49b DM |
160 | /* B.5.1 Standard Bulk OUT Endpoint Descriptor */ |
161 | static struct usb_endpoint_descriptor bulk_out_desc = { | |
162 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | |
163 | .bDescriptorType = USB_DT_ENDPOINT, | |
164 | .bEndpointAddress = USB_DIR_OUT, | |
165 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
166 | }; | |
167 | ||
24cf3459 BJS |
168 | static struct usb_ss_ep_comp_descriptor bulk_out_ss_comp_desc = { |
169 | .bLength = sizeof(bulk_out_ss_comp_desc), | |
170 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
171 | /* .bMaxBurst = 0, */ | |
172 | /* .bmAttributes = 0, */ | |
173 | }; | |
174 | ||
d5daf49b | 175 | /* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */ |
c8933c3f DM |
176 | static struct usb_ms_endpoint_descriptor_16 ms_out_desc = { |
177 | /* .bLength = DYNAMIC */ | |
d5daf49b DM |
178 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
179 | .bDescriptorSubtype = USB_MS_GENERAL, | |
c8933c3f DM |
180 | /* .bNumEmbMIDIJack = DYNAMIC */ |
181 | /* .baAssocJackID = DYNAMIC */ | |
d5daf49b DM |
182 | }; |
183 | ||
184 | /* B.6.1 Standard Bulk IN Endpoint Descriptor */ | |
185 | static struct usb_endpoint_descriptor bulk_in_desc = { | |
186 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | |
187 | .bDescriptorType = USB_DT_ENDPOINT, | |
188 | .bEndpointAddress = USB_DIR_IN, | |
189 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | |
190 | }; | |
191 | ||
24cf3459 BJS |
192 | static struct usb_ss_ep_comp_descriptor bulk_in_ss_comp_desc = { |
193 | .bLength = sizeof(bulk_in_ss_comp_desc), | |
194 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
195 | /* .bMaxBurst = 0, */ | |
196 | /* .bmAttributes = 0, */ | |
197 | }; | |
198 | ||
d5daf49b | 199 | /* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */ |
c8933c3f DM |
200 | static struct usb_ms_endpoint_descriptor_16 ms_in_desc = { |
201 | /* .bLength = DYNAMIC */ | |
d5daf49b DM |
202 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
203 | .bDescriptorSubtype = USB_MS_GENERAL, | |
c8933c3f DM |
204 | /* .bNumEmbMIDIJack = DYNAMIC */ |
205 | /* .baAssocJackID = DYNAMIC */ | |
d5daf49b DM |
206 | }; |
207 | ||
208 | /* string IDs are assigned dynamically */ | |
209 | ||
210 | #define STRING_FUNC_IDX 0 | |
211 | ||
212 | static struct usb_string midi_string_defs[] = { | |
213 | [STRING_FUNC_IDX].s = "MIDI function", | |
214 | { } /* end of list */ | |
215 | }; | |
216 | ||
217 | static struct usb_gadget_strings midi_stringtab = { | |
218 | .language = 0x0409, /* en-us */ | |
219 | .strings = midi_string_defs, | |
220 | }; | |
221 | ||
222 | static struct usb_gadget_strings *midi_strings[] = { | |
223 | &midi_stringtab, | |
224 | NULL, | |
225 | }; | |
226 | ||
1efd54ea AP |
227 | static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep, |
228 | unsigned length) | |
d5daf49b | 229 | { |
aadbe812 | 230 | return alloc_ep_req(ep, length); |
d5daf49b DM |
231 | } |
232 | ||
d5daf49b DM |
233 | static const uint8_t f_midi_cin_length[] = { |
234 | 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 | |
235 | }; | |
236 | ||
237 | /* | |
238 | * Receives a chunk of MIDI data. | |
239 | */ | |
240 | static void f_midi_read_data(struct usb_ep *ep, int cable, | |
241 | uint8_t *data, int length) | |
242 | { | |
243 | struct f_midi *midi = ep->driver_data; | |
c8933c3f | 244 | struct snd_rawmidi_substream *substream = midi->out_substream[cable]; |
d5daf49b | 245 | |
c8933c3f | 246 | if (!substream) |
d5daf49b DM |
247 | /* Nobody is listening - throw it on the floor. */ |
248 | return; | |
249 | ||
c8933c3f | 250 | if (!test_bit(cable, &midi->out_triggered)) |
d5daf49b DM |
251 | return; |
252 | ||
c8933c3f | 253 | snd_rawmidi_receive(substream, data, length); |
d5daf49b DM |
254 | } |
255 | ||
256 | static void f_midi_handle_out_data(struct usb_ep *ep, struct usb_request *req) | |
257 | { | |
258 | unsigned int i; | |
259 | u8 *buf = req->buf; | |
260 | ||
261 | for (i = 0; i + 3 < req->actual; i += 4) | |
262 | if (buf[i] != 0) { | |
263 | int cable = buf[i] >> 4; | |
264 | int length = f_midi_cin_length[buf[i] & 0x0f]; | |
265 | f_midi_read_data(ep, cable, &buf[i + 1], length); | |
266 | } | |
267 | } | |
268 | ||
269 | static void | |
270 | f_midi_complete(struct usb_ep *ep, struct usb_request *req) | |
271 | { | |
272 | struct f_midi *midi = ep->driver_data; | |
273 | struct usb_composite_dev *cdev = midi->func.config->cdev; | |
274 | int status = req->status; | |
275 | ||
276 | switch (status) { | |
277 | case 0: /* normal completion */ | |
278 | if (ep == midi->out_ep) { | |
279 | /* We received stuff. req is queued again, below */ | |
280 | f_midi_handle_out_data(ep, req); | |
281 | } else if (ep == midi->in_ep) { | |
282 | /* Our transmit completed. See if there's more to go. | |
283 | * f_midi_transmit eats req, don't queue it again. */ | |
e1e3d7ec FT |
284 | req->length = 0; |
285 | f_midi_transmit(midi); | |
d5daf49b DM |
286 | return; |
287 | } | |
288 | break; | |
289 | ||
290 | /* this endpoint is normally active while we're configured */ | |
291 | case -ECONNABORTED: /* hardware forced ep reset */ | |
292 | case -ECONNRESET: /* request dequeued */ | |
293 | case -ESHUTDOWN: /* disconnect from host */ | |
294 | VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status, | |
295 | req->actual, req->length); | |
e1e3d7ec | 296 | if (ep == midi->out_ep) { |
d5daf49b | 297 | f_midi_handle_out_data(ep, req); |
e1e3d7ec FT |
298 | /* We don't need to free IN requests because it's handled |
299 | * by the midi->in_req_fifo. */ | |
300 | free_ep_req(ep, req); | |
301 | } | |
d5daf49b DM |
302 | return; |
303 | ||
304 | case -EOVERFLOW: /* buffer overrun on read means that | |
305 | * we didn't provide a big enough buffer. | |
306 | */ | |
307 | default: | |
308 | DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name, | |
309 | status, req->actual, req->length); | |
310 | break; | |
311 | case -EREMOTEIO: /* short read */ | |
312 | break; | |
313 | } | |
314 | ||
315 | status = usb_ep_queue(ep, req, GFP_ATOMIC); | |
316 | if (status) { | |
317 | ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n", | |
318 | ep->name, req->length, status); | |
319 | usb_ep_set_halt(ep); | |
320 | /* FIXME recover later ... somehow */ | |
321 | } | |
322 | } | |
323 | ||
f8ca46ae FT |
324 | static void f_midi_drop_out_substreams(struct f_midi *midi) |
325 | { | |
326 | unsigned int i; | |
327 | ||
328 | for (i = 0; i < midi->in_ports; i++) { | |
329 | struct gmidi_in_port *port = midi->in_ports_array + i; | |
330 | struct snd_rawmidi_substream *substream = port->substream; | |
331 | ||
332 | if (port->active && substream) | |
333 | snd_rawmidi_drop_output(substream); | |
334 | } | |
335 | } | |
336 | ||
d5daf49b DM |
337 | static int f_midi_start_ep(struct f_midi *midi, |
338 | struct usb_function *f, | |
339 | struct usb_ep *ep) | |
340 | { | |
341 | int err; | |
342 | struct usb_composite_dev *cdev = f->config->cdev; | |
343 | ||
ce723951 | 344 | usb_ep_disable(ep); |
d5daf49b DM |
345 | |
346 | err = config_ep_by_speed(midi->gadget, f, ep); | |
347 | if (err) { | |
348 | ERROR(cdev, "can't configure %s: %d\n", ep->name, err); | |
349 | return err; | |
350 | } | |
351 | ||
352 | err = usb_ep_enable(ep); | |
353 | if (err) { | |
354 | ERROR(cdev, "can't start %s: %d\n", ep->name, err); | |
355 | return err; | |
356 | } | |
357 | ||
358 | ep->driver_data = midi; | |
359 | ||
360 | return 0; | |
361 | } | |
362 | ||
363 | static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |
364 | { | |
365 | struct f_midi *midi = func_to_midi(f); | |
d5daf49b DM |
366 | unsigned i; |
367 | int err; | |
368 | ||
919de443 FT |
369 | /* we only set alt for MIDIStreaming interface */ |
370 | if (intf != midi->ms_id) | |
4ef7a4a1 RB |
371 | return 0; |
372 | ||
d5daf49b DM |
373 | err = f_midi_start_ep(midi, f, midi->in_ep); |
374 | if (err) | |
375 | return err; | |
376 | ||
377 | err = f_midi_start_ep(midi, f, midi->out_ep); | |
378 | if (err) | |
379 | return err; | |
380 | ||
e1e3d7ec FT |
381 | /* pre-allocate write usb requests to use on f_midi_transmit. */ |
382 | while (kfifo_avail(&midi->in_req_fifo)) { | |
383 | struct usb_request *req = | |
384 | midi_alloc_ep_req(midi->in_ep, midi->buflen); | |
385 | ||
386 | if (req == NULL) | |
387 | return -ENOMEM; | |
388 | ||
389 | req->length = 0; | |
390 | req->complete = f_midi_complete; | |
391 | ||
392 | kfifo_put(&midi->in_req_fifo, req); | |
393 | } | |
394 | ||
d5daf49b DM |
395 | /* allocate a bunch of read buffers and queue them all at once. */ |
396 | for (i = 0; i < midi->qlen && err == 0; i++) { | |
397 | struct usb_request *req = | |
4a655f15 FT |
398 | midi_alloc_ep_req(midi->out_ep, midi->buflen); |
399 | ||
d5daf49b DM |
400 | if (req == NULL) |
401 | return -ENOMEM; | |
402 | ||
403 | req->complete = f_midi_complete; | |
404 | err = usb_ep_queue(midi->out_ep, req, GFP_ATOMIC); | |
405 | if (err) { | |
f0f1b8ca | 406 | ERROR(midi, "%s: couldn't enqueue request: %d\n", |
d5daf49b | 407 | midi->out_ep->name, err); |
7fafcfdf YT |
408 | if (req->buf != NULL) |
409 | free_ep_req(midi->out_ep, req); | |
f0f1b8ca | 410 | return err; |
d5daf49b DM |
411 | } |
412 | } | |
413 | ||
414 | return 0; | |
415 | } | |
416 | ||
417 | static void f_midi_disable(struct usb_function *f) | |
418 | { | |
419 | struct f_midi *midi = func_to_midi(f); | |
420 | struct usb_composite_dev *cdev = f->config->cdev; | |
e1e3d7ec | 421 | struct usb_request *req = NULL; |
d5daf49b DM |
422 | |
423 | DBG(cdev, "disable\n"); | |
424 | ||
425 | /* | |
426 | * just disable endpoints, forcing completion of pending i/o. | |
427 | * all our completion handlers free their requests in this case. | |
428 | */ | |
429 | usb_ep_disable(midi->in_ep); | |
430 | usb_ep_disable(midi->out_ep); | |
e1e3d7ec FT |
431 | |
432 | /* release IN requests */ | |
433 | while (kfifo_get(&midi->in_req_fifo, &req)) | |
434 | free_ep_req(midi->in_ep, req); | |
f8ca46ae FT |
435 | |
436 | f_midi_drop_out_substreams(midi); | |
d5daf49b DM |
437 | } |
438 | ||
d5daf49b DM |
439 | static int f_midi_snd_free(struct snd_device *device) |
440 | { | |
441 | return 0; | |
442 | } | |
443 | ||
d5daf49b DM |
444 | /* |
445 | * Converts MIDI commands to USB MIDI packets. | |
446 | */ | |
447 | static void f_midi_transmit_byte(struct usb_request *req, | |
448 | struct gmidi_in_port *port, uint8_t b) | |
449 | { | |
f42ab18c FT |
450 | uint8_t p[4] = { port->cable << 4, 0, 0, 0 }; |
451 | uint8_t next_state = STATE_INITIAL; | |
452 | ||
453 | switch (b) { | |
454 | case 0xf8 ... 0xff: | |
455 | /* System Real-Time Messages */ | |
456 | p[0] |= 0x0f; | |
457 | p[1] = b; | |
458 | next_state = port->state; | |
459 | port->state = STATE_REAL_TIME; | |
460 | break; | |
461 | ||
462 | case 0xf7: | |
463 | /* End of SysEx */ | |
464 | switch (port->state) { | |
465 | case STATE_SYSEX_0: | |
466 | p[0] |= 0x05; | |
467 | p[1] = 0xf7; | |
468 | next_state = STATE_FINISHED; | |
469 | break; | |
470 | case STATE_SYSEX_1: | |
471 | p[0] |= 0x06; | |
472 | p[1] = port->data[0]; | |
473 | p[2] = 0xf7; | |
474 | next_state = STATE_FINISHED; | |
475 | break; | |
476 | case STATE_SYSEX_2: | |
477 | p[0] |= 0x07; | |
478 | p[1] = port->data[0]; | |
479 | p[2] = port->data[1]; | |
480 | p[3] = 0xf7; | |
481 | next_state = STATE_FINISHED; | |
482 | break; | |
483 | default: | |
484 | /* Ignore byte */ | |
485 | next_state = port->state; | |
486 | port->state = STATE_INITIAL; | |
487 | } | |
488 | break; | |
d5daf49b | 489 | |
f42ab18c FT |
490 | case 0xf0 ... 0xf6: |
491 | /* System Common Messages */ | |
492 | port->data[0] = port->data[1] = 0; | |
493 | port->state = STATE_INITIAL; | |
d5daf49b DM |
494 | switch (b) { |
495 | case 0xf0: | |
496 | port->data[0] = b; | |
f42ab18c FT |
497 | port->data[1] = 0; |
498 | next_state = STATE_SYSEX_1; | |
d5daf49b DM |
499 | break; |
500 | case 0xf1: | |
501 | case 0xf3: | |
502 | port->data[0] = b; | |
f42ab18c | 503 | next_state = STATE_1PARAM; |
d5daf49b DM |
504 | break; |
505 | case 0xf2: | |
506 | port->data[0] = b; | |
f42ab18c | 507 | next_state = STATE_2PARAM_1; |
d5daf49b DM |
508 | break; |
509 | case 0xf4: | |
510 | case 0xf5: | |
f42ab18c | 511 | next_state = STATE_INITIAL; |
d5daf49b DM |
512 | break; |
513 | case 0xf6: | |
f42ab18c FT |
514 | p[0] |= 0x05; |
515 | p[1] = 0xf6; | |
516 | next_state = STATE_FINISHED; | |
d5daf49b DM |
517 | break; |
518 | } | |
f42ab18c FT |
519 | break; |
520 | ||
521 | case 0x80 ... 0xef: | |
522 | /* | |
523 | * Channel Voice Messages, Channel Mode Messages | |
524 | * and Control Change Messages. | |
525 | */ | |
d5daf49b | 526 | port->data[0] = b; |
f42ab18c FT |
527 | port->data[1] = 0; |
528 | port->state = STATE_INITIAL; | |
d5daf49b | 529 | if (b >= 0xc0 && b <= 0xdf) |
f42ab18c | 530 | next_state = STATE_1PARAM; |
d5daf49b | 531 | else |
f42ab18c FT |
532 | next_state = STATE_2PARAM_1; |
533 | break; | |
534 | ||
535 | case 0x00 ... 0x7f: | |
536 | /* Message parameters */ | |
d5daf49b DM |
537 | switch (port->state) { |
538 | case STATE_1PARAM: | |
f42ab18c FT |
539 | if (port->data[0] < 0xf0) |
540 | p[0] |= port->data[0] >> 4; | |
541 | else | |
542 | p[0] |= 0x02; | |
543 | ||
544 | p[1] = port->data[0]; | |
545 | p[2] = b; | |
546 | /* This is to allow Running State Messages */ | |
547 | next_state = STATE_1PARAM; | |
d5daf49b DM |
548 | break; |
549 | case STATE_2PARAM_1: | |
550 | port->data[1] = b; | |
f42ab18c | 551 | next_state = STATE_2PARAM_2; |
d5daf49b DM |
552 | break; |
553 | case STATE_2PARAM_2: | |
f42ab18c FT |
554 | if (port->data[0] < 0xf0) |
555 | p[0] |= port->data[0] >> 4; | |
556 | else | |
557 | p[0] |= 0x03; | |
558 | ||
559 | p[1] = port->data[0]; | |
560 | p[2] = port->data[1]; | |
561 | p[3] = b; | |
562 | /* This is to allow Running State Messages */ | |
563 | next_state = STATE_2PARAM_1; | |
d5daf49b DM |
564 | break; |
565 | case STATE_SYSEX_0: | |
566 | port->data[0] = b; | |
f42ab18c | 567 | next_state = STATE_SYSEX_1; |
d5daf49b DM |
568 | break; |
569 | case STATE_SYSEX_1: | |
570 | port->data[1] = b; | |
f42ab18c | 571 | next_state = STATE_SYSEX_2; |
d5daf49b DM |
572 | break; |
573 | case STATE_SYSEX_2: | |
f42ab18c FT |
574 | p[0] |= 0x04; |
575 | p[1] = port->data[0]; | |
576 | p[2] = port->data[1]; | |
577 | p[3] = b; | |
578 | next_state = STATE_SYSEX_0; | |
d5daf49b DM |
579 | break; |
580 | } | |
f42ab18c FT |
581 | break; |
582 | } | |
583 | ||
584 | /* States where we have to write into the USB request */ | |
585 | if (next_state == STATE_FINISHED || | |
586 | port->state == STATE_SYSEX_2 || | |
587 | port->state == STATE_1PARAM || | |
588 | port->state == STATE_2PARAM_2 || | |
589 | port->state == STATE_REAL_TIME) { | |
590 | ||
591 | unsigned int length = req->length; | |
592 | u8 *buf = (u8 *)req->buf + length; | |
593 | ||
594 | memcpy(buf, p, sizeof(p)); | |
595 | req->length = length + sizeof(p); | |
596 | ||
597 | if (next_state == STATE_FINISHED) { | |
598 | next_state = STATE_INITIAL; | |
599 | port->data[0] = port->data[1] = 0; | |
600 | } | |
d5daf49b | 601 | } |
f42ab18c FT |
602 | |
603 | port->state = next_state; | |
d5daf49b DM |
604 | } |
605 | ||
9a71eb56 | 606 | static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) |
e1e3d7ec | 607 | { |
9a71eb56 MN |
608 | struct usb_request *req = NULL; |
609 | unsigned int len, i; | |
610 | bool active = false; | |
611 | int err; | |
e1e3d7ec | 612 | |
9a71eb56 MN |
613 | /* |
614 | * We peek the request in order to reuse it if it fails to enqueue on | |
615 | * its endpoint | |
616 | */ | |
617 | len = kfifo_peek(&midi->in_req_fifo, &req); | |
618 | if (len != 1) { | |
619 | ERROR(midi, "%s: Couldn't get usb request\n", __func__); | |
620 | return -1; | |
621 | } | |
e1e3d7ec | 622 | |
9a71eb56 MN |
623 | /* |
624 | * If buffer overrun, then we ignore this transmission. | |
625 | * IMPORTANT: This will cause the user-space rawmidi device to block | |
626 | * until a) usb requests have been completed or b) snd_rawmidi_write() | |
627 | * times out. | |
628 | */ | |
629 | if (req->length > 0) | |
630 | return 0; | |
e1e3d7ec | 631 | |
bf0028f8 MN |
632 | for (i = midi->in_last_port; i < midi->in_ports; ++i) { |
633 | struct gmidi_in_port *port = midi->in_ports_array + i; | |
4111d494 | 634 | struct snd_rawmidi_substream *substream = port->substream; |
bf0028f8 | 635 | |
9a71eb56 MN |
636 | if (!port->active || !substream) |
637 | continue; | |
e1e3d7ec | 638 | |
9a71eb56 MN |
639 | while (req->length + 3 < midi->buflen) { |
640 | uint8_t b; | |
e1e3d7ec | 641 | |
9a71eb56 MN |
642 | if (snd_rawmidi_transmit(substream, &b, 1) != 1) { |
643 | port->active = 0; | |
e1e3d7ec FT |
644 | break; |
645 | } | |
9a71eb56 MN |
646 | f_midi_transmit_byte(req, port, b); |
647 | } | |
e1e3d7ec | 648 | |
9a71eb56 | 649 | active = !!port->active; |
06cd928b | 650 | if (active) |
9a71eb56 | 651 | break; |
9a71eb56 | 652 | } |
06cd928b | 653 | midi->in_last_port = active ? i : 0; |
e1e3d7ec | 654 | |
9a71eb56 | 655 | if (req->length <= 0) |
06cd928b | 656 | goto done; |
9a71eb56 MN |
657 | |
658 | err = usb_ep_queue(ep, req, GFP_ATOMIC); | |
659 | if (err < 0) { | |
660 | ERROR(midi, "%s failed to queue req: %d\n", | |
661 | midi->in_ep->name, err); | |
662 | req->length = 0; /* Re-use request next time. */ | |
663 | } else { | |
664 | /* Upon success, put request at the back of the queue. */ | |
665 | kfifo_skip(&midi->in_req_fifo); | |
666 | kfifo_put(&midi->in_req_fifo, req); | |
667 | } | |
e1e3d7ec | 668 | |
06cd928b | 669 | done: |
9a71eb56 MN |
670 | return active; |
671 | } | |
e1e3d7ec | 672 | |
9a71eb56 MN |
673 | static void f_midi_transmit(struct f_midi *midi) |
674 | { | |
675 | struct usb_ep *ep = midi->in_ep; | |
676 | int ret; | |
9acdf4df | 677 | unsigned long flags; |
d5daf49b | 678 | |
9a71eb56 MN |
679 | /* We only care about USB requests if IN endpoint is enabled */ |
680 | if (!ep || !ep->enabled) | |
681 | goto drop_out; | |
f35fe4be | 682 | |
9acdf4df FT |
683 | spin_lock_irqsave(&midi->transmit_lock, flags); |
684 | ||
9a71eb56 MN |
685 | do { |
686 | ret = f_midi_do_transmit(midi, ep); | |
4fc50ba5 DC |
687 | if (ret < 0) { |
688 | spin_unlock_irqrestore(&midi->transmit_lock, flags); | |
9a71eb56 | 689 | goto drop_out; |
4fc50ba5 | 690 | } |
9a71eb56 | 691 | } while (ret); |
e1e3d7ec | 692 | |
9acdf4df FT |
693 | spin_unlock_irqrestore(&midi->transmit_lock, flags); |
694 | ||
e1e3d7ec FT |
695 | return; |
696 | ||
697 | drop_out: | |
698 | f_midi_drop_out_substreams(midi); | |
d5daf49b DM |
699 | } |
700 | ||
8653d71c | 701 | static void f_midi_in_work(struct work_struct *work) |
d5daf49b | 702 | { |
8653d71c DB |
703 | struct f_midi *midi; |
704 | ||
705 | midi = container_of(work, struct f_midi, work); | |
e1e3d7ec | 706 | f_midi_transmit(midi); |
d5daf49b DM |
707 | } |
708 | ||
709 | static int f_midi_in_open(struct snd_rawmidi_substream *substream) | |
710 | { | |
711 | struct f_midi *midi = substream->rmidi->private_data; | |
4111d494 | 712 | struct gmidi_in_port *port; |
d5daf49b | 713 | |
bf0028f8 | 714 | if (substream->number >= midi->in_ports) |
c8933c3f DM |
715 | return -EINVAL; |
716 | ||
d5daf49b | 717 | VDBG(midi, "%s()\n", __func__); |
4111d494 MN |
718 | port = midi->in_ports_array + substream->number; |
719 | port->substream = substream; | |
f42ab18c | 720 | port->state = STATE_INITIAL; |
d5daf49b DM |
721 | return 0; |
722 | } | |
723 | ||
724 | static int f_midi_in_close(struct snd_rawmidi_substream *substream) | |
725 | { | |
726 | struct f_midi *midi = substream->rmidi->private_data; | |
727 | ||
728 | VDBG(midi, "%s()\n", __func__); | |
729 | return 0; | |
730 | } | |
731 | ||
732 | static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up) | |
733 | { | |
734 | struct f_midi *midi = substream->rmidi->private_data; | |
735 | ||
bf0028f8 | 736 | if (substream->number >= midi->in_ports) |
c8933c3f DM |
737 | return; |
738 | ||
d5daf49b | 739 | VDBG(midi, "%s() %d\n", __func__, up); |
bf0028f8 | 740 | midi->in_ports_array[substream->number].active = up; |
d5daf49b | 741 | if (up) |
8653d71c | 742 | queue_work(system_highpri_wq, &midi->work); |
d5daf49b DM |
743 | } |
744 | ||
745 | static int f_midi_out_open(struct snd_rawmidi_substream *substream) | |
746 | { | |
747 | struct f_midi *midi = substream->rmidi->private_data; | |
748 | ||
08895512 | 749 | if (substream->number >= MAX_PORTS) |
c8933c3f DM |
750 | return -EINVAL; |
751 | ||
d5daf49b | 752 | VDBG(midi, "%s()\n", __func__); |
c8933c3f | 753 | midi->out_substream[substream->number] = substream; |
d5daf49b DM |
754 | return 0; |
755 | } | |
756 | ||
757 | static int f_midi_out_close(struct snd_rawmidi_substream *substream) | |
758 | { | |
759 | struct f_midi *midi = substream->rmidi->private_data; | |
760 | ||
761 | VDBG(midi, "%s()\n", __func__); | |
762 | return 0; | |
763 | } | |
764 | ||
765 | static void f_midi_out_trigger(struct snd_rawmidi_substream *substream, int up) | |
766 | { | |
767 | struct f_midi *midi = substream->rmidi->private_data; | |
768 | ||
769 | VDBG(midi, "%s()\n", __func__); | |
770 | ||
771 | if (up) | |
772 | set_bit(substream->number, &midi->out_triggered); | |
773 | else | |
774 | clear_bit(substream->number, &midi->out_triggered); | |
775 | } | |
776 | ||
c0542900 | 777 | static const struct snd_rawmidi_ops gmidi_in_ops = { |
d5daf49b DM |
778 | .open = f_midi_in_open, |
779 | .close = f_midi_in_close, | |
780 | .trigger = f_midi_in_trigger, | |
781 | }; | |
782 | ||
c0542900 | 783 | static const struct snd_rawmidi_ops gmidi_out_ops = { |
d5daf49b DM |
784 | .open = f_midi_out_open, |
785 | .close = f_midi_out_close, | |
786 | .trigger = f_midi_out_trigger | |
787 | }; | |
788 | ||
d23b4c3e AP |
789 | static inline void f_midi_unregister_card(struct f_midi *midi) |
790 | { | |
791 | if (midi->card) { | |
792 | snd_card_free(midi->card); | |
793 | midi->card = NULL; | |
794 | } | |
795 | } | |
796 | ||
d5daf49b DM |
797 | /* register as a sound "card" */ |
798 | static int f_midi_register_card(struct f_midi *midi) | |
799 | { | |
800 | struct snd_card *card; | |
801 | struct snd_rawmidi *rmidi; | |
802 | int err; | |
d5daf49b DM |
803 | static struct snd_device_ops ops = { |
804 | .dev_free = f_midi_snd_free, | |
805 | }; | |
806 | ||
13345095 TI |
807 | err = snd_card_new(&midi->gadget->dev, midi->index, midi->id, |
808 | THIS_MODULE, 0, &card); | |
d5daf49b | 809 | if (err < 0) { |
13345095 | 810 | ERROR(midi, "snd_card_new() failed\n"); |
d5daf49b DM |
811 | goto fail; |
812 | } | |
813 | midi->card = card; | |
814 | ||
815 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, midi, &ops); | |
816 | if (err < 0) { | |
817 | ERROR(midi, "snd_device_new() failed: error %d\n", err); | |
818 | goto fail; | |
819 | } | |
820 | ||
821 | strcpy(card->driver, f_midi_longname); | |
822 | strcpy(card->longname, f_midi_longname); | |
823 | strcpy(card->shortname, f_midi_shortname); | |
824 | ||
825 | /* Set up rawmidi */ | |
d5daf49b DM |
826 | snd_component_add(card, "MIDI"); |
827 | err = snd_rawmidi_new(card, card->longname, 0, | |
c8933c3f | 828 | midi->out_ports, midi->in_ports, &rmidi); |
d5daf49b DM |
829 | if (err < 0) { |
830 | ERROR(midi, "snd_rawmidi_new() failed: error %d\n", err); | |
831 | goto fail; | |
832 | } | |
833 | midi->rmidi = rmidi; | |
e1e3d7ec | 834 | midi->in_last_port = 0; |
d5daf49b DM |
835 | strcpy(rmidi->name, card->shortname); |
836 | rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | |
837 | SNDRV_RAWMIDI_INFO_INPUT | | |
838 | SNDRV_RAWMIDI_INFO_DUPLEX; | |
839 | rmidi->private_data = midi; | |
2d19cdc1 JZ |
840 | rmidi->private_free = f_midi_rmidi_free; |
841 | midi->free_ref++; | |
d5daf49b DM |
842 | |
843 | /* | |
844 | * Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT. | |
845 | * It's an upside-down world being a gadget. | |
846 | */ | |
847 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops); | |
848 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops); | |
849 | ||
d5daf49b DM |
850 | /* register it - we're ready to go */ |
851 | err = snd_card_register(card); | |
852 | if (err < 0) { | |
853 | ERROR(midi, "snd_card_register() failed\n"); | |
854 | goto fail; | |
855 | } | |
856 | ||
857 | VDBG(midi, "%s() finished ok\n", __func__); | |
858 | return 0; | |
859 | ||
860 | fail: | |
d23b4c3e | 861 | f_midi_unregister_card(midi); |
d5daf49b DM |
862 | return err; |
863 | } | |
864 | ||
865 | /* MIDI function driver setup/binding */ | |
866 | ||
b85e9de9 | 867 | static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) |
d5daf49b | 868 | { |
74203de0 | 869 | struct usb_descriptor_header **midi_function; |
c8933c3f | 870 | struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; |
74203de0 | 871 | struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS]; |
c8933c3f | 872 | struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS]; |
74203de0 | 873 | struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS]; |
d5daf49b DM |
874 | struct usb_composite_dev *cdev = c->cdev; |
875 | struct f_midi *midi = func_to_midi(f); | |
9caa0d77 | 876 | struct usb_string *us; |
24cf3459 | 877 | int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; |
d5daf49b | 878 | |
b85e9de9 | 879 | midi->gadget = cdev->gadget; |
8653d71c | 880 | INIT_WORK(&midi->work, f_midi_in_work); |
b85e9de9 AP |
881 | status = f_midi_register_card(midi); |
882 | if (status < 0) | |
883 | goto fail_register; | |
884 | ||
d5daf49b | 885 | /* maybe allocate device-global string ID */ |
9caa0d77 AP |
886 | us = usb_gstrings_attach(c->cdev, midi_strings, |
887 | ARRAY_SIZE(midi_string_defs)); | |
888 | if (IS_ERR(us)) { | |
889 | status = PTR_ERR(us); | |
890 | goto fail; | |
d5daf49b | 891 | } |
9caa0d77 | 892 | ac_interface_desc.iInterface = us[STRING_FUNC_IDX].id; |
d5daf49b DM |
893 | |
894 | /* We have two interfaces, AudioControl and MIDIStreaming */ | |
895 | status = usb_interface_id(c, f); | |
896 | if (status < 0) | |
897 | goto fail; | |
898 | ac_interface_desc.bInterfaceNumber = status; | |
899 | ||
900 | status = usb_interface_id(c, f); | |
901 | if (status < 0) | |
902 | goto fail; | |
903 | ms_interface_desc.bInterfaceNumber = status; | |
904 | ac_header_desc.baInterfaceNr[0] = status; | |
919de443 | 905 | midi->ms_id = status; |
d5daf49b DM |
906 | |
907 | status = -ENODEV; | |
908 | ||
909 | /* allocate instance-specific endpoints */ | |
910 | midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc); | |
911 | if (!midi->in_ep) | |
912 | goto fail; | |
d5daf49b DM |
913 | |
914 | midi->out_ep = usb_ep_autoconfig(cdev->gadget, &bulk_out_desc); | |
915 | if (!midi->out_ep) | |
916 | goto fail; | |
d5daf49b | 917 | |
74203de0 | 918 | /* allocate temporary function list */ |
24cf3459 | 919 | midi_function = kcalloc((MAX_PORTS * 4) + 11, sizeof(*midi_function), |
74203de0 DM |
920 | GFP_KERNEL); |
921 | if (!midi_function) { | |
922 | status = -ENOMEM; | |
923 | goto fail; | |
924 | } | |
925 | ||
c8933c3f DM |
926 | /* |
927 | * construct the function's descriptor set. As the number of | |
928 | * input and output MIDI ports is configurable, we have to do | |
929 | * it that way. | |
930 | */ | |
931 | ||
932 | /* add the headers - these are always the same */ | |
933 | midi_function[i++] = (struct usb_descriptor_header *) &ac_interface_desc; | |
934 | midi_function[i++] = (struct usb_descriptor_header *) &ac_header_desc; | |
935 | midi_function[i++] = (struct usb_descriptor_header *) &ms_interface_desc; | |
936 | ||
937 | /* calculate the header's wTotalLength */ | |
938 | n = USB_DT_MS_HEADER_SIZE | |
74203de0 DM |
939 | + (midi->in_ports + midi->out_ports) * |
940 | (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1)); | |
c8933c3f DM |
941 | ms_header_desc.wTotalLength = cpu_to_le16(n); |
942 | ||
943 | midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc; | |
944 | ||
74203de0 | 945 | /* configure the external IN jacks, each linked to an embedded OUT jack */ |
c8933c3f | 946 | for (n = 0; n < midi->in_ports; n++) { |
74203de0 DM |
947 | struct usb_midi_in_jack_descriptor *in_ext = &jack_in_ext_desc[n]; |
948 | struct usb_midi_out_jack_descriptor_1 *out_emb = &jack_out_emb_desc[n]; | |
949 | ||
950 | in_ext->bLength = USB_DT_MIDI_IN_SIZE; | |
951 | in_ext->bDescriptorType = USB_DT_CS_INTERFACE; | |
952 | in_ext->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; | |
953 | in_ext->bJackType = USB_MS_EXTERNAL; | |
954 | in_ext->bJackID = jack++; | |
955 | in_ext->iJack = 0; | |
956 | midi_function[i++] = (struct usb_descriptor_header *) in_ext; | |
957 | ||
958 | out_emb->bLength = USB_DT_MIDI_OUT_SIZE(1); | |
959 | out_emb->bDescriptorType = USB_DT_CS_INTERFACE; | |
960 | out_emb->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; | |
961 | out_emb->bJackType = USB_MS_EMBEDDED; | |
962 | out_emb->bJackID = jack++; | |
963 | out_emb->bNrInputPins = 1; | |
964 | out_emb->pins[0].baSourcePin = 1; | |
965 | out_emb->pins[0].baSourceID = in_ext->bJackID; | |
966 | out_emb->iJack = 0; | |
967 | midi_function[i++] = (struct usb_descriptor_header *) out_emb; | |
968 | ||
969 | /* link it to the endpoint */ | |
970 | ms_in_desc.baAssocJackID[n] = out_emb->bJackID; | |
c8933c3f DM |
971 | } |
972 | ||
74203de0 | 973 | /* configure the external OUT jacks, each linked to an embedded IN jack */ |
c8933c3f | 974 | for (n = 0; n < midi->out_ports; n++) { |
74203de0 DM |
975 | struct usb_midi_in_jack_descriptor *in_emb = &jack_in_emb_desc[n]; |
976 | struct usb_midi_out_jack_descriptor_1 *out_ext = &jack_out_ext_desc[n]; | |
977 | ||
978 | in_emb->bLength = USB_DT_MIDI_IN_SIZE; | |
979 | in_emb->bDescriptorType = USB_DT_CS_INTERFACE; | |
980 | in_emb->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; | |
981 | in_emb->bJackType = USB_MS_EMBEDDED; | |
982 | in_emb->bJackID = jack++; | |
983 | in_emb->iJack = 0; | |
984 | midi_function[i++] = (struct usb_descriptor_header *) in_emb; | |
985 | ||
986 | out_ext->bLength = USB_DT_MIDI_OUT_SIZE(1); | |
987 | out_ext->bDescriptorType = USB_DT_CS_INTERFACE; | |
988 | out_ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; | |
989 | out_ext->bJackType = USB_MS_EXTERNAL; | |
990 | out_ext->bJackID = jack++; | |
991 | out_ext->bNrInputPins = 1; | |
992 | out_ext->iJack = 0; | |
993 | out_ext->pins[0].baSourceID = in_emb->bJackID; | |
994 | out_ext->pins[0].baSourcePin = 1; | |
995 | midi_function[i++] = (struct usb_descriptor_header *) out_ext; | |
996 | ||
997 | /* link it to the endpoint */ | |
998 | ms_out_desc.baAssocJackID[n] = in_emb->bJackID; | |
c8933c3f DM |
999 | } |
1000 | ||
1001 | /* configure the endpoint descriptors ... */ | |
1002 | ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); | |
1003 | ms_out_desc.bNumEmbMIDIJack = midi->in_ports; | |
c8933c3f DM |
1004 | |
1005 | ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); | |
1006 | ms_in_desc.bNumEmbMIDIJack = midi->out_ports; | |
c8933c3f DM |
1007 | |
1008 | /* ... and add them to the list */ | |
24cf3459 | 1009 | endpoint_descriptor_index = i; |
c8933c3f DM |
1010 | midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc; |
1011 | midi_function[i++] = (struct usb_descriptor_header *) &ms_out_desc; | |
1012 | midi_function[i++] = (struct usb_descriptor_header *) &bulk_in_desc; | |
1013 | midi_function[i++] = (struct usb_descriptor_header *) &ms_in_desc; | |
1014 | midi_function[i++] = NULL; | |
1015 | ||
d5daf49b DM |
1016 | /* |
1017 | * support all relevant hardware speeds... we expect that when | |
1018 | * hardware is dual speed, all bulk-capable endpoints work at | |
1019 | * both speeds | |
1020 | */ | |
1021 | /* copy descriptors, and track endpoint copies */ | |
10287bae SAS |
1022 | f->fs_descriptors = usb_copy_descriptors(midi_function); |
1023 | if (!f->fs_descriptors) | |
7f2a9268 | 1024 | goto fail_f_midi; |
10287bae | 1025 | |
46decc82 LY |
1026 | bulk_in_desc.wMaxPacketSize = cpu_to_le16(512); |
1027 | bulk_out_desc.wMaxPacketSize = cpu_to_le16(512); | |
1028 | f->hs_descriptors = usb_copy_descriptors(midi_function); | |
1029 | if (!f->hs_descriptors) | |
1030 | goto fail_f_midi; | |
d5daf49b | 1031 | |
46decc82 LY |
1032 | bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024); |
1033 | bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024); | |
1034 | i = endpoint_descriptor_index; | |
1035 | midi_function[i++] = (struct usb_descriptor_header *) | |
1036 | &bulk_out_desc; | |
1037 | midi_function[i++] = (struct usb_descriptor_header *) | |
1038 | &bulk_out_ss_comp_desc; | |
1039 | midi_function[i++] = (struct usb_descriptor_header *) | |
1040 | &ms_out_desc; | |
1041 | midi_function[i++] = (struct usb_descriptor_header *) | |
1042 | &bulk_in_desc; | |
1043 | midi_function[i++] = (struct usb_descriptor_header *) | |
1044 | &bulk_in_ss_comp_desc; | |
1045 | midi_function[i++] = (struct usb_descriptor_header *) | |
1046 | &ms_in_desc; | |
1047 | f->ss_descriptors = usb_copy_descriptors(midi_function); | |
1048 | if (!f->ss_descriptors) | |
1049 | goto fail_f_midi; | |
24cf3459 | 1050 | |
74203de0 DM |
1051 | kfree(midi_function); |
1052 | ||
d5daf49b DM |
1053 | return 0; |
1054 | ||
7f2a9268 SAS |
1055 | fail_f_midi: |
1056 | kfree(midi_function); | |
24cf3459 | 1057 | usb_free_all_descriptors(f); |
d5daf49b | 1058 | fail: |
b85e9de9 AP |
1059 | f_midi_unregister_card(midi); |
1060 | fail_register: | |
d5daf49b DM |
1061 | ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); |
1062 | ||
1063 | return status; | |
1064 | } | |
1065 | ||
6f1de344 AP |
1066 | static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item) |
1067 | { | |
1068 | return container_of(to_config_group(item), struct f_midi_opts, | |
1069 | func_inst.group); | |
1070 | } | |
1071 | ||
6f1de344 AP |
1072 | static void midi_attr_release(struct config_item *item) |
1073 | { | |
1074 | struct f_midi_opts *opts = to_f_midi_opts(item); | |
1075 | ||
1076 | usb_put_function_instance(&opts->func_inst); | |
1077 | } | |
1078 | ||
1079 | static struct configfs_item_operations midi_item_ops = { | |
1080 | .release = midi_attr_release, | |
6f1de344 AP |
1081 | }; |
1082 | ||
1083 | #define F_MIDI_OPT(name, test_limit, limit) \ | |
3755a273 | 1084 | static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \ |
6f1de344 | 1085 | { \ |
3755a273 | 1086 | struct f_midi_opts *opts = to_f_midi_opts(item); \ |
6f1de344 AP |
1087 | int result; \ |
1088 | \ | |
1089 | mutex_lock(&opts->lock); \ | |
d4299761 | 1090 | result = sprintf(page, "%u\n", opts->name); \ |
6f1de344 AP |
1091 | mutex_unlock(&opts->lock); \ |
1092 | \ | |
1093 | return result; \ | |
1094 | } \ | |
1095 | \ | |
3755a273 | 1096 | static ssize_t f_midi_opts_##name##_store(struct config_item *item, \ |
6f1de344 AP |
1097 | const char *page, size_t len) \ |
1098 | { \ | |
3755a273 | 1099 | struct f_midi_opts *opts = to_f_midi_opts(item); \ |
6f1de344 AP |
1100 | int ret; \ |
1101 | u32 num; \ | |
1102 | \ | |
1103 | mutex_lock(&opts->lock); \ | |
9286e24b | 1104 | if (opts->refcnt > 1) { \ |
6f1de344 AP |
1105 | ret = -EBUSY; \ |
1106 | goto end; \ | |
1107 | } \ | |
1108 | \ | |
1109 | ret = kstrtou32(page, 0, &num); \ | |
1110 | if (ret) \ | |
1111 | goto end; \ | |
1112 | \ | |
1113 | if (test_limit && num > limit) { \ | |
1114 | ret = -EINVAL; \ | |
1115 | goto end; \ | |
1116 | } \ | |
1117 | opts->name = num; \ | |
1118 | ret = len; \ | |
1119 | \ | |
1120 | end: \ | |
1121 | mutex_unlock(&opts->lock); \ | |
1122 | return ret; \ | |
1123 | } \ | |
1124 | \ | |
3755a273 | 1125 | CONFIGFS_ATTR(f_midi_opts_, name); |
6f1de344 | 1126 | |
d4299761 JK |
1127 | #define F_MIDI_OPT_SIGNED(name, test_limit, limit) \ |
1128 | static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \ | |
1129 | { \ | |
1130 | struct f_midi_opts *opts = to_f_midi_opts(item); \ | |
1131 | int result; \ | |
1132 | \ | |
1133 | mutex_lock(&opts->lock); \ | |
1134 | result = sprintf(page, "%d\n", opts->name); \ | |
1135 | mutex_unlock(&opts->lock); \ | |
1136 | \ | |
1137 | return result; \ | |
1138 | } \ | |
1139 | \ | |
1140 | static ssize_t f_midi_opts_##name##_store(struct config_item *item, \ | |
1141 | const char *page, size_t len) \ | |
1142 | { \ | |
1143 | struct f_midi_opts *opts = to_f_midi_opts(item); \ | |
1144 | int ret; \ | |
1145 | s32 num; \ | |
1146 | \ | |
1147 | mutex_lock(&opts->lock); \ | |
1148 | if (opts->refcnt > 1) { \ | |
1149 | ret = -EBUSY; \ | |
1150 | goto end; \ | |
1151 | } \ | |
1152 | \ | |
1153 | ret = kstrtos32(page, 0, &num); \ | |
1154 | if (ret) \ | |
1155 | goto end; \ | |
1156 | \ | |
1157 | if (test_limit && num > limit) { \ | |
1158 | ret = -EINVAL; \ | |
1159 | goto end; \ | |
1160 | } \ | |
1161 | opts->name = num; \ | |
1162 | ret = len; \ | |
1163 | \ | |
1164 | end: \ | |
1165 | mutex_unlock(&opts->lock); \ | |
1166 | return ret; \ | |
1167 | } \ | |
1168 | \ | |
1169 | CONFIGFS_ATTR(f_midi_opts_, name); | |
1170 | ||
1171 | F_MIDI_OPT_SIGNED(index, true, SNDRV_CARDS); | |
6f1de344 AP |
1172 | F_MIDI_OPT(buflen, false, 0); |
1173 | F_MIDI_OPT(qlen, false, 0); | |
1174 | F_MIDI_OPT(in_ports, true, MAX_PORTS); | |
1175 | F_MIDI_OPT(out_ports, true, MAX_PORTS); | |
1176 | ||
3755a273 | 1177 | static ssize_t f_midi_opts_id_show(struct config_item *item, char *page) |
6f1de344 | 1178 | { |
3755a273 | 1179 | struct f_midi_opts *opts = to_f_midi_opts(item); |
6f1de344 AP |
1180 | int result; |
1181 | ||
1182 | mutex_lock(&opts->lock); | |
a25a23cc PS |
1183 | if (opts->id) { |
1184 | result = strlcpy(page, opts->id, PAGE_SIZE); | |
1185 | } else { | |
1186 | page[0] = 0; | |
1187 | result = 0; | |
1188 | } | |
1189 | ||
6f1de344 AP |
1190 | mutex_unlock(&opts->lock); |
1191 | ||
1192 | return result; | |
1193 | } | |
1194 | ||
3755a273 | 1195 | static ssize_t f_midi_opts_id_store(struct config_item *item, |
6f1de344 AP |
1196 | const char *page, size_t len) |
1197 | { | |
3755a273 | 1198 | struct f_midi_opts *opts = to_f_midi_opts(item); |
6f1de344 AP |
1199 | int ret; |
1200 | char *c; | |
1201 | ||
1202 | mutex_lock(&opts->lock); | |
9286e24b | 1203 | if (opts->refcnt > 1) { |
6f1de344 AP |
1204 | ret = -EBUSY; |
1205 | goto end; | |
1206 | } | |
1207 | ||
1208 | c = kstrndup(page, len, GFP_KERNEL); | |
1209 | if (!c) { | |
1210 | ret = -ENOMEM; | |
1211 | goto end; | |
1212 | } | |
1213 | if (opts->id_allocated) | |
1214 | kfree(opts->id); | |
1215 | opts->id = c; | |
1216 | opts->id_allocated = true; | |
1217 | ret = len; | |
1218 | end: | |
1219 | mutex_unlock(&opts->lock); | |
1220 | return ret; | |
1221 | } | |
1222 | ||
3755a273 | 1223 | CONFIGFS_ATTR(f_midi_opts_, id); |
6f1de344 AP |
1224 | |
1225 | static struct configfs_attribute *midi_attrs[] = { | |
3755a273 CH |
1226 | &f_midi_opts_attr_index, |
1227 | &f_midi_opts_attr_buflen, | |
1228 | &f_midi_opts_attr_qlen, | |
1229 | &f_midi_opts_attr_in_ports, | |
1230 | &f_midi_opts_attr_out_ports, | |
1231 | &f_midi_opts_attr_id, | |
6f1de344 AP |
1232 | NULL, |
1233 | }; | |
1234 | ||
97363902 | 1235 | static const struct config_item_type midi_func_type = { |
6f1de344 AP |
1236 | .ct_item_ops = &midi_item_ops, |
1237 | .ct_attrs = midi_attrs, | |
1238 | .ct_owner = THIS_MODULE, | |
1239 | }; | |
1240 | ||
b85e9de9 AP |
1241 | static void f_midi_free_inst(struct usb_function_instance *f) |
1242 | { | |
1243 | struct f_midi_opts *opts; | |
9286e24b | 1244 | bool free = false; |
b85e9de9 AP |
1245 | |
1246 | opts = container_of(f, struct f_midi_opts, func_inst); | |
1247 | ||
9286e24b JZ |
1248 | mutex_lock(&opts->lock); |
1249 | if (!--opts->refcnt) { | |
1250 | free = true; | |
1251 | } | |
1252 | mutex_unlock(&opts->lock); | |
6f1de344 | 1253 | |
9286e24b JZ |
1254 | if (free) { |
1255 | if (opts->id_allocated) | |
1256 | kfree(opts->id); | |
1257 | kfree(opts); | |
1258 | } | |
b85e9de9 AP |
1259 | } |
1260 | ||
1261 | static struct usb_function_instance *f_midi_alloc_inst(void) | |
1262 | { | |
1263 | struct f_midi_opts *opts; | |
1264 | ||
1265 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | |
1266 | if (!opts) | |
1267 | return ERR_PTR(-ENOMEM); | |
6f1de344 AP |
1268 | |
1269 | mutex_init(&opts->lock); | |
b85e9de9 | 1270 | opts->func_inst.free_func_inst = f_midi_free_inst; |
6f1de344 AP |
1271 | opts->index = SNDRV_DEFAULT_IDX1; |
1272 | opts->id = SNDRV_DEFAULT_STR1; | |
7ea9fde7 | 1273 | opts->buflen = 512; |
6f1de344 AP |
1274 | opts->qlen = 32; |
1275 | opts->in_ports = 1; | |
1276 | opts->out_ports = 1; | |
9286e24b | 1277 | opts->refcnt = 1; |
6f1de344 AP |
1278 | |
1279 | config_group_init_type_name(&opts->func_inst.group, "", | |
1280 | &midi_func_type); | |
b85e9de9 AP |
1281 | |
1282 | return &opts->func_inst; | |
1283 | } | |
1284 | ||
1285 | static void f_midi_free(struct usb_function *f) | |
1286 | { | |
1287 | struct f_midi *midi; | |
1288 | struct f_midi_opts *opts; | |
9286e24b | 1289 | bool free = false; |
b85e9de9 AP |
1290 | |
1291 | midi = func_to_midi(f); | |
1292 | opts = container_of(f->fi, struct f_midi_opts, func_inst); | |
6f1de344 | 1293 | mutex_lock(&opts->lock); |
2d19cdc1 JZ |
1294 | if (!--midi->free_ref) { |
1295 | kfree(midi->id); | |
1296 | kfifo_free(&midi->in_req_fifo); | |
1297 | kfree(midi); | |
9286e24b | 1298 | free = true; |
2d19cdc1 | 1299 | } |
6f1de344 | 1300 | mutex_unlock(&opts->lock); |
9286e24b JZ |
1301 | |
1302 | if (free) | |
1303 | f_midi_free_inst(&opts->func_inst); | |
b85e9de9 AP |
1304 | } |
1305 | ||
2d19cdc1 JZ |
1306 | static void f_midi_rmidi_free(struct snd_rawmidi *rmidi) |
1307 | { | |
1308 | f_midi_free(rmidi->private_data); | |
1309 | } | |
1310 | ||
b85e9de9 AP |
1311 | static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) |
1312 | { | |
1313 | struct usb_composite_dev *cdev = f->config->cdev; | |
1314 | struct f_midi *midi = func_to_midi(f); | |
1315 | struct snd_card *card; | |
1316 | ||
1317 | DBG(cdev, "unbind\n"); | |
1318 | ||
1319 | /* just to be sure */ | |
1320 | f_midi_disable(f); | |
1321 | ||
1322 | card = midi->card; | |
1323 | midi->card = NULL; | |
1324 | if (card) | |
2d19cdc1 | 1325 | snd_card_free_when_closed(card); |
b85e9de9 AP |
1326 | |
1327 | usb_free_all_descriptors(f); | |
1328 | } | |
1329 | ||
f509fee8 | 1330 | static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) |
b85e9de9 | 1331 | { |
413489c8 | 1332 | struct f_midi *midi = NULL; |
b85e9de9 AP |
1333 | struct f_midi_opts *opts; |
1334 | int status, i; | |
1335 | ||
1336 | opts = container_of(fi, struct f_midi_opts, func_inst); | |
6f1de344 AP |
1337 | |
1338 | mutex_lock(&opts->lock); | |
b85e9de9 | 1339 | /* sanity check */ |
6f1de344 | 1340 | if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS) { |
413489c8 DC |
1341 | status = -EINVAL; |
1342 | goto setup_fail; | |
6f1de344 | 1343 | } |
b85e9de9 AP |
1344 | |
1345 | /* allocate and initialize one new instance */ | |
acafe7e3 KC |
1346 | midi = kzalloc(struct_size(midi, in_ports_array, opts->in_ports), |
1347 | GFP_KERNEL); | |
6f1de344 | 1348 | if (!midi) { |
413489c8 DC |
1349 | status = -ENOMEM; |
1350 | goto setup_fail; | |
6f1de344 | 1351 | } |
18271702 | 1352 | midi->in_ports = opts->in_ports; |
b85e9de9 | 1353 | |
bf0028f8 MN |
1354 | for (i = 0; i < opts->in_ports; i++) |
1355 | midi->in_ports_array[i].cable = i; | |
b85e9de9 AP |
1356 | |
1357 | /* set up ALSA midi devices */ | |
1358 | midi->id = kstrdup(opts->id, GFP_KERNEL); | |
1359 | if (opts->id && !midi->id) { | |
1360 | status = -ENOMEM; | |
e7694cb6 | 1361 | goto midi_free; |
b85e9de9 | 1362 | } |
b85e9de9 AP |
1363 | midi->out_ports = opts->out_ports; |
1364 | midi->index = opts->index; | |
1365 | midi->buflen = opts->buflen; | |
1366 | midi->qlen = opts->qlen; | |
e1e3d7ec | 1367 | midi->in_last_port = 0; |
2d19cdc1 | 1368 | midi->free_ref = 1; |
e1e3d7ec FT |
1369 | |
1370 | status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL); | |
1371 | if (status) | |
e7694cb6 | 1372 | goto midi_free; |
e1e3d7ec | 1373 | |
9acdf4df FT |
1374 | spin_lock_init(&midi->transmit_lock); |
1375 | ||
6f1de344 AP |
1376 | ++opts->refcnt; |
1377 | mutex_unlock(&opts->lock); | |
b85e9de9 AP |
1378 | |
1379 | midi->func.name = "gmidi function"; | |
b85e9de9 AP |
1380 | midi->func.bind = f_midi_bind; |
1381 | midi->func.unbind = f_midi_unbind; | |
1382 | midi->func.set_alt = f_midi_set_alt; | |
1383 | midi->func.disable = f_midi_disable; | |
1384 | midi->func.free_func = f_midi_free; | |
1385 | ||
1386 | return &midi->func; | |
1387 | ||
e7694cb6 ZQ |
1388 | midi_free: |
1389 | if (midi) | |
1390 | kfree(midi->id); | |
1391 | kfree(midi); | |
b85e9de9 | 1392 | setup_fail: |
413489c8 | 1393 | mutex_unlock(&opts->lock); |
e7694cb6 | 1394 | |
b85e9de9 AP |
1395 | return ERR_PTR(status); |
1396 | } | |
1397 | ||
1398 | DECLARE_USB_FUNCTION_INIT(midi, f_midi_alloc_inst, f_midi_alloc); |