aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2011-09-28 10:41:32 -0400
committerFelipe Balbi <balbi@ti.com>2011-10-13 13:39:49 -0400
commitd5daf49b58661ec4af7a55b277176efbf945ca05 (patch)
treede8eeeda54aa36144208d4add536b94f0d121607 /drivers/usb/gadget
parent56526c0b8d752bf243a21722455807518925685f (diff)
USB: gadget: midi: add midi function driver
This patch adds f_midi.c to implement a USB gadget function that works with the composite framework, so it can be combined with other USB functions. The code for the ALSA/MIDI logic was taken from the midi device gadget, other parts have been rewritten to benefit from the dynamic descriptor allocation features. This was successfully tested on an OMAP3 board. Signed-off-by: Daniel Mack <zonque@gmail.com> Cc: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/f_midi.c923
1 files changed, 923 insertions, 0 deletions
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
new file mode 100644
index 000000000000..5064ea4efbed
--- /dev/null
+++ b/drivers/usb/gadget/f_midi.c
@@ -0,0 +1,923 @@
1/*
2 * f_midi.c -- USB MIDI class function driver
3 *
4 * Copyright (C) 2006 Thumtronics Pty Ltd.
5 * Developed for Thumtronics by Grey Innovation
6 * Ben Williamson <ben.williamson@greyinnovation.com>
7 *
8 * Rewritten for the composite framework
9 * Copyright (C) 2011 Daniel Mack <zonque@gmail.com>
10 *
11 * Based on drivers/usb/gadget/f_audio.c,
12 * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
13 * Copyright (C) 2008 Analog Devices, Inc
14 *
15 * and drivers/usb/gadget/midi.c,
16 * Copyright (C) 2006 Thumtronics Pty Ltd.
17 * Ben Williamson <ben.williamson@greyinnovation.com>
18 *
19 * Licensed under the GPL-2 or later.
20 */
21
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/utsname.h>
25#include <linux/device.h>
26
27#include <sound/core.h>
28#include <sound/initval.h>
29#include <sound/rawmidi.h>
30
31#include <linux/usb/ch9.h>
32#include <linux/usb/gadget.h>
33#include <linux/usb/audio.h>
34#include <linux/usb/midi.h>
35
36MODULE_AUTHOR("Ben Williamson");
37MODULE_LICENSE("GPL v2");
38
39static const char f_midi_shortname[] = "f_midi";
40static const char f_midi_longname[] = "MIDI Gadget";
41
42/*
43 * This is a gadget, and the IN/OUT naming is from the host's perspective.
44 * USB -> OUT endpoint -> rawmidi
45 * USB <- IN endpoint <- rawmidi
46 */
47struct gmidi_in_port {
48 struct f_midi *midi;
49 int active;
50 uint8_t cable; /* cable number << 4 */
51 uint8_t state;
52#define STATE_UNKNOWN 0
53#define STATE_1PARAM 1
54#define STATE_2PARAM_1 2
55#define STATE_2PARAM_2 3
56#define STATE_SYSEX_0 4
57#define STATE_SYSEX_1 5
58#define STATE_SYSEX_2 6
59 uint8_t data[2];
60};
61
62struct f_midi {
63 struct usb_function func;
64 struct usb_gadget *gadget;
65 struct usb_ep *in_ep, *out_ep;
66 struct snd_card *card;
67 struct snd_rawmidi *rmidi;
68 struct snd_rawmidi_substream *in_substream;
69 struct snd_rawmidi_substream *out_substream;
70
71 /* For the moment we only support one port in
72 each direction, but in_port is kept as a
73 separate struct so we can have more later. */
74 struct gmidi_in_port in_port;
75 unsigned long out_triggered;
76 struct tasklet_struct tasklet;
77 int index;
78 char *id;
79 unsigned int buflen, qlen;
80};
81
82static inline struct f_midi *func_to_midi(struct usb_function *f)
83{
84 return container_of(f, struct f_midi, func);
85}
86
87static void f_midi_transmit(struct f_midi *midi, struct usb_request *req);
88
89DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
90DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
91DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
92
93/* B.3.1 Standard AC Interface Descriptor */
94static struct usb_interface_descriptor ac_interface_desc __initdata = {
95 .bLength = USB_DT_INTERFACE_SIZE,
96 .bDescriptorType = USB_DT_INTERFACE,
97 /* .bInterfaceNumber = DYNAMIC */
98 /* .bNumEndpoints = DYNAMIC */
99 .bInterfaceClass = USB_CLASS_AUDIO,
100 .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
101 /* .iInterface = DYNAMIC */
102};
103
104/* B.3.2 Class-Specific AC Interface Descriptor */
105static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = {
106 .bLength = UAC_DT_AC_HEADER_SIZE(1),
107 .bDescriptorType = USB_DT_CS_INTERFACE,
108 .bDescriptorSubtype = USB_MS_HEADER,
109 .bcdADC = cpu_to_le16(0x0100),
110 .wTotalLength = cpu_to_le16(UAC_DT_AC_HEADER_SIZE(1)),
111 .bInCollection = 1,
112 /* .baInterfaceNr = DYNAMIC */
113};
114
115/* B.4.1 Standard MS Interface Descriptor */
116static struct usb_interface_descriptor ms_interface_desc __initdata = {
117 .bLength = USB_DT_INTERFACE_SIZE,
118 .bDescriptorType = USB_DT_INTERFACE,
119 /* .bInterfaceNumber = DYNAMIC */
120 .bNumEndpoints = 2,
121 .bInterfaceClass = USB_CLASS_AUDIO,
122 .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING,
123 /* .iInterface = DYNAMIC */
124};
125
126/* B.4.2 Class-Specific MS Interface Descriptor */
127static struct usb_ms_header_descriptor ms_header_desc __initdata = {
128 .bLength = USB_DT_MS_HEADER_SIZE,
129 .bDescriptorType = USB_DT_CS_INTERFACE,
130 .bDescriptorSubtype = USB_MS_HEADER,
131 .bcdMSC = cpu_to_le16(0x0100),
132 .wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE
133 + 2*USB_DT_MIDI_IN_SIZE
134 + 2*USB_DT_MIDI_OUT_SIZE(1)),
135};
136
137#define JACK_IN_EMB 1
138#define JACK_IN_EXT 2
139#define JACK_OUT_EMB 3
140#define JACK_OUT_EXT 4
141
142/* B.4.3 MIDI IN Jack Descriptors */
143static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
144 .bLength = USB_DT_MIDI_IN_SIZE,
145 .bDescriptorType = USB_DT_CS_INTERFACE,
146 .bDescriptorSubtype = USB_MS_MIDI_IN_JACK,
147 .bJackType = USB_MS_EMBEDDED,
148 .bJackID = JACK_IN_EMB,
149};
150
151static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = {
152 .bLength = USB_DT_MIDI_IN_SIZE,
153 .bDescriptorType = USB_DT_CS_INTERFACE,
154 .bDescriptorSubtype = USB_MS_MIDI_IN_JACK,
155 .bJackType = USB_MS_EXTERNAL,
156 .bJackID = JACK_IN_EXT,
157};
158
159/* B.4.4 MIDI OUT Jack Descriptors */
160static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = {
161 .bLength = USB_DT_MIDI_OUT_SIZE(1),
162 .bDescriptorType = USB_DT_CS_INTERFACE,
163 .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK,
164 .bJackType = USB_MS_EMBEDDED,
165 .bJackID = JACK_OUT_EMB,
166 .bNrInputPins = 1,
167 .pins = {
168 [0] = {
169 .baSourceID = JACK_IN_EXT,
170 .baSourcePin = 1,
171 }
172 }
173};
174
175static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = {
176 .bLength = USB_DT_MIDI_OUT_SIZE(1),
177 .bDescriptorType = USB_DT_CS_INTERFACE,
178 .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK,
179 .bJackType = USB_MS_EXTERNAL,
180 .bJackID = JACK_OUT_EXT,
181 .bNrInputPins = 1,
182 .pins = {
183 [0] = {
184 .baSourceID = JACK_IN_EMB,
185 .baSourcePin = 1,
186 }
187 }
188};
189
190/* B.5.1 Standard Bulk OUT Endpoint Descriptor */
191static struct usb_endpoint_descriptor bulk_out_desc = {
192 .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
193 .bDescriptorType = USB_DT_ENDPOINT,
194 .bEndpointAddress = USB_DIR_OUT,
195 .bmAttributes = USB_ENDPOINT_XFER_BULK,
196};
197
198/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */
199static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = {
200 .bLength = USB_DT_MS_ENDPOINT_SIZE(1),
201 .bDescriptorType = USB_DT_CS_ENDPOINT,
202 .bDescriptorSubtype = USB_MS_GENERAL,
203 .bNumEmbMIDIJack = 1,
204 .baAssocJackID = {
205 [0] = JACK_IN_EMB,
206 }
207};
208
209/* B.6.1 Standard Bulk IN Endpoint Descriptor */
210static struct usb_endpoint_descriptor bulk_in_desc = {
211 .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
212 .bDescriptorType = USB_DT_ENDPOINT,
213 .bEndpointAddress = USB_DIR_IN,
214 .bmAttributes = USB_ENDPOINT_XFER_BULK,
215};
216
217/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
218static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = {
219 .bLength = USB_DT_MS_ENDPOINT_SIZE(1),
220 .bDescriptorType = USB_DT_CS_ENDPOINT,
221 .bDescriptorSubtype = USB_MS_GENERAL,
222 .bNumEmbMIDIJack = 1,
223 .baAssocJackID = {
224 [0] = JACK_OUT_EMB,
225 }
226};
227
228static struct usb_descriptor_header *midi_function[] = {
229 (struct usb_descriptor_header *)&ac_interface_desc,
230 (struct usb_descriptor_header *)&ac_header_desc,
231 (struct usb_descriptor_header *)&ms_interface_desc,
232
233 (struct usb_descriptor_header *)&ms_header_desc,
234 (struct usb_descriptor_header *)&jack_in_emb_desc,
235 (struct usb_descriptor_header *)&jack_in_ext_desc,
236 (struct usb_descriptor_header *)&jack_out_emb_desc,
237 (struct usb_descriptor_header *)&jack_out_ext_desc,
238 /* If you add more jacks, update ms_header_desc.wTotalLength */
239
240 (struct usb_descriptor_header *)&bulk_out_desc,
241 (struct usb_descriptor_header *)&ms_out_desc,
242 (struct usb_descriptor_header *)&bulk_in_desc,
243 (struct usb_descriptor_header *)&ms_in_desc,
244 NULL,
245};
246
247/* string IDs are assigned dynamically */
248
249#define STRING_FUNC_IDX 0
250
251static struct usb_string midi_string_defs[] = {
252 [STRING_FUNC_IDX].s = "MIDI function",
253 { } /* end of list */
254};
255
256static struct usb_gadget_strings midi_stringtab = {
257 .language = 0x0409, /* en-us */
258 .strings = midi_string_defs,
259};
260
261static struct usb_gadget_strings *midi_strings[] = {
262 &midi_stringtab,
263 NULL,
264};
265
266static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
267{
268 struct usb_request *req;
269
270 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
271 if (req) {
272 req->length = length;
273 req->buf = kmalloc(length, GFP_ATOMIC);
274 if (!req->buf) {
275 usb_ep_free_request(ep, req);
276 req = NULL;
277 }
278 }
279 return req;
280}
281
282static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
283{
284 kfree(req->buf);
285 usb_ep_free_request(ep, req);
286}
287
288static const uint8_t f_midi_cin_length[] = {
289 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
290};
291
292/*
293 * Receives a chunk of MIDI data.
294 */
295static void f_midi_read_data(struct usb_ep *ep, int cable,
296 uint8_t *data, int length)
297{
298 struct f_midi *midi = ep->driver_data;
299 /* cable is ignored, because for now we only have one. */
300
301 if (!midi->out_substream)
302 /* Nobody is listening - throw it on the floor. */
303 return;
304
305 if (!test_bit(midi->out_substream->number, &midi->out_triggered))
306 return;
307
308 snd_rawmidi_receive(midi->out_substream, data, length);
309}
310
311static void f_midi_handle_out_data(struct usb_ep *ep, struct usb_request *req)
312{
313 unsigned int i;
314 u8 *buf = req->buf;
315
316 for (i = 0; i + 3 < req->actual; i += 4)
317 if (buf[i] != 0) {
318 int cable = buf[i] >> 4;
319 int length = f_midi_cin_length[buf[i] & 0x0f];
320 f_midi_read_data(ep, cable, &buf[i + 1], length);
321 }
322}
323
324static void
325f_midi_complete(struct usb_ep *ep, struct usb_request *req)
326{
327 struct f_midi *midi = ep->driver_data;
328 struct usb_composite_dev *cdev = midi->func.config->cdev;
329 int status = req->status;
330
331 switch (status) {
332 case 0: /* normal completion */
333 if (ep == midi->out_ep) {
334 /* We received stuff. req is queued again, below */
335 f_midi_handle_out_data(ep, req);
336 } else if (ep == midi->in_ep) {
337 /* Our transmit completed. See if there's more to go.
338 * f_midi_transmit eats req, don't queue it again. */
339 f_midi_transmit(midi, req);
340 return;
341 }
342 break;
343
344 /* this endpoint is normally active while we're configured */
345 case -ECONNABORTED: /* hardware forced ep reset */
346 case -ECONNRESET: /* request dequeued */
347 case -ESHUTDOWN: /* disconnect from host */
348 VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status,
349 req->actual, req->length);
350 if (ep == midi->out_ep)
351 f_midi_handle_out_data(ep, req);
352
353 free_ep_req(ep, req);
354 return;
355
356 case -EOVERFLOW: /* buffer overrun on read means that
357 * we didn't provide a big enough buffer.
358 */
359 default:
360 DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
361 status, req->actual, req->length);
362 break;
363 case -EREMOTEIO: /* short read */
364 break;
365 }
366
367 status = usb_ep_queue(ep, req, GFP_ATOMIC);
368 if (status) {
369 ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n",
370 ep->name, req->length, status);
371 usb_ep_set_halt(ep);
372 /* FIXME recover later ... somehow */
373 }
374}
375
376static int f_midi_start_ep(struct f_midi *midi,
377 struct usb_function *f,
378 struct usb_ep *ep)
379{
380 int err;
381 struct usb_composite_dev *cdev = f->config->cdev;
382
383 if (ep->driver_data)
384 usb_ep_disable(ep);
385
386 err = config_ep_by_speed(midi->gadget, f, ep);
387 if (err) {
388 ERROR(cdev, "can't configure %s: %d\n", ep->name, err);
389 return err;
390 }
391
392 err = usb_ep_enable(ep);
393 if (err) {
394 ERROR(cdev, "can't start %s: %d\n", ep->name, err);
395 return err;
396 }
397
398 ep->driver_data = midi;
399
400 return 0;
401}
402
403static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
404{
405 struct f_midi *midi = func_to_midi(f);
406 struct usb_composite_dev *cdev = f->config->cdev;
407 unsigned i;
408 int err;
409
410 err = f_midi_start_ep(midi, f, midi->in_ep);
411 if (err)
412 return err;
413
414 err = f_midi_start_ep(midi, f, midi->out_ep);
415 if (err)
416 return err;
417
418 if (midi->out_ep->driver_data)
419 usb_ep_disable(midi->out_ep);
420
421 err = config_ep_by_speed(midi->gadget, f, midi->out_ep);
422 if (err) {
423 ERROR(cdev, "can't configure %s: %d\n",
424 midi->out_ep->name, err);
425 return err;
426 }
427
428 err = usb_ep_enable(midi->out_ep);
429 if (err) {
430 ERROR(cdev, "can't start %s: %d\n",
431 midi->out_ep->name, err);
432 return err;
433 }
434
435 midi->out_ep->driver_data = midi;
436
437 /* allocate a bunch of read buffers and queue them all at once. */
438 for (i = 0; i < midi->qlen && err == 0; i++) {
439 struct usb_request *req =
440 alloc_ep_req(midi->out_ep, midi->buflen);
441 if (req == NULL)
442 return -ENOMEM;
443
444 req->complete = f_midi_complete;
445 err = usb_ep_queue(midi->out_ep, req, GFP_ATOMIC);
446 if (err) {
447 ERROR(midi, "%s queue req: %d\n",
448 midi->out_ep->name, err);
449 }
450 }
451
452 return 0;
453}
454
455static void f_midi_disable(struct usb_function *f)
456{
457 struct f_midi *midi = func_to_midi(f);
458 struct usb_composite_dev *cdev = f->config->cdev;
459
460 DBG(cdev, "disable\n");
461
462 /*
463 * just disable endpoints, forcing completion of pending i/o.
464 * all our completion handlers free their requests in this case.
465 */
466 usb_ep_disable(midi->in_ep);
467 usb_ep_disable(midi->out_ep);
468}
469
470static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
471{
472 struct usb_composite_dev *cdev = f->config->cdev;
473 struct f_midi *midi = func_to_midi(f);
474 struct snd_card *card;
475
476 DBG(cdev, "unbind\n");
477
478 /* just to be sure */
479 f_midi_disable(f);
480
481 card = midi->card;
482 midi->card = NULL;
483 if (card)
484 snd_card_free(card);
485
486 kfree(midi->id);
487 midi->id = NULL;
488
489 usb_free_descriptors(f->descriptors);
490 kfree(midi);
491}
492
493static int f_midi_snd_free(struct snd_device *device)
494{
495 return 0;
496}
497
498static void f_midi_transmit_packet(struct usb_request *req, uint8_t p0,
499 uint8_t p1, uint8_t p2, uint8_t p3)
500{
501 unsigned length = req->length;
502 u8 *buf = (u8 *)req->buf + length;
503
504 buf[0] = p0;
505 buf[1] = p1;
506 buf[2] = p2;
507 buf[3] = p3;
508 req->length = length + 4;
509}
510
511/*
512 * Converts MIDI commands to USB MIDI packets.
513 */
514static void f_midi_transmit_byte(struct usb_request *req,
515 struct gmidi_in_port *port, uint8_t b)
516{
517 uint8_t p0 = port->cable;
518
519 if (b >= 0xf8) {
520 f_midi_transmit_packet(req, p0 | 0x0f, b, 0, 0);
521 } else if (b >= 0xf0) {
522 switch (b) {
523 case 0xf0:
524 port->data[0] = b;
525 port->state = STATE_SYSEX_1;
526 break;
527 case 0xf1:
528 case 0xf3:
529 port->data[0] = b;
530 port->state = STATE_1PARAM;
531 break;
532 case 0xf2:
533 port->data[0] = b;
534 port->state = STATE_2PARAM_1;
535 break;
536 case 0xf4:
537 case 0xf5:
538 port->state = STATE_UNKNOWN;
539 break;
540 case 0xf6:
541 f_midi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0);
542 port->state = STATE_UNKNOWN;
543 break;
544 case 0xf7:
545 switch (port->state) {
546 case STATE_SYSEX_0:
547 f_midi_transmit_packet(req,
548 p0 | 0x05, 0xf7, 0, 0);
549 break;
550 case STATE_SYSEX_1:
551 f_midi_transmit_packet(req,
552 p0 | 0x06, port->data[0], 0xf7, 0);
553 break;
554 case STATE_SYSEX_2:
555 f_midi_transmit_packet(req,
556 p0 | 0x07, port->data[0],
557 port->data[1], 0xf7);
558 break;
559 }
560 port->state = STATE_UNKNOWN;
561 break;
562 }
563 } else if (b >= 0x80) {
564 port->data[0] = b;
565 if (b >= 0xc0 && b <= 0xdf)
566 port->state = STATE_1PARAM;
567 else
568 port->state = STATE_2PARAM_1;
569 } else { /* b < 0x80 */
570 switch (port->state) {
571 case STATE_1PARAM:
572 if (port->data[0] < 0xf0) {
573 p0 |= port->data[0] >> 4;
574 } else {
575 p0 |= 0x02;
576 port->state = STATE_UNKNOWN;
577 }
578 f_midi_transmit_packet(req, p0, port->data[0], b, 0);
579 break;
580 case STATE_2PARAM_1:
581 port->data[1] = b;
582 port->state = STATE_2PARAM_2;
583 break;
584 case STATE_2PARAM_2:
585 if (port->data[0] < 0xf0) {
586 p0 |= port->data[0] >> 4;
587 port->state = STATE_2PARAM_1;
588 } else {
589 p0 |= 0x03;
590 port->state = STATE_UNKNOWN;
591 }
592 f_midi_transmit_packet(req,
593 p0, port->data[0], port->data[1], b);
594 break;
595 case STATE_SYSEX_0:
596 port->data[0] = b;
597 port->state = STATE_SYSEX_1;
598 break;
599 case STATE_SYSEX_1:
600 port->data[1] = b;
601 port->state = STATE_SYSEX_2;
602 break;
603 case STATE_SYSEX_2:
604 f_midi_transmit_packet(req,
605 p0 | 0x04, port->data[0], port->data[1], b);
606 port->state = STATE_SYSEX_0;
607 break;
608 }
609 }
610}
611
612static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
613{
614 struct usb_ep *ep = midi->in_ep;
615 struct gmidi_in_port *port = &midi->in_port;
616
617 if (!ep)
618 return;
619
620 if (!req)
621 req = alloc_ep_req(ep, midi->buflen);
622
623 if (!req) {
624 ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n");
625 return;
626 }
627 req->length = 0;
628 req->complete = f_midi_complete;
629
630 if (port->active) {
631 while (req->length + 3 < midi->buflen) {
632 uint8_t b;
633 if (snd_rawmidi_transmit(midi->in_substream, &b, 1) != 1) {
634 port->active = 0;
635 break;
636 }
637 f_midi_transmit_byte(req, port, b);
638 }
639 }
640
641 if (req->length > 0)
642 usb_ep_queue(ep, req, GFP_ATOMIC);
643 else
644 free_ep_req(ep, req);
645}
646
647static void f_midi_in_tasklet(unsigned long data)
648{
649 struct f_midi *midi = (struct f_midi *) data;
650 f_midi_transmit(midi, NULL);
651}
652
653static int f_midi_in_open(struct snd_rawmidi_substream *substream)
654{
655 struct f_midi *midi = substream->rmidi->private_data;
656
657 VDBG(midi, "%s()\n", __func__);
658 midi->in_substream = substream;
659 midi->in_port.state = STATE_UNKNOWN;
660 return 0;
661}
662
663static int f_midi_in_close(struct snd_rawmidi_substream *substream)
664{
665 struct f_midi *midi = substream->rmidi->private_data;
666
667 VDBG(midi, "%s()\n", __func__);
668 return 0;
669}
670
671static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up)
672{
673 struct f_midi *midi = substream->rmidi->private_data;
674
675 VDBG(midi, "%s() %d\n", __func__, up);
676 midi->in_port.active = up;
677 if (up)
678 tasklet_hi_schedule(&midi->tasklet);
679}
680
681static int f_midi_out_open(struct snd_rawmidi_substream *substream)
682{
683 struct f_midi *midi = substream->rmidi->private_data;
684
685 VDBG(midi, "%s()\n", __func__);
686 midi->out_substream = substream;
687 return 0;
688}
689
690static int f_midi_out_close(struct snd_rawmidi_substream *substream)
691{
692 struct f_midi *midi = substream->rmidi->private_data;
693
694 VDBG(midi, "%s()\n", __func__);
695 return 0;
696}
697
698static void f_midi_out_trigger(struct snd_rawmidi_substream *substream, int up)
699{
700 struct f_midi *midi = substream->rmidi->private_data;
701
702 VDBG(midi, "%s()\n", __func__);
703
704 if (up)
705 set_bit(substream->number, &midi->out_triggered);
706 else
707 clear_bit(substream->number, &midi->out_triggered);
708}
709
710static struct snd_rawmidi_ops gmidi_in_ops = {
711 .open = f_midi_in_open,
712 .close = f_midi_in_close,
713 .trigger = f_midi_in_trigger,
714};
715
716static struct snd_rawmidi_ops gmidi_out_ops = {
717 .open = f_midi_out_open,
718 .close = f_midi_out_close,
719 .trigger = f_midi_out_trigger
720};
721
722/* register as a sound "card" */
723static int f_midi_register_card(struct f_midi *midi)
724{
725 struct snd_card *card;
726 struct snd_rawmidi *rmidi;
727 int err;
728 int out_ports = 1;
729 int in_ports = 1;
730 static struct snd_device_ops ops = {
731 .dev_free = f_midi_snd_free,
732 };
733
734 err = snd_card_create(midi->index, midi->id, THIS_MODULE, 0, &card);
735 if (err < 0) {
736 ERROR(midi, "snd_card_create() failed\n");
737 goto fail;
738 }
739 midi->card = card;
740
741 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, midi, &ops);
742 if (err < 0) {
743 ERROR(midi, "snd_device_new() failed: error %d\n", err);
744 goto fail;
745 }
746
747 strcpy(card->driver, f_midi_longname);
748 strcpy(card->longname, f_midi_longname);
749 strcpy(card->shortname, f_midi_shortname);
750
751 /* Set up rawmidi */
752 midi->in_port.midi = midi;
753 midi->in_port.active = 0;
754 snd_component_add(card, "MIDI");
755 err = snd_rawmidi_new(card, card->longname, 0,
756 out_ports, in_ports, &rmidi);
757 if (err < 0) {
758 ERROR(midi, "snd_rawmidi_new() failed: error %d\n", err);
759 goto fail;
760 }
761 midi->rmidi = rmidi;
762 strcpy(rmidi->name, card->shortname);
763 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
764 SNDRV_RAWMIDI_INFO_INPUT |
765 SNDRV_RAWMIDI_INFO_DUPLEX;
766 rmidi->private_data = midi;
767
768 /*
769 * Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
770 * It's an upside-down world being a gadget.
771 */
772 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops);
773 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops);
774
775 snd_card_set_dev(card, &midi->gadget->dev);
776
777 /* register it - we're ready to go */
778 err = snd_card_register(card);
779 if (err < 0) {
780 ERROR(midi, "snd_card_register() failed\n");
781 goto fail;
782 }
783
784 VDBG(midi, "%s() finished ok\n", __func__);
785 return 0;
786
787fail:
788 if (midi->card) {
789 snd_card_free(midi->card);
790 midi->card = NULL;
791 }
792 return err;
793}
794
795/* MIDI function driver setup/binding */
796
797static int __init
798f_midi_bind(struct usb_configuration *c, struct usb_function *f)
799{
800 struct usb_composite_dev *cdev = c->cdev;
801 struct f_midi *midi = func_to_midi(f);
802 int status;
803
804 /* maybe allocate device-global string ID */
805 if (midi_string_defs[0].id == 0) {
806 status = usb_string_id(c->cdev);
807 if (status < 0)
808 goto fail;
809 midi_string_defs[0].id = status;
810 }
811
812 /* We have two interfaces, AudioControl and MIDIStreaming */
813 status = usb_interface_id(c, f);
814 if (status < 0)
815 goto fail;
816 ac_interface_desc.bInterfaceNumber = status;
817
818 status = usb_interface_id(c, f);
819 if (status < 0)
820 goto fail;
821 ms_interface_desc.bInterfaceNumber = status;
822 ac_header_desc.baInterfaceNr[0] = status;
823
824 status = -ENODEV;
825
826 /* allocate instance-specific endpoints */
827 midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc);
828 if (!midi->in_ep)
829 goto fail;
830 midi->in_ep->driver_data = cdev; /* claim */
831
832 midi->out_ep = usb_ep_autoconfig(cdev->gadget, &bulk_out_desc);
833 if (!midi->out_ep)
834 goto fail;
835 midi->out_ep->driver_data = cdev; /* claim */
836
837 /*
838 * support all relevant hardware speeds... we expect that when
839 * hardware is dual speed, all bulk-capable endpoints work at
840 * both speeds
841 */
842 /* copy descriptors, and track endpoint copies */
843 if (gadget_is_dualspeed(c->cdev->gadget)) {
844 c->highspeed = true;
845 bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);
846 bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);
847 f->hs_descriptors = usb_copy_descriptors(midi_function);
848 } else {
849 f->descriptors = usb_copy_descriptors(midi_function);
850 }
851
852 return 0;
853
854fail:
855 /* we might as well release our claims on endpoints */
856 if (midi->out_ep)
857 midi->out_ep->driver_data = NULL;
858 if (midi->in_ep)
859 midi->in_ep->driver_data = NULL;
860
861 ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
862
863 return status;
864}
865
866/**
867 * f_midi_bind_config - add USB MIDI function to a configuration
868 * @c: the configuration to supcard the USB audio function
869 * @index: the soundcard index to use for the ALSA device creation
870 * @id: the soundcard id to use for the ALSA device creation
871 * @buflen: the buffer length to use
872 * @qlen the number of read requests to pre-allocate
873 * Context: single threaded during gadget setup
874 *
875 * Returns zero on success, else negative errno.
876 */
877int __init f_midi_bind_config(struct usb_configuration *c,
878 int index, char *id,
879 unsigned int buflen,
880 unsigned int qlen)
881{
882 struct f_midi *midi;
883 int status;
884
885 /* allocate and initialize one new instance */
886 midi = kzalloc(sizeof *midi, GFP_KERNEL);
887 if (!midi) {
888 status = -ENOMEM;
889 goto fail;
890 }
891
892 midi->gadget = c->cdev->gadget;
893 tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
894
895 /* set up ALSA midi devices */
896 status = f_midi_register_card(midi);
897 if (status < 0)
898 goto setup_fail;
899
900 midi->func.name = "gmidi function";
901 midi->func.strings = midi_strings;
902 midi->func.bind = f_midi_bind;
903 midi->func.unbind = f_midi_unbind;
904 midi->func.set_alt = f_midi_set_alt;
905 midi->func.disable = f_midi_disable;
906
907 midi->id = kstrdup(id, GFP_KERNEL);
908 midi->index = index;
909 midi->buflen = buflen;
910 midi->qlen = qlen;
911
912 status = usb_add_function(c, &midi->func);
913 if (status)
914 goto setup_fail;
915
916 return 0;
917
918setup_fail:
919 kfree(midi);
920fail:
921 return status;
922}
923