Ping? On Fri, Nov 4, 2011 at 12:31 PM, Daniel Mack <zonque@xxxxxxxxx> wrote: > The dynamic jack allocation of the MIDI gadget currently links all > external jacks to one single instance of an embedded jack. According to > chapter 3.3.1 of the USB MIDI 1.0 spec, this is only valid if these > streams always carry the same data stream. > > Also, with the current implementation, Windows 7(tm) will blue-screen > instantly once a device featuring more than one input and output MIDI > port 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@xxxxxxxxx> > Cc: Greg Kroah-Hartman <gregkh@xxxxxxx> > Cc: Felipe Balbi <balbi@xxxxxx> > --- > drivers/usb/gadget/f_midi.c | 139 ++++++++++++++++++++---------------------- > 1 files changed, 66 insertions(+), 73 deletions(-) > > diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c > index 67b2229..b5ad4e1 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); > > DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); > DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); > -DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16); > DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); > > /* B.3.1 Standard AC Interface Descriptor */ > @@ -140,26 +139,6 @@ static struct usb_ms_header_descriptor ms_header_desc __initdata = { > /* .wTotalLength = DYNAMIC */ > }; > > -/* B.4.3 Embedded MIDI IN Jack Descriptor */ > -static struct usb_midi_in_jack_descriptor jack_in_emb_desc = { > - .bLength = USB_DT_MIDI_IN_SIZE, > - .bDescriptorType = USB_DT_CS_INTERFACE, > - .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, > - .bJackType = USB_MS_EMBEDDED, > - /* .bJackID = DYNAMIC */ > -}; > - > -/* B.4.4 Embedded MIDI OUT Jack Descriptor */ > -static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = { > - /* .bLength = DYNAMIC */ > - .bDescriptorType = USB_DT_CS_INTERFACE, > - .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, > - .bJackType = USB_MS_EMBEDDED, > - /* .bJackID = DYNAMIC */ > - /* .bNrInputPins = DYNAMIC */ > - /* .pins = DYNAMIC */ > -}; > - > /* B.5.1 Standard Bulk OUT Endpoint Descriptor */ > static struct usb_endpoint_descriptor bulk_out_desc = { > .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, > @@ -758,9 +737,11 @@ fail: > static int __init > f_midi_bind(struct usb_configuration *c, struct usb_function *f) > { > - struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12]; > + struct usb_descriptor_header **midi_function; > struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; > + struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS]; > struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS]; > + struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS]; > struct usb_composite_dev *cdev = c->cdev; > struct f_midi *midi = func_to_midi(f); > int status, n, jack = 1, i = 0; > @@ -798,6 +779,15 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) > goto fail; > midi->out_ep->driver_data = cdev; /* claim */ > > + /* allocate temporary function list */ > + midi_function = (struct usb_descriptor_header **) > + kzalloc(sizeof(midi_function) * > + ((MAX_PORTS * 4) + 9), GFP_KERNEL); > + if (!midi_function) { > + status = -ENOMEM; > + goto fail; > + } > + > /* > * construct the function's descriptor set. As the number of > * input and output MIDI ports is configurable, we have to do > @@ -811,73 +801,74 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) > > /* calculate the header's wTotalLength */ > n = USB_DT_MS_HEADER_SIZE > - + (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE > - + (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1); > + + (midi->in_ports + midi->out_ports) * > + (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1)); > ms_header_desc.wTotalLength = cpu_to_le16(n); > > midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc; > > - /* we have one embedded IN jack */ > - jack_in_emb_desc.bJackID = jack++; > - midi_function[i++] = (struct usb_descriptor_header *) &jack_in_emb_desc; > - > - /* and a dynamic amount of external IN jacks */ > - for (n = 0; n < midi->in_ports; n++) { > - struct usb_midi_in_jack_descriptor *ext = &jack_in_ext_desc[n]; > - > - ext->bLength = USB_DT_MIDI_IN_SIZE; > - ext->bDescriptorType = USB_DT_CS_INTERFACE; > - ext->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; > - ext->bJackType = USB_MS_EXTERNAL; > - ext->bJackID = jack++; > - ext->iJack = 0; > - > - midi_function[i++] = (struct usb_descriptor_header *) ext; > - } > - > - /* one embedded OUT jack ... */ > - jack_out_emb_desc.bLength = USB_DT_MIDI_OUT_SIZE(midi->in_ports); > - jack_out_emb_desc.bJackID = jack++; > - jack_out_emb_desc.bNrInputPins = midi->in_ports; > - /* ... which referencess all external IN jacks */ > + /* configure the external IN jacks, each linked to an embedded OUT jack */ > for (n = 0; n < midi->in_ports; n++) { > - jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID; > - jack_out_emb_desc.pins[n].baSourcePin = 1; > + struct usb_midi_in_jack_descriptor *in_ext = &jack_in_ext_desc[n]; > + struct usb_midi_out_jack_descriptor_1 *out_emb = &jack_out_emb_desc[n]; > + > + in_ext->bLength = USB_DT_MIDI_IN_SIZE; > + in_ext->bDescriptorType = USB_DT_CS_INTERFACE; > + in_ext->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; > + in_ext->bJackType = USB_MS_EXTERNAL; > + in_ext->bJackID = jack++; > + in_ext->iJack = 0; > + midi_function[i++] = (struct usb_descriptor_header *) in_ext; > + > + out_emb->bLength = USB_DT_MIDI_OUT_SIZE(1); > + out_emb->bDescriptorType = USB_DT_CS_INTERFACE; > + out_emb->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; > + out_emb->bJackType = USB_MS_EMBEDDED; > + out_emb->bJackID = jack++; > + out_emb->bNrInputPins = 1; > + out_emb->pins[0].baSourcePin = 1; > + out_emb->pins[0].baSourceID = in_ext->bJackID; > + out_emb->iJack = 0; > + midi_function[i++] = (struct usb_descriptor_header *) out_emb; > + > + /* link it to the endpoint */ > + ms_in_desc.baAssocJackID[n] = out_emb->bJackID; > } > > - midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc; > - > - /* and multiple external OUT jacks ... */ > + /* configure the external OUT jacks, each linked to an embedded IN jack */ > for (n = 0; n < midi->out_ports; n++) { > - struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n]; > - int m; > - > - ext->bLength = USB_DT_MIDI_OUT_SIZE(1); > - ext->bDescriptorType = USB_DT_CS_INTERFACE; > - ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; > - ext->bJackType = USB_MS_EXTERNAL; > - ext->bJackID = jack++; > - ext->bNrInputPins = 1; > - ext->iJack = 0; > - /* ... which all reference the same embedded IN jack */ > - for (m = 0; m < midi->out_ports; m++) { > - ext->pins[m].baSourceID = jack_in_emb_desc.bJackID; > - ext->pins[m].baSourcePin = 1; > - } > - > - midi_function[i++] = (struct usb_descriptor_header *) ext; > + struct usb_midi_in_jack_descriptor *in_emb = &jack_in_emb_desc[n]; > + struct usb_midi_out_jack_descriptor_1 *out_ext = &jack_out_ext_desc[n]; > + > + in_emb->bLength = USB_DT_MIDI_IN_SIZE; > + in_emb->bDescriptorType = USB_DT_CS_INTERFACE; > + in_emb->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; > + in_emb->bJackType = USB_MS_EMBEDDED; > + in_emb->bJackID = jack++; > + in_emb->iJack = 0; > + midi_function[i++] = (struct usb_descriptor_header *) in_emb; > + > + out_ext->bLength = USB_DT_MIDI_OUT_SIZE(1); > + out_ext->bDescriptorType = USB_DT_CS_INTERFACE; > + out_ext->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; > + out_ext->bJackType = USB_MS_EXTERNAL; > + out_ext->bJackID = jack++; > + out_ext->bNrInputPins = 1; > + out_ext->iJack = 0; > + out_ext->pins[0].baSourceID = in_emb->bJackID; > + out_ext->pins[0].baSourcePin = 1; > + midi_function[i++] = (struct usb_descriptor_header *) out_ext; > + > + /* link it to the endpoint */ > + ms_out_desc.baAssocJackID[n] = in_emb->bJackID; > } > > /* configure the endpoint descriptors ... */ > ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); > ms_out_desc.bNumEmbMIDIJack = midi->in_ports; > - for (n = 0; n < midi->in_ports; n++) > - ms_out_desc.baAssocJackID[n] = jack_in_emb_desc.bJackID; > > ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); > ms_in_desc.bNumEmbMIDIJack = midi->out_ports; > - for (n = 0; n < midi->out_ports; n++) > - ms_in_desc.baAssocJackID[n] = jack_out_emb_desc.bJackID; > > /* ... and add them to the list */ > midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc; > @@ -901,6 +892,8 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) > f->descriptors = usb_copy_descriptors(midi_function); > } > > + kfree(midi_function); > + > return 0; > > fail: > -- > 1.7.6.4 > > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html