Re: [PATCH] USB: gadget: fix MIDI gadget jack allocation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux