1 /*
2 * Copyright (c) 2023-2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/atomic.h>
9 #include <zephyr/sys/byteorder.h>
10
11 #include <zephyr/usb/usbd.h>
12 #include <zephyr/usb/usb_ch9.h>
13 #include <zephyr/usb/class/usbd_uac2.h>
14 #include <zephyr/drivers/usb/udc.h>
15
16 #include "usbd_uac2_macros.h"
17
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(usbd_uac2, CONFIG_USBD_UAC2_LOG_LEVEL);
20
21 #define DT_DRV_COMPAT zephyr_uac2
22
23 #define COUNT_UAC2_AS_ENDPOINTS(node) \
24 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
25 + AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) + \
26 AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node)))
27 #define COUNT_UAC2_ENDPOINTS(i) \
28 + DT_PROP(DT_DRV_INST(i), interrupt_endpoint) \
29 DT_INST_FOREACH_CHILD(i, COUNT_UAC2_AS_ENDPOINTS)
30 #define UAC2_NUM_ENDPOINTS DT_INST_FOREACH_STATUS_OKAY(COUNT_UAC2_ENDPOINTS)
31
32 /* Net buf is used mostly with external data. The main reason behind external
33 * data is avoiding unnecessary isochronous data copy operations.
34 *
35 * Allow up to 6 bytes per item to facilitate optional interrupt endpoint (which
36 * requires 6 bytes) and feedback endpoint (4 bytes on High-Speed, 3 bytes on
37 * Full-Speed). Because the total number of endpoints is really small (typically
38 * there will be just 2 isochronous endpoints; the upper bound originating from
39 * the USB specification itself is 30 non-control endpoints). Therefore, the
40 * "wasted memory" here is likely to be smaller than the memory overhead for
41 * more complex "only as much as needed" schemes (e.g. heap).
42 */
43 UDC_BUF_POOL_DEFINE(uac2_pool, UAC2_NUM_ENDPOINTS, 6,
44 sizeof(struct udc_buf_info), NULL);
45
46 /* 5.2.2 Control Request Layout */
47 #define SET_CLASS_REQUEST_TYPE 0x21
48 #define GET_CLASS_REQUEST_TYPE 0xA1
49
50 /* A.14 Audio Class-Specific Request Codes */
51 #define CUR 0x01
52 #define RANGE 0x02
53 #define MEM 0x03
54
55 /* A.17.1 Clock Source Control Selectors */
56 #define CS_SAM_FREQ_CONTROL 0x01
57 #define CS_CLOCK_VALID_CONTROL 0x02
58
59 #define CONTROL_ATTRIBUTE(setup) (setup->bRequest)
60 #define CONTROL_ENTITY_ID(setup) ((setup->wIndex & 0xFF00) >> 8)
61 #define CONTROL_SELECTOR(setup) ((setup->wValue & 0xFF00) >> 8)
62 #define CONTROL_CHANNEL_NUMBER(setup) (setup->wValue & 0x00FF)
63
64 typedef enum {
65 ENTITY_TYPE_INVALID,
66 ENTITY_TYPE_CLOCK_SOURCE,
67 ENTITY_TYPE_INPUT_TERMINAL,
68 ENTITY_TYPE_OUTPUT_TERMINAL,
69 } entity_type_t;
70
71 static size_t clock_frequencies(struct usbd_class_data *const c_data,
72 const uint8_t id, const uint32_t **frequencies);
73
74 /* UAC2 device runtime data */
75 struct uac2_ctx {
76 const struct uac2_ops *ops;
77 void *user_data;
78 /* Bit set indicates the AudioStreaming interface has non-zero bandwidth
79 * alternate setting active.
80 */
81 atomic_t as_active;
82 atomic_t as_queued;
83 uint32_t fb_queued;
84 };
85
86 /* UAC2 device constant data */
87 struct uac2_cfg {
88 struct usbd_class_data *const c_data;
89 const struct usb_desc_header **descriptors;
90 /* Entity 1 type is at entity_types[0] */
91 const entity_type_t *entity_types;
92 /* Array of indexes to data endpoint descriptor in descriptors set.
93 * First AudioStreaming interface is at ep_indexes[0]. Index is 0 if
94 * the interface is external interface (Type IV), i.e. no endpoint.
95 */
96 const uint16_t *ep_indexes;
97 /* Same as ep_indexes, but for explicit feedback endpoints. */
98 const uint16_t *fb_indexes;
99 /* First AudioStreaming interface Terminal ID is at as_terminals[0]. */
100 const uint8_t *as_terminals;
101 /* Number of interfaces (ep_indexes, fb_indexes and as_terminals size) */
102 uint8_t num_ifaces;
103 /* Number of entities (entity_type array size) */
104 uint8_t num_entities;
105 };
106
id_type(struct usbd_class_data * const c_data,uint8_t id)107 static entity_type_t id_type(struct usbd_class_data *const c_data, uint8_t id)
108 {
109 const struct device *dev = usbd_class_get_private(c_data);
110 const struct uac2_cfg *cfg = dev->config;
111
112 if ((id - 1) < cfg->num_entities) {
113 return cfg->entity_types[id - 1];
114 }
115
116 return ENTITY_TYPE_INVALID;
117 }
118
119 static const struct usb_ep_descriptor *
get_as_data_ep(struct usbd_class_data * const c_data,int as_idx)120 get_as_data_ep(struct usbd_class_data *const c_data, int as_idx)
121 {
122 const struct device *dev = usbd_class_get_private(c_data);
123 const struct uac2_cfg *cfg = dev->config;
124 const struct usb_desc_header *desc = NULL;
125
126 if ((as_idx >= 0) && (as_idx < cfg->num_ifaces) &&
127 cfg->ep_indexes[as_idx]) {
128 desc = cfg->descriptors[cfg->ep_indexes[as_idx]];
129 }
130
131 return (const struct usb_ep_descriptor *)desc;
132 }
133
134 static const struct usb_ep_descriptor *
get_as_feedback_ep(struct usbd_class_data * const c_data,int as_idx)135 get_as_feedback_ep(struct usbd_class_data *const c_data, int as_idx)
136 {
137 const struct device *dev = usbd_class_get_private(c_data);
138 const struct uac2_cfg *cfg = dev->config;
139 const struct usb_desc_header *desc = NULL;
140
141 if ((as_idx < cfg->num_ifaces) && cfg->fb_indexes[as_idx]) {
142 desc = cfg->descriptors[cfg->fb_indexes[as_idx]];
143 }
144
145 return (const struct usb_ep_descriptor *)desc;
146 }
147
ep_to_as_interface(const struct device * dev,uint8_t ep,bool * fb)148 static int ep_to_as_interface(const struct device *dev, uint8_t ep, bool *fb)
149 {
150 const struct uac2_cfg *cfg = dev->config;
151 const struct usb_ep_descriptor *desc;
152
153 for (int i = 0; i < cfg->num_ifaces; i++) {
154 if (!cfg->ep_indexes[i]) {
155 /* If there is no data endpoint there cannot be feedback
156 * endpoint. Simply skip external interfaces.
157 */
158 continue;
159 }
160
161 desc = get_as_data_ep(cfg->c_data, i);
162 if (desc && (ep == desc->bEndpointAddress)) {
163 *fb = false;
164 return i;
165 }
166
167 desc = get_as_feedback_ep(cfg->c_data, i);
168 if (desc && (ep == desc->bEndpointAddress)) {
169 *fb = true;
170 return i;
171 }
172 }
173
174 *fb = false;
175 return -ENOENT;
176 }
177
terminal_to_as_interface(const struct device * dev,uint8_t terminal)178 static int terminal_to_as_interface(const struct device *dev, uint8_t terminal)
179 {
180 const struct uac2_cfg *cfg = dev->config;
181
182 for (int as_idx = 0; as_idx < cfg->num_ifaces; as_idx++) {
183 if (terminal == cfg->as_terminals[as_idx]) {
184 return as_idx;
185 }
186 }
187
188 return -ENOENT;
189 }
190
usbd_uac2_set_ops(const struct device * dev,const struct uac2_ops * ops,void * user_data)191 void usbd_uac2_set_ops(const struct device *dev,
192 const struct uac2_ops *ops, void *user_data)
193 {
194 struct uac2_ctx *ctx = dev->data;
195
196 __ASSERT(ops->sof_cb, "SOF callback is mandatory");
197
198 ctx->ops = ops;
199 ctx->user_data = user_data;
200 }
201
202 static struct net_buf *
uac2_buf_alloc(const uint8_t ep,void * data,uint16_t size)203 uac2_buf_alloc(const uint8_t ep, void *data, uint16_t size)
204 {
205 struct net_buf *buf = NULL;
206 struct udc_buf_info *bi;
207
208 __ASSERT(IS_UDC_ALIGNED(data), "Application provided unaligned buffer");
209
210 buf = net_buf_alloc_with_data(&uac2_pool, data, size, K_NO_WAIT);
211 if (!buf) {
212 return NULL;
213 }
214
215 bi = udc_get_buf_info(buf);
216 memset(bi, 0, sizeof(struct udc_buf_info));
217 bi->ep = ep;
218
219 if (USB_EP_DIR_IS_OUT(ep)) {
220 /* Buffer is empty, USB stack will write data from host */
221 buf->len = 0;
222 }
223
224 return buf;
225 }
226
usbd_uac2_send(const struct device * dev,uint8_t terminal,void * data,uint16_t size)227 int usbd_uac2_send(const struct device *dev, uint8_t terminal,
228 void *data, uint16_t size)
229 {
230 const struct uac2_cfg *cfg = dev->config;
231 struct uac2_ctx *ctx = dev->data;
232 struct net_buf *buf;
233 const struct usb_ep_descriptor *desc;
234 uint8_t ep = 0;
235 int as_idx = terminal_to_as_interface(dev, terminal);
236 int ret;
237
238 desc = get_as_data_ep(cfg->c_data, as_idx);
239 if (desc) {
240 ep = desc->bEndpointAddress;
241 }
242
243 if (!ep) {
244 LOG_ERR("No endpoint for terminal %d", terminal);
245 return -ENOENT;
246 }
247
248 if (!atomic_test_bit(&ctx->as_active, as_idx)) {
249 /* Host is not interested in the data */
250 ctx->ops->buf_release_cb(dev, terminal, data, ctx->user_data);
251 return 0;
252 }
253
254 if (atomic_test_and_set_bit(&ctx->as_queued, as_idx)) {
255 LOG_ERR("Previous send not finished yet on 0x%02x", ep);
256 return -EAGAIN;
257 }
258
259 buf = uac2_buf_alloc(ep, data, size);
260 if (!buf) {
261 /* This shouldn't really happen because netbuf should be large
262 * enough, but if it does all we loose is just single packet.
263 */
264 LOG_ERR("No netbuf for send");
265 atomic_clear_bit(&ctx->as_queued, as_idx);
266 ctx->ops->buf_release_cb(dev, terminal, data, ctx->user_data);
267 return -ENOMEM;
268 }
269
270 ret = usbd_ep_enqueue(cfg->c_data, buf);
271 if (ret) {
272 LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
273 net_buf_unref(buf);
274 atomic_clear_bit(&ctx->as_queued, as_idx);
275 ctx->ops->buf_release_cb(dev, terminal, data, ctx->user_data);
276 }
277
278 return ret;
279 }
280
schedule_iso_out_read(struct usbd_class_data * const c_data,uint8_t ep,uint16_t mps,uint8_t terminal)281 static void schedule_iso_out_read(struct usbd_class_data *const c_data,
282 uint8_t ep, uint16_t mps, uint8_t terminal)
283 {
284 const struct device *dev = usbd_class_get_private(c_data);
285 const struct uac2_cfg *cfg = dev->config;
286 struct uac2_ctx *ctx = dev->data;
287 struct net_buf *buf;
288 void *data_buf;
289 int as_idx = terminal_to_as_interface(dev, terminal);
290 int ret;
291
292 /* All calls to this function are internal to class, if terminal is not
293 * associated with interface there is a bug in class implementation.
294 */
295 __ASSERT_NO_MSG((as_idx >= 0) && (as_idx < cfg->num_ifaces));
296 /* Silence warning if asserts are not enabled */
297 ARG_UNUSED(cfg);
298
299 if (!((as_idx >= 0) && atomic_test_bit(&ctx->as_active, as_idx))) {
300 /* Host won't send data */
301 return;
302 }
303
304 if (atomic_test_and_set_bit(&ctx->as_queued, as_idx)) {
305 /* Transfer already queued - do not requeue */
306 return;
307 }
308
309 /* Prepare transfer to read audio OUT data from host */
310 data_buf = ctx->ops->get_recv_buf(dev, terminal, mps, ctx->user_data);
311 if (!data_buf) {
312 LOG_ERR("No data buffer for terminal %d", terminal);
313 atomic_clear_bit(&ctx->as_queued, as_idx);
314 return;
315 }
316
317 buf = uac2_buf_alloc(ep, data_buf, mps);
318 if (!buf) {
319 LOG_ERR("No netbuf for read");
320 /* Netbuf pool should be large enough, but if for some reason
321 * we are out of netbuf, there's nothing better to do than to
322 * pass the buffer back to application.
323 */
324 ctx->ops->data_recv_cb(dev, terminal,
325 data_buf, 0, ctx->user_data);
326 atomic_clear_bit(&ctx->as_queued, as_idx);
327 return;
328 }
329
330 ret = usbd_ep_enqueue(c_data, buf);
331 if (ret) {
332 LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
333 net_buf_unref(buf);
334 atomic_clear_bit(&ctx->as_queued, as_idx);
335 }
336 }
337
write_explicit_feedback(struct usbd_class_data * const c_data,uint8_t ep,uint8_t terminal)338 static void write_explicit_feedback(struct usbd_class_data *const c_data,
339 uint8_t ep, uint8_t terminal)
340 {
341 const struct device *dev = usbd_class_get_private(c_data);
342 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
343 struct uac2_ctx *ctx = dev->data;
344 struct net_buf *buf;
345 struct udc_buf_info *bi;
346 uint32_t fb_value;
347 int as_idx = terminal_to_as_interface(dev, terminal);
348 int ret;
349
350 __ASSERT_NO_MSG(as_idx >= 0);
351
352 buf = net_buf_alloc(&uac2_pool, K_NO_WAIT);
353 if (!buf) {
354 LOG_ERR("No buf for feedback");
355 return;
356 }
357
358 bi = udc_get_buf_info(buf);
359 memset(bi, 0, sizeof(struct udc_buf_info));
360 bi->ep = ep;
361
362 fb_value = ctx->ops->feedback_cb(dev, terminal, ctx->user_data);
363
364 /* REVISE: How to determine operating speed? Should we have separate
365 * class instances for high-speed and full-speed (because high-speed
366 * allows more sampling rates and/or bit depths)?
367 */
368 if (usbd_bus_speed(uds_ctx) == USBD_SPEED_FS) {
369 net_buf_add_le24(buf, fb_value);
370 } else {
371 net_buf_add_le32(buf, fb_value);
372 }
373
374 ret = usbd_ep_enqueue(c_data, buf);
375 if (ret) {
376 LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
377 net_buf_unref(buf);
378 } else {
379 ctx->fb_queued |= BIT(as_idx);
380 }
381 }
382
uac2_update(struct usbd_class_data * const c_data,uint8_t iface,uint8_t alternate)383 void uac2_update(struct usbd_class_data *const c_data,
384 uint8_t iface, uint8_t alternate)
385 {
386 const struct device *dev = usbd_class_get_private(c_data);
387 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
388 const struct uac2_cfg *cfg = dev->config;
389 struct uac2_ctx *ctx = dev->data;
390 const struct usb_association_descriptor *iad;
391 const struct usb_ep_descriptor *data_ep, *fb_ep;
392 uint8_t as_idx;
393 bool microframes;
394
395 LOG_DBG("iface %d alt %d", iface, alternate);
396
397 iad = (const struct usb_association_descriptor *)cfg->descriptors[0];
398
399 /* AudioControl interface (bFirstInterface) doesn't have alternate
400 * configurations, therefore the iface must be AudioStreaming.
401 */
402 __ASSERT_NO_MSG((iface > iad->bFirstInterface) &&
403 (iface < iad->bFirstInterface + iad->bInterfaceCount));
404 as_idx = iface - iad->bFirstInterface - 1;
405
406 /* Audio class is forbidden on Low-Speed, therefore the only possibility
407 * for not using microframes is when device operates at Full-Speed.
408 */
409 if (usbd_bus_speed(uds_ctx) == USBD_SPEED_FS) {
410 microframes = false;
411 } else {
412 microframes = true;
413 }
414
415 /* Notify application about terminal state change */
416 ctx->ops->terminal_update_cb(dev, cfg->as_terminals[as_idx], alternate,
417 microframes, ctx->user_data);
418
419 if (alternate == 0) {
420 /* Mark interface as inactive, any pending endpoint transfers
421 * were already cancelled by the USB stack.
422 */
423 atomic_clear_bit(&ctx->as_active, as_idx);
424 return;
425 }
426
427 atomic_set_bit(&ctx->as_active, as_idx);
428
429 data_ep = get_as_data_ep(c_data, as_idx);
430 /* External interfaces (i.e. NULL data_ep) do not have alternate
431 * configuration and therefore data_ep must be valid here.
432 */
433 __ASSERT_NO_MSG(data_ep);
434
435 if (USB_EP_DIR_IS_OUT(data_ep->bEndpointAddress)) {
436 schedule_iso_out_read(c_data, data_ep->bEndpointAddress,
437 sys_le16_to_cpu(data_ep->wMaxPacketSize),
438 cfg->as_terminals[as_idx]);
439
440 fb_ep = get_as_feedback_ep(c_data, as_idx);
441 if (fb_ep) {
442 write_explicit_feedback(c_data, fb_ep->bEndpointAddress,
443 cfg->as_terminals[as_idx]);
444 }
445 }
446 }
447
448 /* Table 5-6: 4-byte Control CUR Parameter Block */
layout3_cur_response(struct net_buf * const buf,uint16_t length,const uint32_t value)449 static void layout3_cur_response(struct net_buf *const buf, uint16_t length,
450 const uint32_t value)
451 {
452 uint8_t tmp[4];
453
454 /* dCUR */
455 sys_put_le32(value, tmp);
456 net_buf_add_mem(buf, tmp, MIN(length, 4));
457 }
458
459 /* Table 5-7: 4-byte Control RANGE Parameter Block */
layout3_range_response(struct net_buf * const buf,uint16_t length,const uint32_t * min,const uint32_t * max,const uint32_t * res,int n)460 static void layout3_range_response(struct net_buf *const buf, uint16_t length,
461 const uint32_t *min, const uint32_t *max,
462 const uint32_t *res, int n)
463 {
464 uint16_t to_add;
465 uint8_t tmp[4];
466 int i;
467 int item;
468
469 /* wNumSubRanges */
470 sys_put_le16(n, tmp);
471 to_add = MIN(length, 2);
472 net_buf_add_mem(buf, tmp, to_add);
473 length -= to_add;
474
475 /* Keep adding dMIN, dMAX, dRES as long as we have entries to add and
476 * we didn't reach wLength response limit.
477 */
478 i = item = 0;
479 while ((length > 0) && (i < n)) {
480 to_add = MIN(length, 4);
481 if (item == 0) {
482 sys_put_le32(min[i], tmp);
483 } else if (item == 1) {
484 sys_put_le32(max[i], tmp);
485 } else if (item == 2) {
486 if (res) {
487 sys_put_le32(res[i], tmp);
488 } else {
489 memset(tmp, 0, 4);
490 }
491 }
492 net_buf_add_mem(buf, tmp, to_add);
493 length -= to_add;
494
495 if (++item == 3) {
496 item = 0;
497 i++;
498 }
499 }
500 }
501
get_clock_source_request(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,struct net_buf * const buf)502 static int get_clock_source_request(struct usbd_class_data *const c_data,
503 const struct usb_setup_packet *const setup,
504 struct net_buf *const buf)
505 {
506 const uint32_t *frequencies;
507 size_t count;
508
509 /* Channel Number must be zero */
510 if (CONTROL_CHANNEL_NUMBER(setup) != 0) {
511 LOG_DBG("Clock source control with channel %d",
512 CONTROL_CHANNEL_NUMBER(setup));
513 errno = -EINVAL;
514 return 0;
515 }
516
517 count = clock_frequencies(c_data, CONTROL_ENTITY_ID(setup), &frequencies);
518
519 if (CONTROL_SELECTOR(setup) == CS_SAM_FREQ_CONTROL) {
520 if (CONTROL_ATTRIBUTE(setup) == CUR) {
521 if (count == 1) {
522 layout3_cur_response(buf, setup->wLength,
523 frequencies[0]);
524 return 0;
525 }
526 /* TODO: If there is more than one frequency supported,
527 * call registered application API to determine active
528 * sample rate.
529 */
530 } else if (CONTROL_ATTRIBUTE(setup) == RANGE) {
531 layout3_range_response(buf, setup->wLength, frequencies,
532 frequencies, NULL, count);
533 return 0;
534 }
535 } else {
536 LOG_DBG("Unhandled clock control selector 0x%02x",
537 CONTROL_SELECTOR(setup));
538 }
539
540 errno = -ENOTSUP;
541 return 0;
542 }
543
uac2_control_to_host(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,struct net_buf * const buf)544 static int uac2_control_to_host(struct usbd_class_data *const c_data,
545 const struct usb_setup_packet *const setup,
546 struct net_buf *const buf)
547 {
548 entity_type_t entity_type;
549
550 if ((CONTROL_ATTRIBUTE(setup) != CUR) &&
551 (CONTROL_ATTRIBUTE(setup) != RANGE)) {
552 errno = -ENOTSUP;
553 return 0;
554 }
555
556 if (setup->bmRequestType == GET_CLASS_REQUEST_TYPE) {
557 entity_type = id_type(c_data, CONTROL_ENTITY_ID(setup));
558 if (entity_type == ENTITY_TYPE_CLOCK_SOURCE) {
559 return get_clock_source_request(c_data, setup, buf);
560 }
561 }
562
563 errno = -ENOTSUP;
564 return 0;
565 }
566
uac2_request(struct usbd_class_data * const c_data,struct net_buf * buf,int err)567 static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *buf,
568 int err)
569 {
570 const struct device *dev = usbd_class_get_private(c_data);
571 const struct uac2_cfg *cfg = dev->config;
572 struct uac2_ctx *ctx = dev->data;
573 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
574 struct udc_buf_info *bi;
575 uint8_t ep, terminal;
576 uint16_t mps;
577 int as_idx;
578 bool is_feedback;
579
580 bi = udc_get_buf_info(buf);
581 if (err) {
582 if (err == -ECONNABORTED) {
583 LOG_WRN("request ep 0x%02x, len %u cancelled",
584 bi->ep, buf->len);
585 } else {
586 LOG_ERR("request ep 0x%02x, len %u failed",
587 bi->ep, buf->len);
588 }
589 }
590
591 mps = buf->size;
592 ep = bi->ep;
593 as_idx = ep_to_as_interface(dev, ep, &is_feedback);
594 __ASSERT_NO_MSG((as_idx >= 0) && (as_idx < cfg->num_ifaces));
595 terminal = cfg->as_terminals[as_idx];
596
597 if (is_feedback) {
598 ctx->fb_queued &= ~BIT(as_idx);
599 } else {
600 atomic_clear_bit(&ctx->as_queued, as_idx);
601 }
602
603 if (USB_EP_DIR_IS_OUT(ep)) {
604 ctx->ops->data_recv_cb(dev, terminal, buf->__buf, buf->len,
605 ctx->user_data);
606 } else if (!is_feedback) {
607 ctx->ops->buf_release_cb(dev, terminal, buf->__buf, ctx->user_data);
608 }
609
610 usbd_ep_buf_free(uds_ctx, buf);
611 if (err) {
612 return 0;
613 }
614
615 /* Reschedule the read or explicit feedback write */
616 if (USB_EP_DIR_IS_OUT(ep)) {
617 schedule_iso_out_read(c_data, ep, mps, terminal);
618 }
619
620 return 0;
621 }
622
uac2_sof(struct usbd_class_data * const c_data)623 static void uac2_sof(struct usbd_class_data *const c_data)
624 {
625 const struct device *dev = usbd_class_get_private(c_data);
626 const struct usb_ep_descriptor *data_ep;
627 const struct usb_ep_descriptor *feedback_ep;
628 const struct uac2_cfg *cfg = dev->config;
629 struct uac2_ctx *ctx = dev->data;
630 int as_idx;
631
632 ctx->ops->sof_cb(dev, ctx->user_data);
633
634 for (as_idx = 0; as_idx < cfg->num_ifaces; as_idx++) {
635 /* Make sure OUT endpoint has read request pending. The request
636 * won't be pending only if there was buffer underrun, i.e. the
637 * application failed to supply receive buffer.
638 */
639 data_ep = get_as_data_ep(c_data, as_idx);
640 if (data_ep && USB_EP_DIR_IS_OUT(data_ep->bEndpointAddress)) {
641 schedule_iso_out_read(c_data, data_ep->bEndpointAddress,
642 sys_le16_to_cpu(data_ep->wMaxPacketSize),
643 cfg->as_terminals[as_idx]);
644 }
645
646 /* Skip interfaces without explicit feedback endpoint */
647 feedback_ep = get_as_feedback_ep(c_data, as_idx);
648 if (feedback_ep == NULL) {
649 continue;
650 }
651
652 /* We didn't get feedback write request callback yet, skip it
653 * for now to allow faster recovery (i.e. reduce workload to be
654 * done during this frame).
655 */
656 if (ctx->fb_queued & BIT(as_idx)) {
657 continue;
658 }
659
660 /* Only send feedback if host has enabled alternate interface */
661 if (!atomic_test_bit(&ctx->as_active, as_idx)) {
662 continue;
663 }
664
665 /* Make feedback available on every frame (value "sent" in
666 * previous SOF is "gone" even if USB host did not attempt to
667 * read it).
668 */
669 write_explicit_feedback(c_data, feedback_ep->bEndpointAddress,
670 cfg->as_terminals[as_idx]);
671 }
672 }
673
uac2_get_desc(struct usbd_class_data * const c_data,const enum usbd_speed speed)674 static void *uac2_get_desc(struct usbd_class_data *const c_data,
675 const enum usbd_speed speed)
676 {
677 struct device *dev = usbd_class_get_private(c_data);
678 const struct uac2_cfg *cfg = dev->config;
679
680 if (speed == USBD_SPEED_FS) {
681 return cfg->descriptors;
682 }
683
684 return NULL;
685 }
686
uac2_init(struct usbd_class_data * const c_data)687 static int uac2_init(struct usbd_class_data *const c_data)
688 {
689 const struct device *dev = usbd_class_get_private(c_data);
690 struct uac2_ctx *ctx = dev->data;
691
692 if (ctx->ops == NULL) {
693 LOG_ERR("Application did not register UAC2 ops");
694 return -EINVAL;
695 }
696
697 return 0;
698 }
699
700 struct usbd_class_api uac2_api = {
701 .update = uac2_update,
702 .control_to_host = uac2_control_to_host,
703 .request = uac2_request,
704 .sof = uac2_sof,
705 .get_desc = uac2_get_desc,
706 .init = uac2_init,
707 };
708
709 #define DEFINE_ENTITY_TYPES(node) \
710 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \
711 ENTITY_TYPE_CLOCK_SOURCE \
712 )) \
713 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_input_terminal), ( \
714 ENTITY_TYPE_INPUT_TERMINAL \
715 )) \
716 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_output_terminal), ( \
717 ENTITY_TYPE_OUTPUT_TERMINAL \
718 )) \
719 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
720 ENTITY_TYPE_INVALID \
721 )) \
722 , /* Comma here causes unknown types to fail at compile time */
723 #define DEFINE_AS_EP_INDEXES(node) \
724 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
725 COND_CODE_1(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), \
726 (UAC2_DESCRIPTOR_AS_DATA_EP_INDEX(node),), (0,)) \
727 ))
728 #define DEFINE_AS_FB_INDEXES(node) \
729 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
730 COND_CODE_1(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), \
731 (UAC2_DESCRIPTOR_AS_FEEDBACK_EP_INDEX(node),), (0,)) \
732 ))
733 #define DEFINE_AS_TERMINALS(node) \
734 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
735 ENTITY_ID(DT_PROP(node, linked_terminal)), \
736 ))
737
738 #define FREQUENCY_TABLE_NAME(node, i) \
739 UTIL_CAT(frequencies_##i##_, ENTITY_ID(node))
740 #define DEFINE_CLOCK_SOURCES(node, i) \
741 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \
742 static const uint32_t FREQUENCY_TABLE_NAME(node, i)[] = \
743 DT_PROP(node, sampling_frequencies); \
744 ))
745
746 #define DEFINE_LOOKUP_TABLES(i) \
747 static const entity_type_t entity_types_##i[] = { \
748 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_ENTITY_TYPES) \
749 }; \
750 static const uint16_t ep_indexes_##i[] = { \
751 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_AS_EP_INDEXES) \
752 }; \
753 static const uint16_t fb_indexes_##i[] = { \
754 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_AS_FB_INDEXES) \
755 }; \
756 static const uint8_t as_terminals_##i[] = { \
757 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_AS_TERMINALS) \
758 }; \
759 DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(i, DEFINE_CLOCK_SOURCES, i)
760
761 #define DEFINE_UAC2_CLASS_DATA(inst) \
762 DT_INST_FOREACH_CHILD(inst, VALIDATE_NODE) \
763 static struct uac2_ctx uac2_ctx_##inst; \
764 UAC2_DESCRIPTOR_ARRAYS(DT_DRV_INST(inst)) \
765 static const struct usb_desc_header *uac2_descriptors_##inst[] = { \
766 UAC2_DESCRIPTOR_PTRS(DT_DRV_INST(inst)) \
767 }; \
768 USBD_DEFINE_CLASS(uac2_##inst, &uac2_api, \
769 (void *)DEVICE_DT_GET(DT_DRV_INST(inst)), NULL); \
770 DEFINE_LOOKUP_TABLES(inst) \
771 static const struct uac2_cfg uac2_cfg_##inst = { \
772 .c_data = &uac2_##inst, \
773 .descriptors = uac2_descriptors_##inst, \
774 .entity_types = entity_types_##inst, \
775 .ep_indexes = ep_indexes_##inst, \
776 .fb_indexes = fb_indexes_##inst, \
777 .as_terminals = as_terminals_##inst, \
778 .num_ifaces = ARRAY_SIZE(ep_indexes_##inst), \
779 .num_entities = ARRAY_SIZE(entity_types_##inst), \
780 }; \
781 BUILD_ASSERT(ARRAY_SIZE(ep_indexes_##inst) <= 32, \
782 "UAC2 implementation supports up to 32 AS interfaces"); \
783 BUILD_ASSERT(ARRAY_SIZE(entity_types_##inst) <= 255, \
784 "UAC2 supports up to 255 entities"); \
785 DEVICE_DT_DEFINE(DT_DRV_INST(inst), NULL, NULL, \
786 &uac2_ctx_##inst, &uac2_cfg_##inst, \
787 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
788 NULL);
DT_INST_FOREACH_STATUS_OKAY(DEFINE_UAC2_CLASS_DATA)789 DT_INST_FOREACH_STATUS_OKAY(DEFINE_UAC2_CLASS_DATA)
790
791 static size_t clock_frequencies(struct usbd_class_data *const c_data,
792 const uint8_t id, const uint32_t **frequencies)
793 {
794 const struct device *dev = usbd_class_get_private(c_data);
795 size_t count;
796
797 #define GET_FREQUENCY_TABLE(node, i) \
798 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \
799 } else if (id == ENTITY_ID(node)) { \
800 *frequencies = FREQUENCY_TABLE_NAME(node, i); \
801 count = ARRAY_SIZE(FREQUENCY_TABLE_NAME(node, i)); \
802 ))
803
804 if (0) {
805 #define SELECT_FREQUENCY_TABLE(i) \
806 } else if (dev == DEVICE_DT_GET(DT_DRV_INST(i))) { \
807 if (0) { \
808 DT_INST_FOREACH_CHILD_VARGS(i, GET_FREQUENCY_TABLE, i) \
809 } else { \
810 *frequencies = NULL; \
811 count = 0; \
812 }
813 DT_INST_FOREACH_STATUS_OKAY(SELECT_FREQUENCY_TABLE)
814 } else {
815 *frequencies = NULL;
816 count = 0;
817 }
818
819 return count;
820 }
821