1 /*
2 * Copyright (c) 2022, sakumisu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "usbd_core.h"
7 #include "usbd_audio.h"
8
9 struct audio_entity_param {
10 uint32_t wCur;
11 uint32_t wMin;
12 uint32_t wMax;
13 uint32_t wRes;
14 };
15
16 struct usbd_audio_priv {
17 struct audio_entity_info *table;
18 uint8_t num;
19 uint16_t uac_version;
20 } g_usbd_audio;
21
audio_class_endpoint_request_handler(struct usb_setup_packet * setup,uint8_t ** data,uint32_t * len)22 static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
23 {
24 uint8_t control_selector;
25 uint32_t sampling_freq = 0;
26 uint8_t ep;
27
28 control_selector = HI_BYTE(setup->wValue);
29 ep = LO_BYTE(setup->wIndex);
30
31 switch (control_selector) {
32 case AUDIO_EP_CONTROL_SAMPLING_FEQ:
33 switch (setup->bRequest) {
34 case AUDIO_REQUEST_SET_CUR:
35 memcpy((uint8_t *)&sampling_freq, *data, *len);
36 USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
37 usbd_audio_set_sampling_freq(ep, sampling_freq);
38 break;
39 case AUDIO_REQUEST_GET_CUR:
40 case AUDIO_REQUEST_GET_MIN:
41 case AUDIO_REQUEST_GET_MAX:
42 case AUDIO_REQUEST_GET_RES:
43 sampling_freq = usbd_audio_get_sampling_freq(ep);
44 memcpy(*data, &sampling_freq, 3);
45 USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
46 *len = 3;
47 break;
48 }
49
50 break;
51 default:
52 USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
53 return -1;
54 }
55 return 0;
56 }
57
audio_class_interface_request_handler(struct usb_setup_packet * setup,uint8_t ** data,uint32_t * len)58 static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
59 {
60 USB_LOG_DBG("Audio Class request: "
61 "bRequest 0x%02x\r\n",
62 setup->bRequest);
63
64 uint8_t entity_id;
65 uint8_t ep;
66 uint8_t subtype = 0x01;
67 uint8_t control_selector;
68 uint8_t ch;
69 uint8_t mute;
70 uint16_t volume;
71 int volume_db = 0;
72 uint32_t sampling_freq = 0;
73
74 const char *mute_string[2] = { "off", "on" };
75
76 entity_id = HI_BYTE(setup->wIndex);
77 control_selector = HI_BYTE(setup->wValue);
78 ch = LO_BYTE(setup->wValue);
79
80 ARG_UNUSED(mute_string);
81
82 for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
83 if (g_usbd_audio.table[i].bEntityId == entity_id) {
84 subtype = g_usbd_audio.table[i].bDescriptorSubtype;
85 ep = g_usbd_audio.table[i].ep;
86 break;
87 }
88 }
89
90 if (subtype == 0x01) {
91 USB_LOG_ERR("Do not find subtype for 0x%02x\r\n", entity_id);
92 return -1;
93 }
94
95 USB_LOG_DBG("Audio entity_id:%02x, subtype:%02x, cs:%02x\r\n", entity_id, subtype, control_selector);
96
97 switch (subtype) {
98 case AUDIO_CONTROL_FEATURE_UNIT:
99 switch (control_selector) {
100 case AUDIO_FU_CONTROL_MUTE:
101 if (g_usbd_audio.uac_version < 0x0200) {
102 switch (setup->bRequest) {
103 case AUDIO_REQUEST_SET_CUR:
104 mute = (*data)[0];
105 usbd_audio_set_mute(ep, ch, mute);
106 break;
107 case AUDIO_REQUEST_GET_CUR:
108 (*data)[0] = usbd_audio_get_mute(ep, ch);
109 *len = 1;
110 break;
111 default:
112 USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
113 return -1;
114 }
115 } else {
116 switch (setup->bRequest) {
117 case AUDIO_REQUEST_CUR:
118 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
119 (*data)[0] = usbd_audio_get_mute(ep, ch);
120 *len = 1;
121 } else {
122 mute = (*data)[0];
123 usbd_audio_set_mute(ep, ch, mute);
124 }
125 break;
126 default:
127 //USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
128 return -1;
129 }
130 }
131 break;
132 case AUDIO_FU_CONTROL_VOLUME:
133 if (g_usbd_audio.uac_version < 0x0200) {
134 switch (setup->bRequest) {
135 case AUDIO_REQUEST_SET_CUR:
136 memcpy(&volume, *data, *len);
137 if (volume < 0x8000) {
138 volume_db = volume / 256;
139 } else if (volume > 0x8000) {
140 volume_db = (0xffff - volume + 1) / -256;
141 }
142 volume_db += 128; /* 0 ~ 255 */
143 USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
144 usbd_audio_set_volume(ep, ch, volume_db);
145 break;
146 case AUDIO_REQUEST_GET_CUR:
147 volume_db = usbd_audio_get_volume(ep, ch);
148 volume_db -= 128;
149 if (volume_db >= 0) {
150 volume = volume_db * 256;
151 } else {
152 volume = volume_db * 256 + 0xffff + 1;
153 }
154 memcpy(*data, &volume, 2);
155 *len = 2;
156 break;
157 case AUDIO_REQUEST_GET_MIN:
158 (*data)[0] = 0x00; /* -2560/256 dB */
159 (*data)[1] = 0xdb;
160 *len = 2;
161 break;
162 case AUDIO_REQUEST_GET_MAX:
163 (*data)[0] = 0x00; /* 0 dB */
164 (*data)[1] = 0x00;
165 *len = 2;
166 break;
167 case AUDIO_REQUEST_GET_RES:
168 (*data)[0] = 0x00; /* -256/256 dB */
169 (*data)[1] = 0x01;
170 *len = 2;
171 break;
172 default:
173 USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
174 return -1;
175 }
176 } else {
177 switch (setup->bRequest) {
178 case AUDIO_REQUEST_CUR:
179 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
180 volume_db = usbd_audio_get_volume(ep, ch);
181 volume = volume_db;
182 memcpy(*data, &volume, 2);
183 *len = 2;
184 } else {
185 memcpy(&volume, *data, *len);
186 volume_db = volume;
187 USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
188 usbd_audio_set_volume(ep, ch, volume_db);
189 }
190 break;
191 case AUDIO_REQUEST_RANGE:
192 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
193 *((uint16_t *)(*data + 0)) = 1;
194 *((uint16_t *)(*data + 2)) = 0;
195 *((uint16_t *)(*data + 4)) = 100;
196 *((uint16_t *)(*data + 6)) = 1;
197 *len = 8;
198 } else {
199 }
200 break;
201 default:
202 //USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
203 return -1;
204 }
205 }
206 break;
207
208 default:
209 USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
210 return -1;
211 }
212 break;
213 case AUDIO_CONTROL_CLOCK_SOURCE:
214 switch (control_selector) {
215 case AUDIO_CS_CONTROL_SAM_FREQ:
216 switch (setup->bRequest) {
217 case AUDIO_REQUEST_CUR:
218 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
219 sampling_freq = usbd_audio_get_sampling_freq(ep);
220 memcpy(*data, &sampling_freq, 4);
221 USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
222 *len = 4;
223 } else {
224 memcpy(&sampling_freq, *data, setup->wLength);
225 USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
226 usbd_audio_set_sampling_freq(ep, sampling_freq);
227 }
228 break;
229 case AUDIO_REQUEST_RANGE:
230 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
231 uint8_t *sampling_freq_table = NULL;
232 uint16_t num;
233
234 usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
235 num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
236 memcpy(*data, sampling_freq_table, (12 * num + 2));
237 *len = (12 * num + 2);
238 } else {
239 }
240 break;
241 default:
242 //USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
243 return -1;
244 }
245 break;
246 case AUDIO_CS_CONTROL_CLOCK_VALID:
247 if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
248 (*data)[0] = 1;
249 *len = 1;
250 } else {
251 return -1;
252 }
253 break;
254
255 default:
256 //USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
257 return -1;
258 }
259 break;
260
261 default:
262 break;
263 }
264 return 0;
265 }
266
audio_notify_handler(uint8_t event,void * arg)267 static void audio_notify_handler(uint8_t event, void *arg)
268 {
269 switch (event) {
270 case USBD_EVENT_RESET:
271
272 break;
273
274 case USBD_EVENT_SET_INTERFACE: {
275 struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
276 if (intf->bAlternateSetting) {
277 usbd_audio_open(intf->bInterfaceNumber);
278 } else {
279 usbd_audio_close(intf->bInterfaceNumber);
280 }
281 }
282
283 break;
284
285 default:
286 break;
287 }
288 }
289
usbd_audio_init_intf(struct usbd_interface * intf,uint16_t uac_version,struct audio_entity_info * table,uint8_t num)290 struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
291 uint16_t uac_version,
292 struct audio_entity_info *table,
293 uint8_t num)
294 {
295 if (uac_version < 0x0200) {
296 intf->class_interface_handler = audio_class_interface_request_handler;
297 intf->class_endpoint_handler = audio_class_endpoint_request_handler;
298 intf->vendor_handler = NULL;
299 intf->notify_handler = audio_notify_handler;
300 } else {
301 intf->class_interface_handler = audio_class_interface_request_handler;
302 intf->class_endpoint_handler = NULL;
303 intf->vendor_handler = NULL;
304 intf->notify_handler = audio_notify_handler;
305 }
306
307 g_usbd_audio.uac_version = uac_version;
308 g_usbd_audio.table = table;
309 g_usbd_audio.num = num;
310
311 return intf;
312 }
313
usbd_audio_set_volume(uint8_t ep,uint8_t ch,int volume)314 __WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
315 {
316 }
317
usbd_audio_get_volume(uint8_t ep,uint8_t ch)318 __WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
319 {
320 return 0;
321 }
322
usbd_audio_set_mute(uint8_t ep,uint8_t ch,bool mute)323 __WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
324 {
325 }
326
usbd_audio_get_mute(uint8_t ep,uint8_t ch)327 __WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
328 {
329 return 0;
330 }
331
usbd_audio_set_sampling_freq(uint8_t ep,uint32_t sampling_freq)332 __WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
333 {
334 }
335
usbd_audio_get_sampling_freq(uint8_t ep)336 __WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
337 {
338 return 0;
339 }
340
usbd_audio_get_sampling_freq_table(uint8_t ep,uint8_t ** sampling_freq_table)341 __WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
342 {
343 }
344