1 /*
2 * Copyright (c) 2024, sakumisu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "usbd_core.h"
7 #include "usb_midi.h"
8
9 #define MIDI_OUT_EP 0x02
10 #define MIDI_IN_EP 0x81
11
12 #define USBD_VID 0x0d28
13 #define USBD_PID 0x0404
14 #define USBD_MAX_POWER 100
15 #define USBD_LANGID_STRING 1033
16
17 #define USB_CONFIG_SIZE (9 + 9 + 9 + 9 + 7 + MIDI_SIZEOF_JACK_DESC + 9 + 5 + 9 + 5)
18
19 #ifdef CONFIG_USB_HS
20 #define MIDI_EP_MPS 512
21 #else
22 #define MIDI_EP_MPS 64
23 #endif
24
25 #ifdef CONFIG_USBDEV_ADVANCE_DESC
26 static const uint8_t device_descriptor[] = {
27 USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01)
28 };
29
30 static const uint8_t config_descriptor[] = {
31 USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
32 // Standard AC Interface Descriptor
33 0x09,
34 0x04,
35 0x00,
36 0x00,
37 0x00,
38 0x01,
39 0x01,
40 0x00,
41 0x00,
42 // Class-specific AC Interface Descriptor
43 0x09,
44 0x24,
45 0x01,
46 0x00,
47 0x01,
48 0x09,
49 0x00,
50 0x01,
51 0x01,
52 // MIDIStreaming Interface Descriptors
53 0x09,
54 0x04,
55 0x01,
56 0x00,
57 0x02,
58 0x01,
59 0x03,
60 0x00,
61 0x00,
62 // Class-Specific MS Interface Header Descriptor
63 0x07,
64 0x24,
65 0x01,
66 0x00,
67 0x01,
68 WBVAL(65),
69
70 // MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x01),
71 // MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x02),
72 // MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x03, 0x02),
73 // MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
74 MIDI_JACK_DESCRIPTOR_INIT(0x01),
75 // OUT endpoint descriptor
76 0x09, 0x05, MIDI_OUT_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
77 0x05, 0x25, 0x01, 0x01, 0x01,
78
79 // IN endpoint descriptor
80 0x09, 0x05, MIDI_IN_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
81 0x05, 0x25, 0x01, 0x01, 0x03
82 };
83
84 static const uint8_t device_quality_descriptor[] = {
85 ///////////////////////////////////////
86 /// device qualifier descriptor
87 ///////////////////////////////////////
88 0x0a,
89 USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
90 0x00,
91 0x02,
92 0x00,
93 0x00,
94 0x00,
95 0x40,
96 0x00,
97 0x00,
98 };
99
100 static const char *string_descriptors[] = {
101 (const char[]){ 0x09, 0x04 }, /* Langid */
102 "CherryUSB", /* Manufacturer */
103 "CherryUSB MIDI DEMO", /* Product */
104 "2022123456", /* Serial Number */
105 };
106
device_descriptor_callback(uint8_t speed)107 static const uint8_t *device_descriptor_callback(uint8_t speed)
108 {
109 return device_descriptor;
110 }
111
config_descriptor_callback(uint8_t speed)112 static const uint8_t *config_descriptor_callback(uint8_t speed)
113 {
114 return config_descriptor;
115 }
116
device_quality_descriptor_callback(uint8_t speed)117 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
118 {
119 return device_quality_descriptor;
120 }
121
string_descriptor_callback(uint8_t speed,uint8_t index)122 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
123 {
124 if (index > 3) {
125 return NULL;
126 }
127 return string_descriptors[index];
128 }
129
130 const struct usb_descriptor midi_descriptor = {
131 .device_descriptor_callback = device_descriptor_callback,
132 .config_descriptor_callback = config_descriptor_callback,
133 .device_quality_descriptor_callback = device_quality_descriptor_callback,
134 .string_descriptor_callback = string_descriptor_callback
135 };
136 #else
137 const uint8_t midi_descriptor[] = {
138 USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
139 USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
140 // Standard AC Interface Descriptor
141 0x09,
142 0x04,
143 0x00,
144 0x00,
145 0x00,
146 0x01,
147 0x01,
148 0x00,
149 0x00,
150 // Class-specific AC Interface Descriptor
151 0x09,
152 0x24,
153 0x01,
154 0x00,
155 0x01,
156 0x09,
157 0x00,
158 0x01,
159 0x01,
160 // MIDIStreaming Interface Descriptors
161 0x09,
162 0x04,
163 0x01,
164 0x00,
165 0x02,
166 0x01,
167 0x03,
168 0x00,
169 0x00,
170 // Class-Specific MS Interface Header Descriptor
171 0x07,
172 0x24,
173 0x01,
174 0x00,
175 0x01,
176 WBVAL(65),
177
178 // MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x01),
179 // MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x02),
180 // MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x03, 0x02),
181 // MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
182 MIDI_JACK_DESCRIPTOR_INIT(0x01),
183 // OUT endpoint descriptor
184 0x09, 0x05, MIDI_OUT_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
185 0x05, 0x25, 0x01, 0x01, 0x01,
186
187 // IN endpoint descriptor
188 0x09, 0x05, MIDI_IN_EP, 0x02, WBVAL(MIDI_EP_MPS), 0x00, 0x00, 0x00,
189 0x05, 0x25, 0x01, 0x01, 0x03,
190
191 ///////////////////////////////////////
192 /// string0 descriptor
193 ///////////////////////////////////////
194 USB_LANGID_INIT(USBD_LANGID_STRING),
195 ///////////////////////////////////////
196 /// string1 descriptor
197 ///////////////////////////////////////
198 0x14, /* bLength */
199 USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
200 'C', 0x00, /* wcChar0 */
201 'h', 0x00, /* wcChar1 */
202 'e', 0x00, /* wcChar2 */
203 'r', 0x00, /* wcChar3 */
204 'r', 0x00, /* wcChar4 */
205 'y', 0x00, /* wcChar5 */
206 'U', 0x00, /* wcChar6 */
207 'S', 0x00, /* wcChar7 */
208 'B', 0x00, /* wcChar8 */
209 ///////////////////////////////////////
210 /// string2 descriptor
211 ///////////////////////////////////////
212 0x28, /* bLength */
213 USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
214 'C', 0x00, /* wcChar0 */
215 'h', 0x00, /* wcChar1 */
216 'e', 0x00, /* wcChar2 */
217 'r', 0x00, /* wcChar3 */
218 'r', 0x00, /* wcChar4 */
219 'y', 0x00, /* wcChar5 */
220 'U', 0x00, /* wcChar6 */
221 'S', 0x00, /* wcChar7 */
222 'B', 0x00, /* wcChar8 */
223 ' ', 0x00, /* wcChar9 */
224 'M', 0x00, /* wcChar10 */
225 'I', 0x00, /* wcChar11 */
226 'D', 0x00, /* wcChar12 */
227 'I', 0x00, /* wcChar13 */
228 ' ', 0x00, /* wcChar14 */
229 'D', 0x00, /* wcChar15 */
230 'E', 0x00, /* wcChar16 */
231 'M', 0x00, /* wcChar17 */
232 'O', 0x00, /* wcChar18 */
233 ///////////////////////////////////////
234 /// string3 descriptor
235 ///////////////////////////////////////
236 0x16, /* bLength */
237 USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
238 '2', 0x00, /* wcChar0 */
239 '0', 0x00, /* wcChar1 */
240 '2', 0x00, /* wcChar2 */
241 '1', 0x00, /* wcChar3 */
242 '0', 0x00, /* wcChar4 */
243 '3', 0x00, /* wcChar5 */
244 '1', 0x00, /* wcChar6 */
245 '0', 0x00, /* wcChar7 */
246 '0', 0x00, /* wcChar8 */
247 '0', 0x00, /* wcChar9 */
248 #ifdef CONFIG_USB_HS
249 ///////////////////////////////////////
250 /// device qualifier descriptor
251 ///////////////////////////////////////
252 0x0a,
253 USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
254 0x00,
255 0x02,
256 0x00,
257 0x00,
258 0x00,
259 0x40,
260 0x00,
261 0x00,
262 #endif
263 0x00
264 };
265 #endif
266
267 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[MIDI_EP_MPS];
268 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[MIDI_EP_MPS];
269
usbd_event_handler(uint8_t busid,uint8_t event)270 static void usbd_event_handler(uint8_t busid, uint8_t event)
271 {
272 switch (event) {
273 case USBD_EVENT_RESET:
274 break;
275 case USBD_EVENT_CONNECTED:
276 break;
277 case USBD_EVENT_DISCONNECTED:
278 break;
279 case USBD_EVENT_RESUME:
280 break;
281 case USBD_EVENT_SUSPEND:
282 break;
283 case USBD_EVENT_CONFIGURED:
284 usbd_ep_start_read(busid, MIDI_OUT_EP, read_buffer, MIDI_EP_MPS);
285 break;
286 case USBD_EVENT_SET_REMOTE_WAKEUP:
287 break;
288 case USBD_EVENT_CLR_REMOTE_WAKEUP:
289 break;
290
291 default:
292 break;
293 }
294 }
295
usbd_midi_bulk_out(uint8_t busid,uint8_t ep,uint32_t nbytes)296 void usbd_midi_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
297 {
298 usbd_ep_start_read(busid, MIDI_OUT_EP, read_buffer, MIDI_EP_MPS);
299 }
300
usbd_midi_bulk_in(uint8_t busid,uint8_t ep,uint32_t nbytes)301 void usbd_midi_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
302 {
303 }
304
305 struct usbd_interface intf0;
306 struct usbd_interface intf1;
307
308 struct usbd_endpoint midi_out_ep = {
309 .ep_addr = MIDI_OUT_EP,
310 .ep_cb = usbd_midi_bulk_out
311 };
312
313 struct usbd_endpoint midi_in_ep = {
314 .ep_addr = MIDI_IN_EP,
315 .ep_cb = usbd_midi_bulk_in
316 };
317
midi_init(uint8_t busid,uintptr_t reg_base)318 void midi_init(uint8_t busid, uintptr_t reg_base)
319 {
320 #ifdef CONFIG_USBDEV_ADVANCE_DESC
321 usbd_desc_register(busid, &midi_descriptor);
322 #else
323 usbd_desc_register(busid, midi_descriptor);
324 #endif
325 usbd_add_interface(busid, &intf0);
326 usbd_add_interface(busid, &intf1);
327 usbd_add_endpoint(busid, &midi_out_ep);
328 usbd_add_endpoint(busid, &midi_in_ep);
329
330 usbd_initialize(busid, reg_base, usbd_event_handler);
331 }