Skip to content

Commit 71e046d

Browse files
committed
add tuh_midi_descriptor_cb()
1 parent b12c8a9 commit 71e046d

File tree

7 files changed

+115
-130
lines changed

7 files changed

+115
-130
lines changed

src/class/audio/audio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ typedef struct TU_ATTR_PACKED
661661
uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors.
662662
uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t.
663663
} audio_desc_cs_ac_interface_t;
664+
TU_VERIFY_STATIC(sizeof(audio_desc_cs_ac_interface_t) == 9, "size is not correct");
664665

665666
/// AUDIO Clock Source Descriptor (4.7.2.1)
666667
typedef struct TU_ATTR_PACKED

src/class/audio/audio_device.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -628,10 +628,6 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio);
628628

629629
#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
630630
static void audiod_parse_for_AS_params(audiod_function_t *audio, uint8_t const *p_desc, uint8_t const *p_desc_end, uint8_t const as_itf);
631-
632-
static inline uint8_t tu_desc_subtype(void const *desc) {
633-
return ((uint8_t const *) desc)[2];
634-
}
635631
#endif
636632

637633
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL

src/class/midi/midi.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -150,27 +150,6 @@ typedef midi_desc_out_jack_n_t(1) midi_desc_out_jack_1in_t; // 1 input
150150
typedef midi_desc_out_jack_1in_t midi_desc_out_jack_t; // backward compatible
151151
TU_VERIFY_STATIC(sizeof(midi_desc_out_jack_1in_t) == 7 + 2 * 1, "size is not correct");
152152

153-
/// MIDI Element Descriptor
154-
typedef struct TU_ATTR_PACKED {
155-
uint8_t bLength ; ///< Size of this descriptor in bytes.
156-
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
157-
uint8_t bDescriptorSubType ; ///< Descriptor SubType
158-
uint8_t bElementID;
159-
160-
uint8_t bNrInputPins;
161-
uint8_t baSourceID;
162-
uint8_t baSourcePin;
163-
164-
uint8_t bNrOutputPins;
165-
uint8_t bInTerminalLink;
166-
uint8_t bOutTerminalLink;
167-
uint8_t bElCapsSize;
168-
169-
uint16_t bmElementCaps;
170-
uint8_t iElement;
171-
} midi_desc_element_t;
172-
TU_VERIFY_STATIC(sizeof(midi_desc_element_t) == 14, "size is not correct");
173-
174153
/// MIDI Element Descriptor with multiple pins
175154
#define midi_desc_element_n_t(input_num) \
176155
struct TU_ATTR_PACKED { \

src/class/midi/midi_host.c

Lines changed: 82 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -194,123 +194,108 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d
194194

195195
midih_interface_t *p_midi = find_new_midi();
196196
TU_VERIFY(p_midi != NULL);
197-
198197
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
199-
// There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface
198+
199+
// There can be just a MIDI or an Audio + MIDI interface
200+
// const uint8_t* p_start = ((uint8_t const*) desc_itf);
201+
const uint8_t* p_end = ((uint8_t const*) desc_itf) + max_len;
200202
uint8_t const *p_desc = (uint8_t const *) desc_itf;
201203
uint16_t len_parsed = 0;
204+
205+
tuh_midi_descriptor_cb_t desc_cb = { 0 };
206+
desc_cb.jack_num = 0;
207+
208+
// If there is Audio Control Interface + Audio Header descriptor, skip it
202209
if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) {
203-
// This driver does not support audio streaming. However, if this is the audio control interface
204-
// there might be a MIDI interface following it. Search through every descriptor until a MIDI
205-
// interface is found or the end of the descriptor is found
206-
while (len_parsed < max_len &&
207-
(desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) {
208-
len_parsed += desc_itf->bLength;
209-
p_desc = tu_desc_next(p_desc);
210-
desc_itf = (tusb_desc_interface_t const *)p_desc;
211-
}
210+
TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t));
212211

212+
p_desc = tu_desc_next(p_desc);
213+
TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
214+
tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_HEADER);
215+
216+
p_desc = tu_desc_next(p_desc);
217+
desc_itf = (tusb_desc_interface_t const *)p_desc;
213218
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
214219
}
215220
TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass);
221+
desc_cb.desc_interface = desc_itf;
222+
216223
len_parsed += desc_itf->bLength;
217224

218225
TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr);
219226
p_midi->itf_num = desc_itf->bInterfaceNumber;
220-
221-
// CS Header descriptor
222227
p_desc = tu_desc_next(p_desc);
223-
midi_desc_header_t const *p_mdh = (midi_desc_header_t const *) p_desc;
224-
TU_VERIFY(p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE &&
225-
p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER);
226-
TU_LOG_DRV(" Interface Header descriptor\r\n");
227-
228-
// p_desc = tu_desc_next(p_desc);
229-
uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descriptor
230-
tusb_desc_endpoint_t const* in_desc = NULL;
231-
tusb_desc_endpoint_t const* out_desc = NULL;
232-
while (len_parsed < max_len) {
233-
TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) ||
234-
(p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) ||
235-
p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT);
236-
237-
if (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) {
238-
// The USB host doesn't really need this information unless it uses
239-
// the string descriptor for a jack or Element
240-
241-
// assume it is an input jack
242-
midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *) p_desc;
243-
if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) {
244-
TU_LOG_DRV(" Interface Header descriptor\r\n");
245-
} else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) {
246-
// Then it is an in jack.
247-
TU_LOG_DRV(" IN Jack %s descriptor \r\n", p_mdij->bJackType == MIDI_JACK_EXTERNAL ? "External" : "Embedded");
248-
} else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) {
249-
// then it is an out jack
250-
TU_LOG_DRV(" OUT Jack %s descriptor\r\n", p_mdij->bJackType == MIDI_JACK_EXTERNAL ? "External" : "Embedded");
251-
} else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) {
252-
// the it is an element;
253-
TU_LOG_DRV("Found element\r\n");
254-
} else {
255-
TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType);
256-
TU_VERIFY(false);// unknown CS Interface sub-type
257-
}
258-
len_parsed += p_mdij->bLength;
259-
} else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) {
260-
TU_LOG_DRV(" CS_ENDPOINT descriptor\r\n");
261-
TU_VERIFY(prev_ep_addr != 0);
262-
// parse out the mapping between the device's embedded jacks and the endpoints
263-
// Each embedded IN jack is associated with an OUT endpoint
264-
midi_desc_cs_endpoint_t const *p_csep = (midi_desc_cs_endpoint_t const *) p_mdh;
265-
if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) {
266-
TU_VERIFY(p_midi->ep_out == prev_ep_addr);
267-
TU_VERIFY(p_midi->num_cables_tx == 0);
268-
p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack;
269-
} else {
270-
TU_VERIFY(p_midi->ep_in == prev_ep_addr);
271-
TU_VERIFY(p_midi->num_cables_rx == 0);
272-
p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack;
273-
}
274-
len_parsed += p_csep->bLength;
275-
prev_ep_addr = 0;
276-
} else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) {
277-
// parse out the bulk endpoint info
278-
tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_mdh;
279-
TU_LOG_DRV(" Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress);
280-
if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) {
281-
TU_VERIFY(p_midi->ep_out == 0);
282-
TU_VERIFY(p_midi->num_cables_tx == 0);
283-
p_midi->ep_out = p_ep->bEndpointAddress;
284-
prev_ep_addr = p_midi->ep_out;
285-
out_desc = p_ep;
286-
} else {
287-
TU_VERIFY(p_midi->ep_in == 0);
288-
TU_VERIFY(p_midi->num_cables_rx == 0);
289-
p_midi->ep_in = p_ep->bEndpointAddress;
290-
prev_ep_addr = p_midi->ep_in;
291-
in_desc = p_ep;
228+
229+
bool found_new_interface = false;
230+
while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) {
231+
switch (tu_desc_type(p_desc)) {
232+
case TUSB_DESC_INTERFACE:
233+
found_new_interface = true;
234+
break;
235+
236+
case TUSB_DESC_CS_INTERFACE:
237+
switch (tu_desc_subtype(p_desc)) {
238+
case MIDI_CS_INTERFACE_HEADER:
239+
TU_LOG_DRV(" Interface Header descriptor\r\n");
240+
desc_cb.desc_header = p_desc;
241+
break;
242+
243+
case MIDI_CS_INTERFACE_IN_JACK:
244+
case MIDI_CS_INTERFACE_OUT_JACK: {
245+
TU_LOG_DRV(" Jack %s %s descriptor \r\n",
246+
tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT",
247+
p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded");
248+
desc_cb.desc_jack[desc_cb.jack_num++] = p_desc;
249+
break;
250+
}
251+
252+
case MIDI_CS_INTERFACE_ELEMENT:
253+
TU_LOG_DRV(" Element descriptor\r\n");
254+
desc_cb.desc_element = p_desc;
255+
break;
256+
257+
default:
258+
TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc));
259+
break;
260+
}
261+
break;
262+
263+
case TUSB_DESC_ENDPOINT: {
264+
tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_desc;
265+
p_desc = tu_desc_next(p_desc); // next to CS endpoint
266+
TU_VERIFY(p_desc < p_end && tu_desc_next(p_desc) <= p_end);
267+
midi_desc_cs_endpoint_t const *p_csep = (midi_desc_cs_endpoint_t const *) p_desc;
268+
269+
TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress);
270+
if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) {
271+
p_midi->ep_out = p_ep->bEndpointAddress;
272+
p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack;
273+
desc_cb.desc_epout = p_ep;
274+
275+
TU_ASSERT(tuh_edpt_open(dev_addr, p_ep));
276+
tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep);
277+
} else {
278+
p_midi->ep_in = p_ep->bEndpointAddress;
279+
p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack;
280+
desc_cb.desc_epin = p_ep;
281+
282+
TU_ASSERT(tuh_edpt_open(dev_addr, p_ep));
283+
tu_edpt_stream_open(&p_midi->ep_stream.rx, p_ep);
284+
}
285+
break;
292286
}
293-
len_parsed += p_mdh->bLength;
287+
288+
default: break; // skip unknown descriptor
294289
}
295290
p_desc = tu_desc_next(p_desc);
296-
p_mdh = (midi_desc_header_t const *) p_desc;
297291
}
298-
TU_VERIFY((p_midi->ep_out != 0 && p_midi->num_cables_tx != 0) ||
299-
(p_midi->ep_in != 0 && p_midi->num_cables_rx != 0));
292+
desc_cb.desc_interface_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf);
300293

301-
if (in_desc) {
302-
TU_ASSERT(tuh_edpt_open(dev_addr, in_desc));
303-
tu_edpt_stream_open(&p_midi->ep_stream.rx, in_desc);
304-
}
305-
if (out_desc) {
306-
TU_ASSERT(tuh_edpt_open(dev_addr, out_desc));
307-
tu_edpt_stream_open(&p_midi->ep_stream.tx, out_desc);
308-
}
309294
p_midi->dev_addr = dev_addr;
310295

311-
// if (tuh_midi_interface_descriptor_cb) {
312-
// tuh_midi_interface_descriptor_cb(dev_addr, desc_itf, );
313-
// }
296+
if (tuh_midi_descriptor_cb) {
297+
tuh_midi_descriptor_cb(dev_addr, &desc_cb);
298+
}
314299

315300
return true;
316301
}

src/class/midi/midi_host.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@
6262
//--------------------------------------------------------------------+
6363
// Application API
6464
//--------------------------------------------------------------------+
65+
typedef struct {
66+
const tusb_desc_interface_t* desc_interface; // start of whole midi interface descriptor
67+
uint16_t desc_interface_len;
68+
69+
const uint8_t* desc_header;
70+
const uint8_t* desc_element;
71+
const tusb_desc_endpoint_t* desc_epin; // endpoint IN descriptor, CS_ENDPOINT is right after
72+
const tusb_desc_endpoint_t* desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after
73+
74+
uint8_t jack_num;
75+
const uint8_t* desc_jack[16]; // list of jack descriptors (embedded + external)
76+
} tuh_midi_descriptor_cb_t;
6577

6678
// Check if MIDI interface is mounted
6779
bool tuh_midi_mounted(uint8_t dev_addr);
@@ -134,7 +146,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *
134146

135147
// Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed.
136148
// Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready.
137-
// TU_ATTR_WEAK void tuh_midi_interface_descriptor_cb(uint8_t dev_addr, const uint8_t* desc_itf, uint16_t desc_len);
149+
TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t dev_addr, tuh_midi_descriptor_cb_t const* desc_cb);
138150

139151
// Invoked when device with MIDI interface is mounted.
140152
TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx);

src/common/tusb_types.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ typedef enum {
281281
// TODO remove
282282
enum {
283283
DESC_OFFSET_LEN = 0,
284-
DESC_OFFSET_TYPE = 1
284+
DESC_OFFSET_TYPE = 1,
285+
DESC_OFFSET_SUBTYPE = 2
285286
};
286287

287288
enum {
@@ -570,14 +571,19 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* des
570571
return desc8 + desc8[DESC_OFFSET_LEN];
571572
}
572573

574+
// get descriptor length
575+
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
576+
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
577+
}
578+
573579
// get descriptor type
574580
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
575581
return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
576582
}
577583

578-
// get descriptor length
579-
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
580-
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
584+
// get descriptor subtype
585+
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) {
586+
return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE];
581587
}
582588

583589
// find descriptor that match byte1 (type)

src/tusb.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,23 +142,29 @@ void tusb_int_handler(uint8_t rhport, bool in_isr) {
142142

143143
uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) {
144144
while (desc + 1 < end) {
145-
if (desc[1] == byte1) return desc;
145+
if (desc[1] == byte1) {
146+
return desc;
147+
}
146148
desc += desc[DESC_OFFSET_LEN];
147149
}
148150
return NULL;
149151
}
150152

151153
uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) {
152154
while (desc + 2 < end) {
153-
if (desc[1] == byte1 && desc[2] == byte2) return desc;
155+
if (desc[1] == byte1 && desc[2] == byte2) {
156+
return desc;
157+
}
154158
desc += desc[DESC_OFFSET_LEN];
155159
}
156160
return NULL;
157161
}
158162

159163
uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) {
160164
while (desc + 3 < end) {
161-
if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) return desc;
165+
if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) {
166+
return desc;
167+
}
162168
desc += desc[DESC_OFFSET_LEN];
163169
}
164170
return NULL;

0 commit comments

Comments
 (0)