1 /*
2  * Copyright (c) 2022, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef USB_MIDI_H
7 #define USB_MIDI_H
8 
9 /* bDescriptorSubType */
10 #define MIDI_VC_HEADER_DESCRIPTOR_SUBTYPE     0x01U
11 #define MIDI_MS_HEADER_DESCRIPTOR_SUBTYPE     0x01U
12 #define MIDI_MS_GENERAL_DESCRIPTOR_SUBTYPE    0x01U
13 #define MIDI_MIDI_IN_JACK_DESCRIPTOR_SUBTYPE  0x02U
14 #define MIDI_MIDI_OUT_JACK_DESCRIPTOR_SUBTYPE 0x03U
15 
16 /* bJackType */
17 #define MIDI_JACK_TYPE_EMBEDDED 0x01
18 #define MIDI_JACK_TYPE_EXTERNAL 0x02
19 
20 #define MIDI_CHANNEL_OMNI 0
21 #define MIDI_CHANNEL_OFF  17
22 
23 #define MIDI_PITCHBEND_MIN -8192
24 #define MIDI_PITCHBEND_MAX 8191
25 
26 /*! Enumeration of MIDI code index number */
27 enum MidiCodeIndexNumber {
28     MIDI_CIN_MISC              = 0,
29     MIDI_CIN_CABLE_EVENT       = 1,
30     MIDI_CIN_SYSCOM_2BYTE      = 2, ///< 2 byte system common message e.g MTC, SongSelect
31     MIDI_CIN_SYSCOM_3BYTE      = 3, ///< 3 byte system common message e.g SPP
32     MIDI_CIN_SYSEX_START       = 4, ///< SysEx starts or continue
33     MIDI_CIN_SYSEX_END_1BYTE   = 5, ///< SysEx ends with 1 data, or 1 byte system common message
34     MIDI_CIN_SYSEX_END_2BYTE   = 6, ///< SysEx ends with 2 data
35     MIDI_CIN_SYSEX_END_3BYTE   = 7, ///< SysEx ends with 3 data
36     MIDI_CIN_NOTE_OFF          = 8,
37     MIDI_CIN_NOTE_ON           = 9,
38     MIDI_CIN_POLY_KEYPRESS     = 10,
39     MIDI_CIN_CONTROL_CHANGE    = 11,
40     MIDI_CIN_PROGRAM_CHANGE    = 12,
41     MIDI_CIN_CHANNEL_PRESSURE  = 13,
42     MIDI_CIN_PITCH_BEND_CHANGE = 14,
43     MIDI_CIN_1BYTE_DATA        = 15
44 };
45 
46 /*! Enumeration of MIDI types */
47 enum MidiType {
48     InvalidType = 0x00,          ///< For notifying errors
49     NoteOff = 0x80,              ///< Note Off
50     NoteOn = 0x90,               ///< Note On
51     AfterTouchPoly = 0xA0,       ///< Polyphonic AfterTouch
52     ControlChange = 0xB0,        ///< Control Change / Channel Mode
53     ProgramChange = 0xC0,        ///< Program Change
54     AfterTouchChannel = 0xD0,    ///< Channel (monophonic) AfterTouch
55     PitchBend = 0xE0,            ///< Pitch Bend
56     SystemExclusive = 0xF0,      ///< System Exclusive
57     TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame
58     SongPosition = 0xF2,         ///< System Common - Song Position Pointer
59     SongSelect = 0xF3,           ///< System Common - Song Select
60     TuneRequest = 0xF6,          ///< System Common - Tune Request
61     Clock = 0xF8,                ///< System Real Time - Timing Clock
62     Start = 0xFA,                ///< System Real Time - Start
63     Continue = 0xFB,             ///< System Real Time - Continue
64     Stop = 0xFC,                 ///< System Real Time - Stop
65     ActiveSensing = 0xFE,        ///< System Real Time - Active Sensing
66     SystemReset = 0xFF,          ///< System Real Time - System Reset
67 };
68 
69 /*! Enumeration of Thru filter modes */
70 enum MidiFilterMode {
71     Off = 0,              ///< Thru disabled (nothing passes through).
72     Full = 1,             ///< Fully enabled Thru (every incoming message is sent back).
73     SameChannel = 2,      ///< Only the messages on the Input Channel will be sent back.
74     DifferentChannel = 3, ///< All the messages but the ones on the Input Channel will be sent back.
75 };
76 
77 /*! \brief Enumeration of Control Change command numbers.
78  See the detailed controllers numbers & description here:
79  http://www.somascape.org/midi/tech/spec.html#ctrlnums
80  */
81 enum MidiControlChangeNumber {
82     // High resolution Continuous Controllers MSB (+32 for LSB) ----------------
83     BankSelect = 0,
84     ModulationWheel = 1,
85     BreathController = 2,
86     // CC3 undefined
87     FootController = 4,
88     PortamentoTime = 5,
89     DataEntry = 6,
90     ChannelVolume = 7,
91     Balance = 8,
92     // CC9 undefined
93     Pan = 10,
94     ExpressionController = 11,
95     EffectControl1 = 12,
96     EffectControl2 = 13,
97     // CC14 undefined
98     // CC15 undefined
99     GeneralPurposeController1 = 16,
100     GeneralPurposeController2 = 17,
101     GeneralPurposeController3 = 18,
102     GeneralPurposeController4 = 19,
103 
104     // Switches ----------------------------------------------------------------
105     Sustain = 64,
106     Portamento = 65,
107     Sostenuto = 66,
108     SoftPedal = 67,
109     Legato = 68,
110     Hold = 69,
111 
112     // Low resolution continuous controllers -----------------------------------
113     SoundController1 = 70,  ///< Synth: Sound Variation   FX: Exciter On/Off
114     SoundController2 = 71,  ///< Synth: Harmonic Content  FX: Compressor On/Off
115     SoundController3 = 72,  ///< Synth: Release Time      FX: Distortion On/Off
116     SoundController4 = 73,  ///< Synth: Attack Time       FX: EQ On/Off
117     SoundController5 = 74,  ///< Synth: Brightness        FX: Expander On/Off
118     SoundController6 = 75,  ///< Synth: Decay Time        FX: Reverb On/Off
119     SoundController7 = 76,  ///< Synth: Vibrato Rate      FX: Delay On/Off
120     SoundController8 = 77,  ///< Synth: Vibrato Depth     FX: Pitch Transpose On/Off
121     SoundController9 = 78,  ///< Synth: Vibrato Delay     FX: Flange/Chorus On/Off
122     SoundController10 = 79, ///< Synth: Undefined         FX: Special Effects On/Off
123     GeneralPurposeController5 = 80,
124     GeneralPurposeController6 = 81,
125     GeneralPurposeController7 = 82,
126     GeneralPurposeController8 = 83,
127     PortamentoControl = 84,
128     // CC85 to CC90 undefined
129     Effects1 = 91, ///< Reverb send level
130     Effects2 = 92, ///< Tremolo depth
131     Effects3 = 93, ///< Chorus send level
132     Effects4 = 94, ///< Celeste depth
133     Effects5 = 95, ///< Phaser depth
134 
135     // Channel Mode messages ---------------------------------------------------
136     AllSoundOff = 120,
137     ResetAllControllers = 121,
138     LocalControl = 122,
139     AllNotesOff = 123,
140     OmniModeOff = 124,
141     OmniModeOn = 125,
142     MonoModeOn = 126,
143     PolyModeOn = 127
144 };
145 
146 struct midi_cs_if_ac_header_descriptor {
147     uint8_t bLength;
148     uint8_t bDescriptorType;
149     uint8_t bDescriptorSubType;
150     uint16_t bcdADC;
151     uint16_t wTotalLength;
152     uint8_t bInCollection;
153     uint8_t baInterfaceNr[];
154 } __PACKED;
155 
156 #define MIDI_SIZEOF_AC_HEADER_DESC(n) (8 + n)
157 
158 struct midi_cs_if_ms_header_descriptor {
159     uint8_t bLength;
160     uint8_t bDescriptorType;
161     uint8_t bDescriptorSubType;
162     uint16_t bcdMSC;
163     uint16_t wTotalLength;
164 } __PACKED;
165 
166 #define MIDI_SIZEOF_MS_HEADER_DESC (7)
167 
168 struct midi_cs_if_in_jack_descriptor {
169     uint8_t bLength;
170     uint8_t bDescriptorType;
171     uint8_t bDescriptorSubType;
172     uint8_t bJackType;
173     uint8_t bJackId;
174     uint8_t iJack;
175 } __PACKED;
176 
177 #define MIDI_SIZEOF_IN_JACK_DESC (6)
178 
179 struct midi_cs_if_out_jack_descriptor {
180     uint8_t bLength;
181     uint8_t bDescriptorType;
182     uint8_t bDescriptorSubType;
183     uint8_t bJackType;
184     uint8_t bJackId;
185     uint8_t bNrInputPins;
186     uint8_t baSourceId;
187     uint8_t baSourcePin;
188     uint8_t iJack;
189 } __PACKED;
190 
191 #define MIDI_SIZEOF_OUT_JACK_DESC (9)
192 
193 struct midi_cs_ep_ms_general_descriptor {
194     uint8_t bLength;
195     uint8_t bDescriptorType;
196     uint8_t bDescriptorSubType;
197     uint8_t bNumEmbMIDIJack;
198     uint8_t baAssocJackID[];
199 } __PACKED;
200 
201 #define MIDI_SIZEOF_MS_GENERAL_DESC(n) (4 + n)
202 
203 // clang-format off
204 #define MIDI_CS_HEADER_DESCRIPTOR_INIT(wTotalLength)                                              \
205     0x07,                                             /* bLength */                               \
206     USB_CS_DESCRIPTOR_TYPE_INTERFACE,                 /* bDescriptorType */                       \
207     MIDI_MS_HEADER_DESCRIPTOR_SUBTYPE,                /* bDescriptorSubtype */                    \
208     WBVAL(0x0100),                                    /* bcdMSC */                                \
209     WBVAL(wTotalLength)                               /* wTotalLength */
210 
211 #define MIDI_IN_JACK_DESCRIPTOR_INIT(bJackType, bJackID) \
212     0x06,                                                \
213     0x24,                                                \
214     MIDI_MIDI_IN_JACK_DESCRIPTOR_SUBTYPE,                \
215     bJackType,                                           \
216     bJackID,                                             \
217     0x00
218 
219 #define MIDI_OUT_JACK_DESCRIPTOR_INIT(bJackType, bJackID, baSourceID) \
220     0x09,                                                             \
221     0x24,                                                             \
222     MIDI_MIDI_OUT_JACK_DESCRIPTOR_SUBTYPE,                            \
223     bJackType,                                                        \
224     bJackID,                                                          \
225     0x01,                                                             \
226     baSourceID,                                                       \
227     0x01,                                                             \
228     0x00
229 
230 #define MIDI_JACK_DESCRIPTOR_INIT(bJackFirstID)                                                     \
231     MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, bJackFirstID),                            \
232     MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, (bJackFirstID + 1)),                      \
233     MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, (bJackFirstID + 2), (bJackFirstID + 1)), \
234     MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, (bJackFirstID + 3), (bJackFirstID))
235 
236 #define MIDI_SIZEOF_JACK_DESC (6 + 6 + 9 + 9)
237 
238 // clang-format on
239 
240 #endif /* USB_MIDI_H */
241