Control Surface pin-t-adl
MIDI Control Surface library for Arduino
TeensyHostMIDI-claim.ipp
Go to the documentation of this file.
1// The following function was reused from the USBHost_t36 library
2// https://github.com/PaulStoffregen/USBHost_t36/blob/d864c8cc33d8dbcd9501e354e777d90f6ac88037/midi.cpp#L62-L220
3
4/* USB EHCI Host for Teensy 3.6
5 * Copyright 2017 Paul Stoffregen (paul@pjrc.com)
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27// Audio Class-Specific Descriptor Types (audio 1.0, page 99)
28// CS_UNDEFINED 0x20
29// CS_DEVICE 0x21
30// CS_CONFIGURATION 0x22
31// CS_STRING 0x23
32// CS_INTERFACE 0x24
33// CS_ENDPOINT 0x25
34// MS Class-Specific Interface Descriptor Subtypes (midi 1.0, page 36)
35// MS_DESCRIPTOR_UNDEFINED 0x00
36// MS_HEADER 0x01
37// MIDI_IN_JACK 0x02
38// MIDI_OUT_JACK 0x03
39// ELEMENT 0x04
40// MS Class-Specific Endpoint Descriptor Subtypes (midi 1.0, page 36)
41// DESCRIPTOR_UNDEFINED 0x00
42// MS_GENERAL 0x01
43// MS MIDI IN and OUT Jack types (midi 1.0, page 36)
44// JACK_TYPE_UNDEFINED 0x00
45// EMBEDDED 0x01
46// EXTERNAL 0x02
47// Endpoint Control Selectors (midi 1.0, page 36)
48// EP_CONTROL_UNDEFINED 0x00
49// ASSOCIATION_CONTROL 0x01
50
52
53template <uint16_t MaxPacketSize>
54bool TeensyHostMIDI<MaxPacketSize>::claim_if_midi(Device_t *dev, int type,
55 const uint8_t *descriptors,
56 uint32_t len) {
57 USBHost::println_("MIDIDevice claim this=", (uintptr_t)this, HEX);
58 USBHost::println_("len = ", len);
59
60 const uint8_t *p = descriptors;
61 const uint8_t *end = p + len;
62
63 if (p[0] != 9 || p[1] != 4)
64 return false; // interface descriptor
65 // USBHost::println_(" bInterfaceClass=", p[5]);
66 // USBHost::println_(" bInterfaceSubClass=", p[6]);
67 bool ismidi = false;
68 if (p[5] == 1 && p[6] == 3) {
69 USBHost::println_(
70 " Interface is MIDI"); // p[5] is bInterfaceClass: 1 = Audio class
71 ismidi = true; // p[6] is bInterfaceSubClass: 3 = MIDI
72 } else {
73 if (p[5] >= 2 && p[5] <= 18)
74 return false; // definitely not MIDI
75 // Yamaha uses vendor specific class, but can be
76 // identified as MIDI from CS_INTERFACE descriptors.
77 // https://forum.pjrc.com/threads/55142?p=199162&viewfull=1#post199162
78 USBHost::println_(" Interface is unknown (might be Yahama)");
79 }
80 p += 9;
81 rx_ep = 0;
82 tx_ep = 0;
83
84 while (p < end) {
85 len = *p;
86 if (len < 4)
87 return false; // all audio desc are at least 4 bytes
88 if (p + len > end)
89 return false; // reject if beyond end of data
90 uint32_t type = p[1];
91 USBHost::print_("type: ", type);
92 USBHost::println_(", len: ", len);
93 if (type == 4 || type == 11)
94 break; // interface or IAD, not for us
95 if (type == 0x24) { // 0x24 = Audio CS_INTERFACE, audio 1.0, page 99
96 uint32_t subtype = p[2];
97 // USBHost::println_("subtype: ", subtype);
98 if (subtype == 1) {
99 // Interface Header, midi 1.0, page 21
100 USBHost::println_(" MIDI Header (ignored)");
101 ismidi = true;
102 } else if (subtype == 2) {
103 // MIDI IN Jack, midi 1.0, page 22
104 USBHost::println_(" MIDI IN Jack (ignored)");
105 ismidi = true;
106 } else if (subtype == 3) {
107 // MIDI OUT Jack, midi 1.0, page 22
108 USBHost::println_(" MIDI OUT Jack (ignored)");
109 ismidi = true;
110 } else if (subtype == 4) {
111 // Element Descriptor, midi 1.0, page 23-24
112 USBHost::println_(" MIDI Element (ignored)");
113 ismidi = true;
114 } else if (subtype == 0xF1 && p[3] == 2) {
115 // see Linux sound/usb/quirks.c create_roland_midi_quirk()
116 USBHost::println_(" Roland vendor-specific (ignored)");
117 ismidi = true;
118 } else {
119 USBHost::println_(" Unknown MIDI CS_INTERFACE descriptor!");
120 return false; // unknown
121 }
122 } else if (type == 5) {
123 // endpoint descriptor
124 if (p[0] < 7)
125 return false; // at least 7 bytes
126 if (p[3] != 2 && p[3] != 3)
127 return false; // must be bulk or interrupt type
128 USBHost::println_(" MIDI Endpoint: ", p[2], HEX);
129 switch (p[2] & 0xF0) {
130 case 0x80:
131 // IN endpoint
132 if (rx_ep == 0) {
133 rx_ep = p[2] & 0x0F;
134 rx_ep_type = p[3];
135 rx_size = p[4] | (p[5] << 8);
136 USBHost::println_(" rx_size = ", rx_size);
137 }
138 break;
139 case 0x00:
140 // OUT endpoint
141 if (tx_ep == 0) {
142 tx_ep = p[2];
143 tx_ep_type = p[3];
144 tx_size = p[4] | (p[5] << 8);
145 USBHost::println_(" tx_size = ", tx_size);
146 }
147 break;
148 default: return false;
149 }
150 } else if (type == 37) {
151 // MIDI endpoint info, midi 1.0: 6.2.2, page 26
152 USBHost::println_(" MIDI Endpoint Jack Association (ignored)");
153 } else {
154 USBHost::println_(" Unknown descriptor, type=", type);
155 return false; // unknown
156 }
157 p += len;
158 }
159
160 return ismidi;
161}
162
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
bool claim_if_midi(Device_t *device, int type, const uint8_t *descriptors, uint32_t len)
static constexpr size_t len(T(&)[N])