};
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
-DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
+DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
DECLARE_USB_MS20_ENDPOINT_DESCRIPTOR(32);
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0, // to be filled
.bAlternateSetting = 0,
- .bNumEndpoints = 2,
+ .bNumEndpoints = 2, // to be filled
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING,
.bInterfaceProtocol = 0,
.wTotalLength = __cpu_to_le16(0x41), // to be calculated
};
-/* MIDI 1.0 IN (Embedded) Jack */
-static struct usb_midi_in_jack_descriptor midi2_midi1_in_jack1_desc = {
- .bLength = 0x06,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MS_MIDI_IN_JACK,
- .bJackType = USB_MS_EMBEDDED,
- .bJackID = 0x01,
- .iJack = 0,
-};
-
-/* MIDI 1.0 IN (External) Jack */
-static struct usb_midi_in_jack_descriptor midi2_midi1_in_jack2_desc = {
- .bLength = 0x06,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MS_MIDI_IN_JACK,
- .bJackType = USB_MS_EXTERNAL,
- .bJackID = 0x02,
- .iJack = 0,
-};
-
-/* MIDI 1.0 OUT (Embedded) Jack */
-static struct usb_midi_out_jack_descriptor_1 midi2_midi1_out_jack1_desc = {
- .bLength = 0x09,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK,
- .bJackType = USB_MS_EMBEDDED,
- .bJackID = 0x03,
- .bNrInputPins = 1,
- .pins = { { 0x02, 0x01 } },
- .iJack = 0,
-};
-
-/* MIDI 1.0 OUT (External) Jack */
-static struct usb_midi_out_jack_descriptor_1 midi2_midi1_out_jack2_desc = {
- .bLength = 0x09,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK,
- .bJackType = USB_MS_EXTERNAL,
- .bJackID = 0x04,
- .bNrInputPins = 1,
- .pins = { { 0x01, 0x01 } },
- .iJack = 0,
-};
-
/* MIDI 1.0 EP OUT */
static struct usb_endpoint_descriptor midi2_midi1_ep_out_desc = {
.bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
-static struct usb_ms_endpoint_descriptor_1 midi2_midi1_ep_out_class_desc = {
- .bLength = 0x05,
+static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_out_class_desc = {
+ .bLength = 0x05, // to be filled
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubtype = USB_MS_GENERAL,
.bNumEmbMIDIJack = 1,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
-static struct usb_ms_endpoint_descriptor_1 midi2_midi1_ep_in_class_desc = {
- .bLength = 0x05,
+static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_in_class_desc = {
+ .bLength = 0x05, // to be filled
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubtype = USB_MS_GENERAL,
.bNumEmbMIDIJack = 1,
static void *midi2_midi1_descs[] = {
&midi2_midi1_if_desc,
&midi2_midi1_class_desc,
- &midi2_midi1_in_jack1_desc,
- &midi2_midi1_in_jack2_desc,
- &midi2_midi1_out_jack1_desc,
- &midi2_midi1_out_jack2_desc,
NULL
};
-static void *midi2_midi1_ep_descs[] = {
+static void *midi2_midi1_ep_out_descs[] = {
&midi2_midi1_ep_out_desc,
&midi2_midi1_ep_out_class_desc,
+ NULL
+};
+
+static void *midi2_midi1_ep_in_descs[] = {
&midi2_midi1_ep_in_desc,
&midi2_midi1_ep_in_class_desc,
NULL
};
-static void *midi2_midi1_ep_ss_descs[] = {
+static void *midi2_midi1_ep_out_ss_descs[] = {
&midi2_midi1_ep_out_desc,
&midi2_midi1_ep_out_ss_comp_desc,
&midi2_midi1_ep_out_class_desc,
+ NULL
+};
+
+static void *midi2_midi1_ep_in_ss_descs[] = {
&midi2_midi1_ep_in_desc,
&midi2_midi1_ep_in_ss_comp_desc,
&midi2_midi1_ep_in_class_desc,
struct usb_descriptor_header **list;
unsigned int size;
unsigned int alloc;
+
+ /* MIDI 1.0 jacks */
+ unsigned char jack_in, jack_out, jack_id;
+ struct usb_midi_in_jack_descriptor jack_ins[16];
+ struct usb_midi_out_jack_descriptor_1 jack_outs[16];
};
static int append_config(struct f_midi2_usb_config *config, void *d)
return 0;
}
+static int append_midi1_in_jack(struct f_midi2 *midi2,
+ struct f_midi2_usb_config *config,
+ unsigned int type)
+{
+ struct usb_midi_in_jack_descriptor *jack =
+ &config->jack_ins[config->jack_in++];
+ int id = ++config->jack_id;
+ int err;
+
+ jack->bLength = 0x06;
+ jack->bDescriptorType = USB_DT_CS_INTERFACE;
+ jack->bDescriptorSubtype = USB_MS_MIDI_IN_JACK;
+ jack->bJackType = type;
+ jack->bJackID = id;
+ jack->iJack = midi2->strings[STR_GTB1].id; // TODO: better names?
+
+ err = append_config(config, jack);
+ if (err < 0)
+ return err;
+ return id;
+}
+
+static int append_midi1_out_jack(struct f_midi2 *midi2,
+ struct f_midi2_usb_config *config,
+ unsigned int type, unsigned int source)
+{
+ struct usb_midi_out_jack_descriptor_1 *jack =
+ &config->jack_outs[config->jack_out++];
+ int id = ++config->jack_id;
+ int err;
+
+ jack->bLength = 0x09;
+ jack->bDescriptorType = USB_DT_CS_INTERFACE;
+ jack->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK;
+ jack->bJackType = type;
+ jack->bJackID = id;
+ jack->bNrInputPins = 1;
+ jack->pins[0].baSourceID = source;
+ jack->pins[0].baSourcePin = 0x01;
+ jack->iJack = midi2->strings[STR_GTB1].id; // TODO: better names?
+
+ err = append_config(config, jack);
+ if (err < 0)
+ return err;
+ return id;
+}
+
static int f_midi2_create_usb_configs(struct f_midi2 *midi2,
struct f_midi2_usb_config *config,
int speed)
{
- void **midi1_eps;
- int i, err;
+ struct f_midi2_block *blk = &midi2->midi2_eps[0].blks[0];
+ void **midi1_in_eps, **midi1_out_eps;
+ int i, jack, total;
+ int err;
switch (speed) {
default:
cpu_to_le16(512);
fallthrough;
case USB_SPEED_FULL:
- midi1_eps = midi2_midi1_ep_descs;
+ midi1_in_eps = midi2_midi1_ep_in_descs;
+ midi1_out_eps = midi2_midi1_ep_out_descs;
break;
case USB_SPEED_SUPER:
case USB_SPEED_SUPER_PLUS:
for (i = 0; i < midi2->num_eps; i++)
midi2_midi2_ep_out_desc[i].wMaxPacketSize =
cpu_to_le16(1024);
- midi1_eps = midi2_midi1_ep_ss_descs;
+ midi1_in_eps = midi2_midi1_ep_in_ss_descs;
+ midi1_out_eps = midi2_midi1_ep_out_ss_descs;
break;
}
err = append_configs(config, midi2_audio_descs);
if (err < 0)
return err;
+
+ switch (blk->info.direction) {
+ case SNDRV_UMP_DIR_INPUT:
+ case SNDRV_UMP_DIR_OUTPUT:
+ midi2_midi1_if_desc.bNumEndpoints = 1;
+ break;
+ default:
+ midi2_midi1_if_desc.bNumEndpoints = 2;
+ break;
+ }
+
err = append_configs(config, midi2_midi1_descs);
if (err < 0)
return err;
- err = append_configs(config, midi1_eps);
- if (err < 0)
- return err;
+
+ total = USB_DT_MS_HEADER_SIZE;
+ if (blk->info.direction != SNDRV_UMP_DIR_INPUT) {
+ midi2_midi1_ep_out_class_desc.bLength =
+ USB_DT_MS_ENDPOINT_SIZE(blk->info.num_groups);
+ total += midi2_midi1_ep_out_class_desc.bLength;
+ midi2_midi1_ep_out_class_desc.bNumEmbMIDIJack =
+ blk->info.num_groups;
+ total += blk->info.num_groups *
+ (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
+ for (i = 0; i < blk->info.num_groups; i++) {
+ jack = append_midi1_in_jack(midi2, config,
+ USB_MS_EMBEDDED);
+ if (jack < 0)
+ return jack;
+ midi2_midi1_ep_out_class_desc.baAssocJackID[i] = jack;
+ jack = append_midi1_out_jack(midi2, config,
+ USB_MS_EXTERNAL, jack);
+ if (jack < 0)
+ return jack;
+ }
+ }
+
+ if (blk->info.direction != SNDRV_UMP_DIR_OUTPUT) {
+ midi2_midi1_ep_in_class_desc.bLength =
+ USB_DT_MS_ENDPOINT_SIZE(blk->info.num_groups);
+ total += midi2_midi1_ep_in_class_desc.bLength;
+ midi2_midi1_ep_in_class_desc.bNumEmbMIDIJack =
+ blk->info.num_groups;
+ total += blk->info.num_groups *
+ (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
+ for (i = 0; i < blk->info.num_groups; i++) {
+ jack = append_midi1_in_jack(midi2, config,
+ USB_MS_EXTERNAL);
+ if (jack < 0)
+ return jack;
+ jack = append_midi1_out_jack(midi2, config,
+ USB_MS_EMBEDDED, jack);
+ if (jack < 0)
+ return jack;
+ midi2_midi1_ep_in_class_desc.baAssocJackID[i] = jack;
+ }
+ }
+
+ midi2_midi1_class_desc.wTotalLength = cpu_to_le16(total);
+
+ if (blk->info.direction != SNDRV_UMP_DIR_INPUT) {
+ err = append_configs(config, midi1_out_eps);
+ if (err < 0)
+ return err;
+ }
+ if (blk->info.direction != SNDRV_UMP_DIR_OUTPUT) {
+ err = append_configs(config, midi1_in_eps);
+ if (err < 0)
+ return err;
+ }
+
err = append_configs(config, midi2_midi2_descs);
if (err < 0)
return err;
midi2_audio_class_desc.baInterfaceNr[0] = status;
/* allocate instance-specific endpoints */
- status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_in,
- &midi2_midi1_ep_in_desc, 0, NULL);
- if (status)
- goto fail;
- status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_out,
- &midi2_midi1_ep_out_desc, 0, NULL);
- if (status)
- goto fail;
+ if (midi2->midi2_eps[0].blks[0].info.direction != SNDRV_UMP_DIR_OUTPUT) {
+ status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_in,
+ &midi2_midi1_ep_in_desc, 0, NULL);
+ if (status)
+ goto fail;
+ }
+
+ if (midi2->midi2_eps[0].blks[0].info.direction != SNDRV_UMP_DIR_INPUT) {
+ status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_out,
+ &midi2_midi1_ep_out_desc, 0, NULL);
+ if (status)
+ goto fail;
+ }
for (i = 0; i < midi2->num_eps; i++) {
status = f_midi2_init_midi2_ep_in(midi2, i);