aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2011-09-28 10:41:34 -0400
committerFelipe Balbi <balbi@ti.com>2011-10-13 13:39:52 -0400
commitc8933c3f79568263c90a46f06cf80419e6c63c97 (patch)
treef2e47dc624e9f5aa5e8e6a5b9907dc157dd0e7bb
parent2672eea5a38b35e6d28f851e990e110e217271eb (diff)
USB: gadget: f_midi: allow a dynamic number of input and output ports
The code in the MIDI gadget was already sort of prepared for multi-port configuration, so the streaming logic itself didn't need much tweaking. However, the descriptors change when the number of ports do, and so some rework of the the preparation algorithms were necessary. Successfully tested on Linux and Max OS X hosts for both input and output streams. Signed-off-by: Daniel Mack <zonque@gmail.com> Cc: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/gadget/f_midi.c287
-rw-r--r--drivers/usb/gadget/gmidi.c12
2 files changed, 191 insertions, 108 deletions
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 84cbf85d23f8..44858dc074d3 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -40,6 +40,13 @@ static const char f_midi_shortname[] = "f_midi";
40static const char f_midi_longname[] = "MIDI Gadget"; 40static const char f_midi_longname[] = "MIDI Gadget";
41 41
42/* 42/*
43 * We can only handle 16 cables on one single endpoint, as cable numbers are
44 * stored in 4-bit fields. And as the interface currently only holds one
45 * single endpoint, this is the maximum number of ports we can allow.
46 */
47#define MAX_PORTS 16
48
49/*
43 * This is a gadget, and the IN/OUT naming is from the host's perspective. 50 * This is a gadget, and the IN/OUT naming is from the host's perspective.
44 * USB -> OUT endpoint -> rawmidi 51 * USB -> OUT endpoint -> rawmidi
45 * USB <- IN endpoint <- rawmidi 52 * USB <- IN endpoint <- rawmidi
@@ -47,7 +54,7 @@ static const char f_midi_longname[] = "MIDI Gadget";
47struct gmidi_in_port { 54struct gmidi_in_port {
48 struct f_midi *midi; 55 struct f_midi *midi;
49 int active; 56 int active;
50 uint8_t cable; /* cable number << 4 */ 57 uint8_t cable;
51 uint8_t state; 58 uint8_t state;
52#define STATE_UNKNOWN 0 59#define STATE_UNKNOWN 0
53#define STATE_1PARAM 1 60#define STATE_1PARAM 1
@@ -65,15 +72,15 @@ struct f_midi {
65 struct usb_ep *in_ep, *out_ep; 72 struct usb_ep *in_ep, *out_ep;
66 struct snd_card *card; 73 struct snd_card *card;
67 struct snd_rawmidi *rmidi; 74 struct snd_rawmidi *rmidi;
68 struct snd_rawmidi_substream *in_substream;
69 struct snd_rawmidi_substream *out_substream;
70 75
71 /* For the moment we only support one port in 76 struct snd_rawmidi_substream *in_substream[MAX_PORTS];
72 each direction, but in_port is kept as a 77 struct snd_rawmidi_substream *out_substream[MAX_PORTS];
73 separate struct so we can have more later. */ 78 struct gmidi_in_port *in_port[MAX_PORTS];
74 struct gmidi_in_port in_port; 79
75 unsigned long out_triggered; 80 unsigned long out_triggered;
76 struct tasklet_struct tasklet; 81 struct tasklet_struct tasklet;
82 unsigned int in_ports;
83 unsigned int out_ports;
77 int index; 84 int index;
78 char *id; 85 char *id;
79 unsigned int buflen, qlen; 86 unsigned int buflen, qlen;
@@ -88,7 +95,8 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req);
88 95
89DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); 96DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
90DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); 97DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
91DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); 98DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16);
99DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
92 100
93/* B.3.1 Standard AC Interface Descriptor */ 101/* B.3.1 Standard AC Interface Descriptor */
94static struct usb_interface_descriptor ac_interface_desc __initdata = { 102static struct usb_interface_descriptor ac_interface_desc __initdata = {
@@ -129,62 +137,27 @@ static struct usb_ms_header_descriptor ms_header_desc __initdata = {
129 .bDescriptorType = USB_DT_CS_INTERFACE, 137 .bDescriptorType = USB_DT_CS_INTERFACE,
130 .bDescriptorSubtype = USB_MS_HEADER, 138 .bDescriptorSubtype = USB_MS_HEADER,
131 .bcdMSC = cpu_to_le16(0x0100), 139 .bcdMSC = cpu_to_le16(0x0100),
132 .wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE 140 /* .wTotalLength = DYNAMIC */
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}; 141};
150 142
151static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = { 143/* B.4.3 Embedded MIDI IN Jack Descriptor */
152 .bLength = USB_DT_MIDI_IN_SIZE, 144static struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
153 .bDescriptorType = USB_DT_CS_INTERFACE, 145 .bLength = USB_DT_MIDI_IN_SIZE,
154 .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, 146 .bDescriptorType = USB_DT_CS_INTERFACE,
155 .bJackType = USB_MS_EXTERNAL, 147 .bDescriptorSubtype = USB_MS_MIDI_IN_JACK,
156 .bJackID = JACK_IN_EXT, 148 .bJackType = USB_MS_EMBEDDED,
149 /* .bJackID = DYNAMIC */
157}; 150};
158 151
159/* B.4.4 MIDI OUT Jack Descriptors */ 152/* B.4.4 Embedded MIDI OUT Jack Descriptor */
160static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = { 153static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = {
161 .bLength = USB_DT_MIDI_OUT_SIZE(1), 154 /* .bLength = DYNAMIC */
162 .bDescriptorType = USB_DT_CS_INTERFACE, 155 .bDescriptorType = USB_DT_CS_INTERFACE,
163 .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, 156 .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK,
164 .bJackType = USB_MS_EMBEDDED, 157 .bJackType = USB_MS_EMBEDDED,
165 .bJackID = JACK_OUT_EMB, 158 /* .bJackID = DYNAMIC */
166 .bNrInputPins = 1, 159 /* .bNrInputPins = DYNAMIC */
167 .pins = { 160 /* .pins = DYNAMIC */
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}; 161};
189 162
190/* B.5.1 Standard Bulk OUT Endpoint Descriptor */ 163/* B.5.1 Standard Bulk OUT Endpoint Descriptor */
@@ -196,14 +169,12 @@ static struct usb_endpoint_descriptor bulk_out_desc = {
196}; 169};
197 170
198/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */ 171/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */
199static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = { 172static struct usb_ms_endpoint_descriptor_16 ms_out_desc = {
200 .bLength = USB_DT_MS_ENDPOINT_SIZE(1), 173 /* .bLength = DYNAMIC */
201 .bDescriptorType = USB_DT_CS_ENDPOINT, 174 .bDescriptorType = USB_DT_CS_ENDPOINT,
202 .bDescriptorSubtype = USB_MS_GENERAL, 175 .bDescriptorSubtype = USB_MS_GENERAL,
203 .bNumEmbMIDIJack = 1, 176 /* .bNumEmbMIDIJack = DYNAMIC */
204 .baAssocJackID = { 177 /* .baAssocJackID = DYNAMIC */
205 [0] = JACK_IN_EMB,
206 }
207}; 178};
208 179
209/* B.6.1 Standard Bulk IN Endpoint Descriptor */ 180/* B.6.1 Standard Bulk IN Endpoint Descriptor */
@@ -215,33 +186,12 @@ static struct usb_endpoint_descriptor bulk_in_desc = {
215}; 186};
216 187
217/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */ 188/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
218static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = { 189static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
219 .bLength = USB_DT_MS_ENDPOINT_SIZE(1), 190 /* .bLength = DYNAMIC */
220 .bDescriptorType = USB_DT_CS_ENDPOINT, 191 .bDescriptorType = USB_DT_CS_ENDPOINT,
221 .bDescriptorSubtype = USB_MS_GENERAL, 192 .bDescriptorSubtype = USB_MS_GENERAL,
222 .bNumEmbMIDIJack = 1, 193 /* .bNumEmbMIDIJack = DYNAMIC */
223 .baAssocJackID = { 194 /* .baAssocJackID = DYNAMIC */
224 [0] = JACK_OUT_EMB,
225 }
226};
227
228static struct usb_descriptor_header *midi_function[] __initdata = {
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}; 195};
246 196
247/* string IDs are assigned dynamically */ 197/* string IDs are assigned dynamically */
@@ -296,16 +246,16 @@ static void f_midi_read_data(struct usb_ep *ep, int cable,
296 uint8_t *data, int length) 246 uint8_t *data, int length)
297{ 247{
298 struct f_midi *midi = ep->driver_data; 248 struct f_midi *midi = ep->driver_data;
299 /* cable is ignored, because for now we only have one. */ 249 struct snd_rawmidi_substream *substream = midi->out_substream[cable];
300 250
301 if (!midi->out_substream) 251 if (!substream)
302 /* Nobody is listening - throw it on the floor. */ 252 /* Nobody is listening - throw it on the floor. */
303 return; 253 return;
304 254
305 if (!test_bit(midi->out_substream->number, &midi->out_triggered)) 255 if (!test_bit(cable, &midi->out_triggered))
306 return; 256 return;
307 257
308 snd_rawmidi_receive(midi->out_substream, data, length); 258 snd_rawmidi_receive(substream, data, length);
309} 259}
310 260
311static void f_midi_handle_out_data(struct usb_ep *ep, struct usb_request *req) 261static void f_midi_handle_out_data(struct usb_ep *ep, struct usb_request *req)
@@ -514,7 +464,7 @@ static void f_midi_transmit_packet(struct usb_request *req, uint8_t p0,
514static void f_midi_transmit_byte(struct usb_request *req, 464static void f_midi_transmit_byte(struct usb_request *req,
515 struct gmidi_in_port *port, uint8_t b) 465 struct gmidi_in_port *port, uint8_t b)
516{ 466{
517 uint8_t p0 = port->cable; 467 uint8_t p0 = port->cable << 4;
518 468
519 if (b >= 0xf8) { 469 if (b >= 0xf8) {
520 f_midi_transmit_packet(req, p0 | 0x0f, b, 0, 0); 470 f_midi_transmit_packet(req, p0 | 0x0f, b, 0, 0);
@@ -612,7 +562,7 @@ static void f_midi_transmit_byte(struct usb_request *req,
612static void f_midi_transmit(struct f_midi *midi, struct usb_request *req) 562static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
613{ 563{
614 struct usb_ep *ep = midi->in_ep; 564 struct usb_ep *ep = midi->in_ep;
615 struct gmidi_in_port *port = &midi->in_port; 565 int i;
616 566
617 if (!ep) 567 if (!ep)
618 return; 568 return;
@@ -627,10 +577,16 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
627 req->length = 0; 577 req->length = 0;
628 req->complete = f_midi_complete; 578 req->complete = f_midi_complete;
629 579
630 if (port->active) { 580 for (i = 0; i < MAX_PORTS; i++) {
581 struct gmidi_in_port *port = midi->in_port[i];
582 struct snd_rawmidi_substream *substream = midi->in_substream[i];
583
584 if (!port || !port->active || !substream)
585 continue;
586
631 while (req->length + 3 < midi->buflen) { 587 while (req->length + 3 < midi->buflen) {
632 uint8_t b; 588 uint8_t b;
633 if (snd_rawmidi_transmit(midi->in_substream, &b, 1) != 1) { 589 if (snd_rawmidi_transmit(substream, &b, 1) != 1) {
634 port->active = 0; 590 port->active = 0;
635 break; 591 break;
636 } 592 }
@@ -654,9 +610,12 @@ static int f_midi_in_open(struct snd_rawmidi_substream *substream)
654{ 610{
655 struct f_midi *midi = substream->rmidi->private_data; 611 struct f_midi *midi = substream->rmidi->private_data;
656 612
613 if (!midi->in_port[substream->number])
614 return -EINVAL;
615
657 VDBG(midi, "%s()\n", __func__); 616 VDBG(midi, "%s()\n", __func__);
658 midi->in_substream = substream; 617 midi->in_substream[substream->number] = substream;
659 midi->in_port.state = STATE_UNKNOWN; 618 midi->in_port[substream->number]->state = STATE_UNKNOWN;
660 return 0; 619 return 0;
661} 620}
662 621
@@ -672,8 +631,11 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up)
672{ 631{
673 struct f_midi *midi = substream->rmidi->private_data; 632 struct f_midi *midi = substream->rmidi->private_data;
674 633
634 if (!midi->in_port[substream->number])
635 return;
636
675 VDBG(midi, "%s() %d\n", __func__, up); 637 VDBG(midi, "%s() %d\n", __func__, up);
676 midi->in_port.active = up; 638 midi->in_port[substream->number]->active = up;
677 if (up) 639 if (up)
678 tasklet_hi_schedule(&midi->tasklet); 640 tasklet_hi_schedule(&midi->tasklet);
679} 641}
@@ -682,8 +644,11 @@ static int f_midi_out_open(struct snd_rawmidi_substream *substream)
682{ 644{
683 struct f_midi *midi = substream->rmidi->private_data; 645 struct f_midi *midi = substream->rmidi->private_data;
684 646
647 if (!substream->number >= MAX_PORTS)
648 return -EINVAL;
649
685 VDBG(midi, "%s()\n", __func__); 650 VDBG(midi, "%s()\n", __func__);
686 midi->out_substream = substream; 651 midi->out_substream[substream->number] = substream;
687 return 0; 652 return 0;
688} 653}
689 654
@@ -725,8 +690,6 @@ static int f_midi_register_card(struct f_midi *midi)
725 struct snd_card *card; 690 struct snd_card *card;
726 struct snd_rawmidi *rmidi; 691 struct snd_rawmidi *rmidi;
727 int err; 692 int err;
728 int out_ports = 1;
729 int in_ports = 1;
730 static struct snd_device_ops ops = { 693 static struct snd_device_ops ops = {
731 .dev_free = f_midi_snd_free, 694 .dev_free = f_midi_snd_free,
732 }; 695 };
@@ -749,11 +712,9 @@ static int f_midi_register_card(struct f_midi *midi)
749 strcpy(card->shortname, f_midi_shortname); 712 strcpy(card->shortname, f_midi_shortname);
750 713
751 /* Set up rawmidi */ 714 /* Set up rawmidi */
752 midi->in_port.midi = midi;
753 midi->in_port.active = 0;
754 snd_component_add(card, "MIDI"); 715 snd_component_add(card, "MIDI");
755 err = snd_rawmidi_new(card, card->longname, 0, 716 err = snd_rawmidi_new(card, card->longname, 0,
756 out_ports, in_ports, &rmidi); 717 midi->out_ports, midi->in_ports, &rmidi);
757 if (err < 0) { 718 if (err < 0) {
758 ERROR(midi, "snd_rawmidi_new() failed: error %d\n", err); 719 ERROR(midi, "snd_rawmidi_new() failed: error %d\n", err);
759 goto fail; 720 goto fail;
@@ -797,9 +758,12 @@ fail:
797static int __init 758static int __init
798f_midi_bind(struct usb_configuration *c, struct usb_function *f) 759f_midi_bind(struct usb_configuration *c, struct usb_function *f)
799{ 760{
761 struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12];
762 struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
763 struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS];
800 struct usb_composite_dev *cdev = c->cdev; 764 struct usb_composite_dev *cdev = c->cdev;
801 struct f_midi *midi = func_to_midi(f); 765 struct f_midi *midi = func_to_midi(f);
802 int status; 766 int status, n, jack = 1, i = 0;
803 767
804 /* maybe allocate device-global string ID */ 768 /* maybe allocate device-global string ID */
805 if (midi_string_defs[0].id == 0) { 769 if (midi_string_defs[0].id == 0) {
@@ -835,6 +799,94 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
835 midi->out_ep->driver_data = cdev; /* claim */ 799 midi->out_ep->driver_data = cdev; /* claim */
836 800
837 /* 801 /*
802 * construct the function's descriptor set. As the number of
803 * input and output MIDI ports is configurable, we have to do
804 * it that way.
805 */
806
807 /* add the headers - these are always the same */
808 midi_function[i++] = (struct usb_descriptor_header *) &ac_interface_desc;
809 midi_function[i++] = (struct usb_descriptor_header *) &ac_header_desc;
810 midi_function[i++] = (struct usb_descriptor_header *) &ms_interface_desc;
811
812 /* calculate the header's wTotalLength */
813 n = USB_DT_MS_HEADER_SIZE
814 + (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE
815 + (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1);
816 ms_header_desc.wTotalLength = cpu_to_le16(n);
817
818 midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
819
820 /* we have one embedded IN jack */
821 jack_in_emb_desc.bJackID = jack++;
822 midi_function[i++] = (struct usb_descriptor_header *) &jack_in_emb_desc;
823
824 /* and a dynamic amount of external IN jacks */
825 for (n = 0; n < midi->in_ports; n++) {
826 struct usb_midi_in_jack_descriptor *ext = &jack_in_ext_desc[n];
827
828 ext->bLength = USB_DT_MIDI_IN_SIZE;
829 ext->bDescriptorType = USB_DT_CS_INTERFACE;
830 ext->bDescriptorSubtype = USB_MS_MIDI_IN_JACK;
831 ext->bJackType = USB_MS_EXTERNAL;
832 ext->bJackID = jack++;
833 ext->iJack = 0;
834
835 midi_function[i++] = (struct usb_descriptor_header *) ext;
836 }
837
838 /* one embedded OUT jack ... */
839 jack_out_emb_desc.bLength = USB_DT_MIDI_OUT_SIZE(midi->in_ports);
840 jack_out_emb_desc.bJackID = jack++;
841 jack_out_emb_desc.bNrInputPins = midi->in_ports;
842 /* ... which referencess all external IN jacks */
843 for (n = 0; n < midi->in_ports; n++) {
844 jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID;
845 jack_out_emb_desc.pins[n].baSourcePin = 1;
846 }
847
848 midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc;
849
850 /* and multiple external OUT jacks ... */
851 for (n = 0; n < midi->out_ports; n++) {
852 struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n];
853 int m;
854
855 ext->bLength = USB_DT_MIDI_OUT_SIZE(1);
856 ext->bDescriptorType = USB_DT_CS_INTERFACE;
857 ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK;
858 ext->bJackType = USB_MS_EXTERNAL;
859 ext->bJackID = jack++;
860 ext->bNrInputPins = 1;
861 ext->iJack = 0;
862 /* ... which all reference the same embedded IN jack */
863 for (m = 0; m < midi->out_ports; m++) {
864 ext->pins[m].baSourceID = jack_in_emb_desc.bJackID;
865 ext->pins[m].baSourcePin = 1;
866 }
867
868 midi_function[i++] = (struct usb_descriptor_header *) ext;
869 }
870
871 /* configure the endpoint descriptors ... */
872 ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
873 ms_out_desc.bNumEmbMIDIJack = midi->in_ports;
874 for (n = 0; n < midi->in_ports; n++)
875 ms_out_desc.baAssocJackID[n] = jack_in_emb_desc.bJackID;
876
877 ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
878 ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
879 for (n = 0; n < midi->out_ports; n++)
880 ms_in_desc.baAssocJackID[n] = jack_out_emb_desc.bJackID;
881
882 /* ... and add them to the list */
883 midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
884 midi_function[i++] = (struct usb_descriptor_header *) &ms_out_desc;
885 midi_function[i++] = (struct usb_descriptor_header *) &bulk_in_desc;
886 midi_function[i++] = (struct usb_descriptor_header *) &ms_in_desc;
887 midi_function[i++] = NULL;
888
889 /*
838 * support all relevant hardware speeds... we expect that when 890 * support all relevant hardware speeds... we expect that when
839 * hardware is dual speed, all bulk-capable endpoints work at 891 * hardware is dual speed, all bulk-capable endpoints work at
840 * both speeds 892 * both speeds
@@ -876,11 +928,17 @@ fail:
876 */ 928 */
877int __init f_midi_bind_config(struct usb_configuration *c, 929int __init f_midi_bind_config(struct usb_configuration *c,
878 int index, char *id, 930 int index, char *id,
931 unsigned int in_ports,
932 unsigned int out_ports,
879 unsigned int buflen, 933 unsigned int buflen,
880 unsigned int qlen) 934 unsigned int qlen)
881{ 935{
882 struct f_midi *midi; 936 struct f_midi *midi;
883 int status; 937 int status, i;
938
939 /* sanity check */
940 if (in_ports > MAX_PORTS || out_ports > MAX_PORTS)
941 return -EINVAL;
884 942
885 /* allocate and initialize one new instance */ 943 /* allocate and initialize one new instance */
886 midi = kzalloc(sizeof *midi, GFP_KERNEL); 944 midi = kzalloc(sizeof *midi, GFP_KERNEL);
@@ -889,10 +947,25 @@ int __init f_midi_bind_config(struct usb_configuration *c,
889 goto fail; 947 goto fail;
890 } 948 }
891 949
950 for (i = 0; i < in_ports; i++) {
951 struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL);
952 if (!port) {
953 status = -ENOMEM;
954 goto fail;
955 }
956
957 port->midi = midi;
958 port->active = 0;
959 port->cable = i;
960 midi->in_port[i] = port;
961 }
962
892 midi->gadget = c->cdev->gadget; 963 midi->gadget = c->cdev->gadget;
893 tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); 964 tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
894 965
895 /* set up ALSA midi devices */ 966 /* set up ALSA midi devices */
967 midi->in_ports = in_ports;
968 midi->out_ports = out_ports;
896 status = f_midi_register_card(midi); 969 status = f_midi_register_card(midi);
897 if (status < 0) 970 if (status < 0)
898 goto setup_fail; 971 goto setup_fail;
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index e7c8c3907133..8fcde37aa6d4 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -66,6 +66,14 @@ static unsigned int qlen = 32;
66module_param(qlen, uint, S_IRUGO); 66module_param(qlen, uint, S_IRUGO);
67MODULE_PARM_DESC(qlen, "USB read request queue length"); 67MODULE_PARM_DESC(qlen, "USB read request queue length");
68 68
69static unsigned int in_ports = 1;
70module_param(in_ports, uint, S_IRUGO);
71MODULE_PARM_DESC(in_ports, "Number of MIDI input ports");
72
73static unsigned int out_ports = 1;
74module_param(out_ports, uint, S_IRUGO);
75MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
76
69/* Thanks to Grey Innovation for donating this product ID. 77/* Thanks to Grey Innovation for donating this product ID.
70 * 78 *
71 * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! 79 * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
@@ -124,7 +132,9 @@ static struct usb_configuration midi_config = {
124 132
125static int __init midi_bind_config(struct usb_configuration *c) 133static int __init midi_bind_config(struct usb_configuration *c)
126{ 134{
127 return f_midi_bind_config(c, index, id, buflen, qlen); 135 return f_midi_bind_config(c, index, id,
136 in_ports, out_ports,
137 buflen, qlen);
128} 138}
129 139
130static int __init midi_bind(struct usb_composite_dev *cdev) 140static int __init midi_bind(struct usb_composite_dev *cdev)