aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_midi.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2011-10-15 07:45:05 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-14 14:51:25 -0500
commit74203de067ae5c71526168b597088022836e31d3 (patch)
treedd60379860dee7513136ce018e4d04270190331c /drivers/usb/gadget/f_midi.c
parentce7b6121851c72d661134d113a78161095e0ae73 (diff)
usb: gadget: fix MIDI gadget jack allocation
The dynamic jack allocation of the MIDI gadget currently links all external jacks to one single instance of an embedded jack. According to the spec, this is only valid if these streams always carry the same data stream, as described in the USB MIDI 1.0 spec, chapter 3.3.1. Also, genius Windows 7(tm) terminates it's life cycle instantly with a blue screen of death once a device with more than one input and output port with the current implementation is connected. While at it, and because it grew again by this change, allocate the temporary function pointer list on the heap, not on the stack. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/f_midi.c')
-rw-r--r--drivers/usb/gadget/f_midi.c138
1 files changed, 65 insertions, 73 deletions
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 67b222908cf9..3797b3d6c622 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -95,7 +95,6 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req);
95 95
96DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); 96DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
97DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); 97DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
98DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16);
99DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); 98DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
100 99
101/* B.3.1 Standard AC Interface Descriptor */ 100/* B.3.1 Standard AC Interface Descriptor */
@@ -140,26 +139,6 @@ static struct usb_ms_header_descriptor ms_header_desc __initdata = {
140 /* .wTotalLength = DYNAMIC */ 139 /* .wTotalLength = DYNAMIC */
141}; 140};
142 141
143/* B.4.3 Embedded MIDI IN Jack Descriptor */
144static struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
145 .bLength = USB_DT_MIDI_IN_SIZE,
146 .bDescriptorType = USB_DT_CS_INTERFACE,
147 .bDescriptorSubtype = USB_MS_MIDI_IN_JACK,
148 .bJackType = USB_MS_EMBEDDED,
149 /* .bJackID = DYNAMIC */
150};
151
152/* B.4.4 Embedded MIDI OUT Jack Descriptor */
153static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = {
154 /* .bLength = DYNAMIC */
155 .bDescriptorType = USB_DT_CS_INTERFACE,
156 .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK,
157 .bJackType = USB_MS_EMBEDDED,
158 /* .bJackID = DYNAMIC */
159 /* .bNrInputPins = DYNAMIC */
160 /* .pins = DYNAMIC */
161};
162
163/* B.5.1 Standard Bulk OUT Endpoint Descriptor */ 142/* B.5.1 Standard Bulk OUT Endpoint Descriptor */
164static struct usb_endpoint_descriptor bulk_out_desc = { 143static struct usb_endpoint_descriptor bulk_out_desc = {
165 .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, 144 .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
@@ -758,9 +737,11 @@ fail:
758static int __init 737static int __init
759f_midi_bind(struct usb_configuration *c, struct usb_function *f) 738f_midi_bind(struct usb_configuration *c, struct usb_function *f)
760{ 739{
761 struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12]; 740 struct usb_descriptor_header **midi_function;
762 struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; 741 struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
742 struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS];
763 struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS]; 743 struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS];
744 struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS];
764 struct usb_composite_dev *cdev = c->cdev; 745 struct usb_composite_dev *cdev = c->cdev;
765 struct f_midi *midi = func_to_midi(f); 746 struct f_midi *midi = func_to_midi(f);
766 int status, n, jack = 1, i = 0; 747 int status, n, jack = 1, i = 0;
@@ -798,6 +779,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
798 goto fail; 779 goto fail;
799 midi->out_ep->driver_data = cdev; /* claim */ 780 midi->out_ep->driver_data = cdev; /* claim */
800 781
782 /* allocate temporary function list */
783 midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(midi_function),
784 GFP_KERNEL);
785 if (!midi_function) {
786 status = -ENOMEM;
787 goto fail;
788 }
789
801 /* 790 /*
802 * construct the function's descriptor set. As the number of 791 * construct the function's descriptor set. As the number of
803 * input and output MIDI ports is configurable, we have to do 792 * input and output MIDI ports is configurable, we have to do
@@ -811,73 +800,74 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
811 800
812 /* calculate the header's wTotalLength */ 801 /* calculate the header's wTotalLength */
813 n = USB_DT_MS_HEADER_SIZE 802 n = USB_DT_MS_HEADER_SIZE
814 + (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE 803 + (midi->in_ports + midi->out_ports) *
815 + (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1); 804 (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
816 ms_header_desc.wTotalLength = cpu_to_le16(n); 805 ms_header_desc.wTotalLength = cpu_to_le16(n);
817 806
818 midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc; 807 midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
819 808
820 /* we have one embedded IN jack */ 809 /* configure the external IN jacks, each linked to an embedded OUT 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++) { 810 for (n = 0; n < midi->in_ports; n++) {
844 jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID; 811 struct usb_midi_in_jack_descriptor *in_ext = &jack_in_ext_desc[n];
845 jack_out_emb_desc.pins[n].baSourcePin = 1; 812 struct usb_midi_out_jack_descriptor_1 *out_emb = &jack_out_emb_desc[n];
813
814 in_ext->bLength = USB_DT_MIDI_IN_SIZE;
815 in_ext->bDescriptorType = USB_DT_CS_INTERFACE;
816 in_ext->bDescriptorSubtype = USB_MS_MIDI_IN_JACK;
817 in_ext->bJackType = USB_MS_EXTERNAL;
818 in_ext->bJackID = jack++;
819 in_ext->iJack = 0;
820 midi_function[i++] = (struct usb_descriptor_header *) in_ext;
821
822 out_emb->bLength = USB_DT_MIDI_OUT_SIZE(1);
823 out_emb->bDescriptorType = USB_DT_CS_INTERFACE;
824 out_emb->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK;
825 out_emb->bJackType = USB_MS_EMBEDDED;
826 out_emb->bJackID = jack++;
827 out_emb->bNrInputPins = 1;
828 out_emb->pins[0].baSourcePin = 1;
829 out_emb->pins[0].baSourceID = in_ext->bJackID;
830 out_emb->iJack = 0;
831 midi_function[i++] = (struct usb_descriptor_header *) out_emb;
832
833 /* link it to the endpoint */
834 ms_in_desc.baAssocJackID[n] = out_emb->bJackID;
846 } 835 }
847 836
848 midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc; 837 /* configure the external OUT jacks, each linked to an embedded IN jack */
849
850 /* and multiple external OUT jacks ... */
851 for (n = 0; n < midi->out_ports; n++) { 838 for (n = 0; n < midi->out_ports; n++) {
852 struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n]; 839 struct usb_midi_in_jack_descriptor *in_emb = &jack_in_emb_desc[n];
853 int m; 840 struct usb_midi_out_jack_descriptor_1 *out_ext = &jack_out_ext_desc[n];
854 841
855 ext->bLength = USB_DT_MIDI_OUT_SIZE(1); 842 in_emb->bLength = USB_DT_MIDI_IN_SIZE;
856 ext->bDescriptorType = USB_DT_CS_INTERFACE; 843 in_emb->bDescriptorType = USB_DT_CS_INTERFACE;
857 ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; 844 in_emb->bDescriptorSubtype = USB_MS_MIDI_IN_JACK;
858 ext->bJackType = USB_MS_EXTERNAL; 845 in_emb->bJackType = USB_MS_EMBEDDED;
859 ext->bJackID = jack++; 846 in_emb->bJackID = jack++;
860 ext->bNrInputPins = 1; 847 in_emb->iJack = 0;
861 ext->iJack = 0; 848 midi_function[i++] = (struct usb_descriptor_header *) in_emb;
862 /* ... which all reference the same embedded IN jack */ 849
863 for (m = 0; m < midi->out_ports; m++) { 850 out_ext->bLength = USB_DT_MIDI_OUT_SIZE(1);
864 ext->pins[m].baSourceID = jack_in_emb_desc.bJackID; 851 out_ext->bDescriptorType = USB_DT_CS_INTERFACE;
865 ext->pins[m].baSourcePin = 1; 852 out_ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK;
866 } 853 out_ext->bJackType = USB_MS_EXTERNAL;
867 854 out_ext->bJackID = jack++;
868 midi_function[i++] = (struct usb_descriptor_header *) ext; 855 out_ext->bNrInputPins = 1;
856 out_ext->iJack = 0;
857 out_ext->pins[0].baSourceID = in_emb->bJackID;
858 out_ext->pins[0].baSourcePin = 1;
859 midi_function[i++] = (struct usb_descriptor_header *) out_ext;
860
861 /* link it to the endpoint */
862 ms_out_desc.baAssocJackID[n] = in_emb->bJackID;
869 } 863 }
870 864
871 /* configure the endpoint descriptors ... */ 865 /* configure the endpoint descriptors ... */
872 ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); 866 ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
873 ms_out_desc.bNumEmbMIDIJack = midi->in_ports; 867 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 868
877 ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); 869 ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
878 ms_in_desc.bNumEmbMIDIJack = midi->out_ports; 870 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 871
882 /* ... and add them to the list */ 872 /* ... and add them to the list */
883 midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc; 873 midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
@@ -901,6 +891,8 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
901 f->descriptors = usb_copy_descriptors(midi_function); 891 f->descriptors = usb_copy_descriptors(midi_function);
902 } 892 }
903 893
894 kfree(midi_function);
895
904 return 0; 896 return 0;
905 897
906fail: 898fail: