Merge "usb: gadget: MIDI: Add support for SuperSpeed enumeration"
This commit is contained in:
commit
f7a2f37c6b
1 changed files with 54 additions and 1 deletions
|
@ -167,6 +167,15 @@ static struct usb_endpoint_descriptor bulk_in_desc = {
|
||||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct usb_ss_ep_comp_descriptor ss_bulk_comp_desc = {
|
||||||
|
.bLength = sizeof(ss_bulk_comp_desc),
|
||||||
|
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||||
|
|
||||||
|
/* the following 2 values can be tweaked if necessary */
|
||||||
|
/* .bMaxBurst = 0, */
|
||||||
|
/* .bmAttributes = 0, */
|
||||||
|
};
|
||||||
|
|
||||||
/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
|
/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
|
||||||
static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
|
static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
|
||||||
/* .bLength = DYNAMIC */
|
/* .bLength = DYNAMIC */
|
||||||
|
@ -720,6 +729,7 @@ fail:
|
||||||
static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
{
|
{
|
||||||
struct usb_descriptor_header **midi_function;
|
struct usb_descriptor_header **midi_function;
|
||||||
|
struct usb_descriptor_header **midi_ss_function;
|
||||||
struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
|
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_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_ext_desc[MAX_PORTS];
|
||||||
|
@ -727,7 +737,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
struct usb_composite_dev *cdev = c->cdev;
|
struct usb_composite_dev *cdev = c->cdev;
|
||||||
struct f_midi *midi = func_to_midi(f);
|
struct f_midi *midi = func_to_midi(f);
|
||||||
struct usb_string *us;
|
struct usb_string *us;
|
||||||
int status, n, jack = 1, i = 0;
|
int status, n, jack = 1, i = 0, j = 0;
|
||||||
|
|
||||||
midi->gadget = cdev->gadget;
|
midi->gadget = cdev->gadget;
|
||||||
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
|
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
|
||||||
|
@ -767,11 +777,20 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
if (!midi->out_ep)
|
if (!midi->out_ep)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/* allocate temporary function list for ss */
|
||||||
|
midi_ss_function = kcalloc((MAX_PORTS * 4) + 11,
|
||||||
|
sizeof(*midi_ss_function), GFP_KERNEL);
|
||||||
|
if (!midi_ss_function) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate temporary function list */
|
/* allocate temporary function list */
|
||||||
midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
|
midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!midi_function) {
|
if (!midi_function) {
|
||||||
status = -ENOMEM;
|
status = -ENOMEM;
|
||||||
|
kfree(midi_ss_function);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,6 +804,12 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &ac_interface_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &ac_interface_desc;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &ac_header_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &ac_header_desc;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &ms_interface_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &ms_interface_desc;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) &ac_interface_desc;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) &ac_header_desc;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) &ms_interface_desc;
|
||||||
|
|
||||||
/* calculate the header's wTotalLength */
|
/* calculate the header's wTotalLength */
|
||||||
n = USB_DT_MS_HEADER_SIZE
|
n = USB_DT_MS_HEADER_SIZE
|
||||||
|
@ -793,6 +818,8 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
ms_header_desc.wTotalLength = cpu_to_le16(n);
|
ms_header_desc.wTotalLength = cpu_to_le16(n);
|
||||||
|
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) &ms_header_desc;
|
||||||
|
|
||||||
/* configure the external IN jacks, each linked to an embedded OUT jack */
|
/* configure the external IN jacks, each linked to an embedded OUT jack */
|
||||||
for (n = 0; n < midi->in_ports; n++) {
|
for (n = 0; n < midi->in_ports; n++) {
|
||||||
|
@ -806,6 +833,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
in_ext->bJackID = jack++;
|
in_ext->bJackID = jack++;
|
||||||
in_ext->iJack = 0;
|
in_ext->iJack = 0;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) in_ext;
|
midi_function[i++] = (struct usb_descriptor_header *) in_ext;
|
||||||
|
midi_ss_function[j++] = (struct usb_descriptor_header *) in_ext;
|
||||||
|
|
||||||
out_emb->bLength = USB_DT_MIDI_OUT_SIZE(1);
|
out_emb->bLength = USB_DT_MIDI_OUT_SIZE(1);
|
||||||
out_emb->bDescriptorType = USB_DT_CS_INTERFACE;
|
out_emb->bDescriptorType = USB_DT_CS_INTERFACE;
|
||||||
|
@ -817,6 +845,8 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
out_emb->pins[0].baSourceID = in_ext->bJackID;
|
out_emb->pins[0].baSourceID = in_ext->bJackID;
|
||||||
out_emb->iJack = 0;
|
out_emb->iJack = 0;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) out_emb;
|
midi_function[i++] = (struct usb_descriptor_header *) out_emb;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) out_emb;
|
||||||
|
|
||||||
/* link it to the endpoint */
|
/* link it to the endpoint */
|
||||||
ms_in_desc.baAssocJackID[n] = out_emb->bJackID;
|
ms_in_desc.baAssocJackID[n] = out_emb->bJackID;
|
||||||
|
@ -834,6 +864,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
in_emb->bJackID = jack++;
|
in_emb->bJackID = jack++;
|
||||||
in_emb->iJack = 0;
|
in_emb->iJack = 0;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) in_emb;
|
midi_function[i++] = (struct usb_descriptor_header *) in_emb;
|
||||||
|
midi_ss_function[j++] = (struct usb_descriptor_header *) in_emb;
|
||||||
|
|
||||||
out_ext->bLength = USB_DT_MIDI_OUT_SIZE(1);
|
out_ext->bLength = USB_DT_MIDI_OUT_SIZE(1);
|
||||||
out_ext->bDescriptorType = USB_DT_CS_INTERFACE;
|
out_ext->bDescriptorType = USB_DT_CS_INTERFACE;
|
||||||
|
@ -845,6 +876,8 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
out_ext->pins[0].baSourceID = in_emb->bJackID;
|
out_ext->pins[0].baSourceID = in_emb->bJackID;
|
||||||
out_ext->pins[0].baSourcePin = 1;
|
out_ext->pins[0].baSourcePin = 1;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) out_ext;
|
midi_function[i++] = (struct usb_descriptor_header *) out_ext;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) out_ext;
|
||||||
|
|
||||||
/* link it to the endpoint */
|
/* link it to the endpoint */
|
||||||
ms_out_desc.baAssocJackID[n] = in_emb->bJackID;
|
ms_out_desc.baAssocJackID[n] = in_emb->bJackID;
|
||||||
|
@ -864,6 +897,16 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &ms_in_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &ms_in_desc;
|
||||||
midi_function[i++] = NULL;
|
midi_function[i++] = NULL;
|
||||||
|
|
||||||
|
midi_ss_function[j++] = (struct usb_descriptor_header *) &bulk_out_desc;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) &ss_bulk_comp_desc;
|
||||||
|
midi_ss_function[j++] = (struct usb_descriptor_header *) &ms_out_desc;
|
||||||
|
midi_ss_function[j++] = (struct usb_descriptor_header *) &bulk_in_desc;
|
||||||
|
midi_ss_function[j++] =
|
||||||
|
(struct usb_descriptor_header *) &ss_bulk_comp_desc;
|
||||||
|
midi_ss_function[j++] = (struct usb_descriptor_header *) &ms_in_desc;
|
||||||
|
midi_ss_function[j++] = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* support all relevant hardware speeds... we expect that when
|
* support all relevant hardware speeds... we expect that when
|
||||||
* hardware is dual speed, all bulk-capable endpoints work at
|
* hardware is dual speed, all bulk-capable endpoints work at
|
||||||
|
@ -882,13 +925,23 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
goto fail_f_midi;
|
goto fail_f_midi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gadget_is_superspeed(c->cdev->gadget)) {
|
||||||
|
bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024);
|
||||||
|
bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024);
|
||||||
|
f->ss_descriptors = usb_copy_descriptors(midi_ss_function);
|
||||||
|
if (!f->ss_descriptors)
|
||||||
|
goto fail_f_midi;
|
||||||
|
}
|
||||||
|
|
||||||
kfree(midi_function);
|
kfree(midi_function);
|
||||||
|
kfree(midi_ss_function);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_f_midi:
|
fail_f_midi:
|
||||||
kfree(midi_function);
|
kfree(midi_function);
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
|
kfree(midi_ss_function);
|
||||||
fail:
|
fail:
|
||||||
f_midi_unregister_card(midi);
|
f_midi_unregister_card(midi);
|
||||||
fail_register:
|
fail_register:
|
||||||
|
|
Loading…
Add table
Reference in a new issue