1 /*
2 * Copyright (c) 2023-2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/sys/atomic.h>
13 #include <zephyr/sys/byteorder.h>
14
15 #include <zephyr/usb/usbd.h>
16 #include <zephyr/usb/usb_ch9.h>
17 #include <zephyr/usb/class/usbd_uac2.h>
18 #include <zephyr/drivers/usb/udc.h>
19
20 #include "usbd_uac2_macros.h"
21
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(usbd_uac2, CONFIG_USBD_UAC2_LOG_LEVEL);
24
25 #define DT_DRV_COMPAT zephyr_uac2
26
27 #define COUNT_UAC2_AS_ENDPOINT_BUFFERS(node) \
28 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
29 + AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) \
30 + AS_IS_USB_ISO_IN(node) /* ISO IN double buffering */ \
31 + AS_IS_USB_ISO_OUT(node) /* ISO OUT double buffering */ \
32 + 2 * AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node)))
33 #define COUNT_UAC2_EP_BUFFERS(i) \
34 + DT_PROP(DT_DRV_INST(i), interrupt_endpoint) \
35 DT_INST_FOREACH_CHILD(i, COUNT_UAC2_AS_ENDPOINT_BUFFERS)
36 #define UAC2_NUM_EP_BUFFERS DT_INST_FOREACH_STATUS_OKAY(COUNT_UAC2_EP_BUFFERS)
37
38 /* Net buf is used mostly with external data. The main reason behind external
39 * data is avoiding unnecessary isochronous data copy operations.
40 *
41 * Allow up to 6 bytes per item to facilitate optional interrupt endpoint (which
42 * requires 6 bytes) and feedback endpoint (4 bytes on High-Speed, 3 bytes on
43 * Full-Speed). Because the total number of endpoints is really small (typically
44 * there will be just 2 isochronous endpoints; the upper bound originating from
45 * the USB specification itself is 30 non-control endpoints). Therefore, the
46 * "wasted memory" here is likely to be smaller than the memory overhead for
47 * more complex "only as much as needed" schemes (e.g. heap).
48 */
49 UDC_BUF_POOL_DEFINE(uac2_pool, UAC2_NUM_EP_BUFFERS, 6,
50 sizeof(struct udc_buf_info), NULL);
51
52 /* 5.2.2 Control Request Layout */
53 #define SET_CLASS_REQUEST_TYPE 0x21
54 #define GET_CLASS_REQUEST_TYPE 0xA1
55
56 /* A.14 Audio Class-Specific Request Codes */
57 #define CUR 0x01
58 #define RANGE 0x02
59 #define MEM 0x03
60
61 /* A.17.1 Clock Source Control Selectors */
62 #define CS_SAM_FREQ_CONTROL 0x01
63 #define CS_CLOCK_VALID_CONTROL 0x02
64
65 #define CONTROL_ATTRIBUTE(setup) (setup->bRequest)
66 #define CONTROL_ENTITY_ID(setup) ((setup->wIndex & 0xFF00) >> 8)
67 #define CONTROL_SELECTOR(setup) ((setup->wValue & 0xFF00) >> 8)
68 #define CONTROL_CHANNEL_NUMBER(setup) (setup->wValue & 0x00FF)
69
70 typedef enum {
71 ENTITY_TYPE_INVALID,
72 ENTITY_TYPE_CLOCK_SOURCE,
73 ENTITY_TYPE_INPUT_TERMINAL,
74 ENTITY_TYPE_OUTPUT_TERMINAL,
75 } entity_type_t;
76
77 static size_t clock_frequencies(struct usbd_class_data *const c_data,
78 const uint8_t id, const uint32_t **frequencies);
79
80 /* UAC2 device runtime data */
81 struct uac2_ctx {
82 const struct uac2_ops *ops;
83 void *user_data;
84 /* Bit set indicates the AudioStreaming interface has non-zero bandwidth
85 * alternate setting active.
86 */
87 atomic_t as_active;
88 atomic_t as_queued;
89 atomic_t as_double;
90 uint32_t fb_queued;
91 uint32_t fb_double;
92 };
93
94 /* UAC2 device constant data */
95 struct uac2_cfg {
96 struct usbd_class_data *const c_data;
97 const struct usb_desc_header **fs_descriptors;
98 const struct usb_desc_header **hs_descriptors;
99 /* Entity 1 type is at entity_types[0] */
100 const entity_type_t *entity_types;
101 /* Array of indexes to data endpoint descriptor in descriptors set.
102 * First AudioStreaming interface is at ep_indexes[0]. Index is 0 if
103 * the interface is external interface (Type IV), i.e. no endpoint.
104 */
105 const uint16_t *ep_indexes;
106 /* Same as ep_indexes, but for explicit feedback endpoints. */
107 const uint16_t *fb_indexes;
108 /* First AudioStreaming interface Terminal ID is at as_terminals[0]. */
109 const uint8_t *as_terminals;
110 /* Number of interfaces (ep_indexes, fb_indexes and as_terminals size) */
111 uint8_t num_ifaces;
112 /* Number of entities (entity_type array size) */
113 uint8_t num_entities;
114 };
115
id_type(struct usbd_class_data * const c_data,uint8_t id)116 static entity_type_t id_type(struct usbd_class_data *const c_data, uint8_t id)
117 {
118 const struct device *dev = usbd_class_get_private(c_data);
119 const struct uac2_cfg *cfg = dev->config;
120
121 if ((id - 1) < cfg->num_entities) {
122 return cfg->entity_types[id - 1];
123 }
124
125 return ENTITY_TYPE_INVALID;
126 }
127
128 static const struct usb_ep_descriptor *
get_as_data_ep(struct usbd_class_data * const c_data,int as_idx)129 get_as_data_ep(struct usbd_class_data *const c_data, int as_idx)
130 {
131 const struct device *dev = usbd_class_get_private(c_data);
132 const struct uac2_cfg *cfg = dev->config;
133 const struct usb_desc_header *desc = NULL;
134 const struct usb_desc_header **descriptors;
135
136 if (usbd_bus_speed(c_data->uds_ctx) == USBD_SPEED_FS) {
137 descriptors = cfg->fs_descriptors;
138 } else {
139 descriptors = cfg->hs_descriptors;
140 }
141
142 if ((as_idx >= 0) && (as_idx < cfg->num_ifaces) &&
143 cfg->ep_indexes[as_idx] && descriptors) {
144 desc = descriptors[cfg->ep_indexes[as_idx]];
145 }
146
147 return (const struct usb_ep_descriptor *)desc;
148 }
149
150 static const struct usb_ep_descriptor *
get_as_feedback_ep(struct usbd_class_data * const c_data,int as_idx)151 get_as_feedback_ep(struct usbd_class_data *const c_data, int as_idx)
152 {
153 const struct device *dev = usbd_class_get_private(c_data);
154 const struct uac2_cfg *cfg = dev->config;
155 const struct usb_desc_header *desc = NULL;
156 const struct usb_desc_header **descriptors;
157
158 if (usbd_bus_speed(c_data->uds_ctx) == USBD_SPEED_FS) {
159 descriptors = cfg->fs_descriptors;
160 } else {
161 descriptors = cfg->hs_descriptors;
162 }
163
164 if ((as_idx < cfg->num_ifaces) && cfg->fb_indexes[as_idx] &&
165 descriptors) {
166 desc = descriptors[cfg->fb_indexes[as_idx]];
167 }
168
169 return (const struct usb_ep_descriptor *)desc;
170 }
171
ep_to_as_interface(const struct device * dev,uint8_t ep,bool * fb)172 static int ep_to_as_interface(const struct device *dev, uint8_t ep, bool *fb)
173 {
174 const struct uac2_cfg *cfg = dev->config;
175 const struct usb_ep_descriptor *desc;
176
177 for (int i = 0; i < cfg->num_ifaces; i++) {
178 if (!cfg->ep_indexes[i]) {
179 /* If there is no data endpoint there cannot be feedback
180 * endpoint. Simply skip external interfaces.
181 */
182 continue;
183 }
184
185 desc = get_as_data_ep(cfg->c_data, i);
186 if (desc && (ep == desc->bEndpointAddress)) {
187 *fb = false;
188 return i;
189 }
190
191 desc = get_as_feedback_ep(cfg->c_data, i);
192 if (desc && (ep == desc->bEndpointAddress)) {
193 *fb = true;
194 return i;
195 }
196 }
197
198 *fb = false;
199 return -ENOENT;
200 }
201
terminal_to_as_interface(const struct device * dev,uint8_t terminal)202 static int terminal_to_as_interface(const struct device *dev, uint8_t terminal)
203 {
204 const struct uac2_cfg *cfg = dev->config;
205
206 for (int as_idx = 0; as_idx < cfg->num_ifaces; as_idx++) {
207 if (terminal == cfg->as_terminals[as_idx]) {
208 return as_idx;
209 }
210 }
211
212 return -ENOENT;
213 }
214
usbd_uac2_set_ops(const struct device * dev,const struct uac2_ops * ops,void * user_data)215 void usbd_uac2_set_ops(const struct device *dev,
216 const struct uac2_ops *ops, void *user_data)
217 {
218 const struct uac2_cfg *cfg = dev->config;
219 struct uac2_ctx *ctx = dev->data;
220
221 __ASSERT(ops->sof_cb, "SOF callback is mandatory");
222 __ASSERT(ops->terminal_update_cb, "terminal_update_cb is mandatory");
223
224 for (uint8_t i = 0U; i < cfg->num_ifaces; i++) {
225 const uint16_t ep_idx = cfg->ep_indexes[i];
226
227 if (cfg->fb_indexes[i] != 0U) {
228 __ASSERT(ops->feedback_cb, "feedback_cb is mandatory");
229 }
230
231 if (ep_idx) {
232 const struct usb_ep_descriptor *desc = NULL;
233
234 if (cfg->fs_descriptors != NULL) {
235 /* If fs_descriptors is non-NULL and ep_idx is non-zero then
236 * cfg->fs_descriptors[ep_idx] is non-NULL
237 */
238 desc = (const struct usb_ep_descriptor *)
239 cfg->fs_descriptors[ep_idx];
240 } else if (cfg->hs_descriptors != NULL) {
241 /* If hs_descriptors is non-NULL and ep_idx is non-zero then
242 * cfg->hs_descriptors[ep_idx] is non-NULL
243 */
244 desc = (const struct usb_ep_descriptor *)
245 cfg->hs_descriptors[ep_idx];
246 }
247
248 if (desc != NULL) {
249 if (USB_EP_DIR_IS_OUT(desc->bEndpointAddress)) {
250 __ASSERT(ops->get_recv_buf, "get_recv_buf is mandatory");
251 __ASSERT(ops->data_recv_cb, "data_recv_cb is mandatory");
252 }
253
254 if (USB_EP_DIR_IS_IN(desc->bEndpointAddress)) {
255 __ASSERT(ops->buf_release_cb,
256 "buf_release_cb is mandatory");
257 }
258 }
259 }
260 }
261
262 ctx->ops = ops;
263 ctx->user_data = user_data;
264 }
265
266 static struct net_buf *
uac2_buf_alloc(const uint8_t ep,void * data,uint16_t size)267 uac2_buf_alloc(const uint8_t ep, void *data, uint16_t size)
268 {
269 struct net_buf *buf = NULL;
270 struct udc_buf_info *bi;
271
272 __ASSERT(IS_UDC_ALIGNED(data), "Application provided unaligned buffer");
273
274 buf = net_buf_alloc_with_data(&uac2_pool, data, size, K_NO_WAIT);
275 if (!buf) {
276 return NULL;
277 }
278
279 bi = udc_get_buf_info(buf);
280 bi->ep = ep;
281
282 if (USB_EP_DIR_IS_OUT(ep)) {
283 /* Buffer is empty, USB stack will write data from host */
284 buf->len = 0;
285 }
286
287 return buf;
288 }
289
usbd_uac2_send(const struct device * dev,uint8_t terminal,void * data,uint16_t size)290 int usbd_uac2_send(const struct device *dev, uint8_t terminal,
291 void *data, uint16_t size)
292 {
293 const struct uac2_cfg *cfg = dev->config;
294 struct uac2_ctx *ctx = dev->data;
295 struct net_buf *buf;
296 const struct usb_ep_descriptor *desc;
297 atomic_t *queued_bits = &ctx->as_queued;
298 uint8_t ep = 0;
299 int as_idx = terminal_to_as_interface(dev, terminal);
300 int ret;
301
302 desc = get_as_data_ep(cfg->c_data, as_idx);
303 if (desc) {
304 ep = desc->bEndpointAddress;
305 }
306
307 if (!ep) {
308 LOG_ERR("No endpoint for terminal %d", terminal);
309 return -ENOENT;
310 }
311
312 if (!atomic_test_bit(&ctx->as_active, as_idx)) {
313 /* Host is not interested in the data */
314 ctx->ops->buf_release_cb(dev, terminal, data, ctx->user_data);
315 return 0;
316 }
317
318 if (atomic_test_and_set_bit(queued_bits, as_idx)) {
319 queued_bits = &ctx->as_double;
320 if (atomic_test_and_set_bit(queued_bits, as_idx)) {
321 LOG_DBG("Already double queued on 0x%02x", ep);
322 return -EAGAIN;
323 }
324 }
325
326 buf = uac2_buf_alloc(ep, data, size);
327 if (!buf) {
328 /* This shouldn't really happen because netbuf should be large
329 * enough, but if it does all we loose is just single packet.
330 */
331 LOG_ERR("No netbuf for send");
332 atomic_clear_bit(queued_bits, as_idx);
333 return -ENOMEM;
334 }
335
336 ret = usbd_ep_enqueue(cfg->c_data, buf);
337 if (ret) {
338 LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
339 net_buf_unref(buf);
340 atomic_clear_bit(queued_bits, as_idx);
341 }
342
343 return ret;
344 }
345
schedule_iso_out_read(struct usbd_class_data * const c_data,uint8_t ep,uint16_t mps,uint8_t terminal)346 static void schedule_iso_out_read(struct usbd_class_data *const c_data,
347 uint8_t ep, uint16_t mps, uint8_t terminal)
348 {
349 const struct device *dev = usbd_class_get_private(c_data);
350 const struct uac2_cfg *cfg = dev->config;
351 struct uac2_ctx *ctx = dev->data;
352 struct net_buf *buf;
353 atomic_t *queued_bits = &ctx->as_queued;
354 void *data_buf;
355 int as_idx = terminal_to_as_interface(dev, terminal);
356 int ret;
357
358 /* All calls to this function are internal to class, if terminal is not
359 * associated with interface there is a bug in class implementation.
360 */
361 __ASSERT_NO_MSG((as_idx >= 0) && (as_idx < cfg->num_ifaces));
362 /* Silence warning if asserts are not enabled */
363 ARG_UNUSED(cfg);
364
365 if (!((as_idx >= 0) && atomic_test_bit(&ctx->as_active, as_idx))) {
366 /* Host won't send data */
367 return;
368 }
369
370 if (atomic_test_and_set_bit(queued_bits, as_idx)) {
371 queued_bits = &ctx->as_double;
372 if (atomic_test_and_set_bit(queued_bits, as_idx)) {
373 /* Transfer already double queued - nothing to do */
374 return;
375 }
376 }
377
378 /* Prepare transfer to read audio OUT data from host */
379 data_buf = ctx->ops->get_recv_buf(dev, terminal, mps, ctx->user_data);
380 if (!data_buf) {
381 LOG_ERR("No data buffer for terminal %d", terminal);
382 atomic_clear_bit(queued_bits, as_idx);
383 return;
384 }
385
386 buf = uac2_buf_alloc(ep, data_buf, mps);
387 if (!buf) {
388 LOG_ERR("No netbuf for read");
389 /* Netbuf pool should be large enough, but if for some reason
390 * we are out of netbuf, there's nothing better to do than to
391 * pass the buffer back to application.
392 */
393 ctx->ops->data_recv_cb(dev, terminal,
394 data_buf, 0, ctx->user_data);
395 atomic_clear_bit(queued_bits, as_idx);
396 return;
397 }
398
399 ret = usbd_ep_enqueue(c_data, buf);
400 if (ret) {
401 LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
402 net_buf_unref(buf);
403 ctx->ops->data_recv_cb(dev, terminal,
404 data_buf, 0, ctx->user_data);
405 atomic_clear_bit(queued_bits, as_idx);
406 }
407 }
408
write_explicit_feedback(struct usbd_class_data * const c_data,uint8_t ep,uint8_t terminal)409 static void write_explicit_feedback(struct usbd_class_data *const c_data,
410 uint8_t ep, uint8_t terminal)
411 {
412 const struct device *dev = usbd_class_get_private(c_data);
413 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
414 struct uac2_ctx *ctx = dev->data;
415 struct net_buf *buf;
416 struct udc_buf_info *bi;
417 uint32_t fb_value;
418 int as_idx = terminal_to_as_interface(dev, terminal);
419 int ret;
420
421 __ASSERT_NO_MSG(as_idx >= 0);
422
423 buf = net_buf_alloc(&uac2_pool, K_NO_WAIT);
424 if (!buf) {
425 LOG_ERR("No buf for feedback");
426 return;
427 }
428
429 bi = udc_get_buf_info(buf);
430 bi->ep = ep;
431
432 fb_value = ctx->ops->feedback_cb(dev, terminal, ctx->user_data);
433
434 if (usbd_bus_speed(uds_ctx) == USBD_SPEED_FS) {
435 net_buf_add_le24(buf, fb_value);
436 } else {
437 net_buf_add_le32(buf, fb_value);
438 }
439
440 ret = usbd_ep_enqueue(c_data, buf);
441 if (ret) {
442 LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
443 net_buf_unref(buf);
444 } else {
445 if (ctx->fb_queued & BIT(as_idx)) {
446 ctx->fb_double |= BIT(as_idx);
447 } else {
448 ctx->fb_queued |= BIT(as_idx);
449 }
450 }
451 }
452
uac2_update(struct usbd_class_data * const c_data,uint8_t iface,uint8_t alternate)453 void uac2_update(struct usbd_class_data *const c_data,
454 uint8_t iface, uint8_t alternate)
455 {
456 const struct device *dev = usbd_class_get_private(c_data);
457 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
458 const struct uac2_cfg *cfg = dev->config;
459 struct uac2_ctx *ctx = dev->data;
460 const struct usb_desc_header **descriptors;
461 const struct usb_association_descriptor *iad;
462 const struct usb_ep_descriptor *data_ep, *fb_ep;
463 uint8_t as_idx;
464 bool microframes;
465
466 LOG_DBG("iface %d alt %d", iface, alternate);
467
468 /* Audio class is forbidden on Low-Speed, therefore the only possibility
469 * for not using microframes is when device operates at Full-Speed.
470 */
471 if (usbd_bus_speed(uds_ctx) == USBD_SPEED_FS) {
472 microframes = false;
473 descriptors = cfg->fs_descriptors;
474 } else {
475 microframes = true;
476 descriptors = cfg->hs_descriptors;
477 }
478
479 if (!descriptors) {
480 return;
481 }
482
483 iad = (const struct usb_association_descriptor *)descriptors[0];
484
485 /* AudioControl interface (bFirstInterface) doesn't have alternate
486 * configurations, therefore the iface must be AudioStreaming.
487 */
488 __ASSERT_NO_MSG((iface > iad->bFirstInterface) &&
489 (iface < iad->bFirstInterface + iad->bInterfaceCount));
490 as_idx = iface - iad->bFirstInterface - 1;
491
492 /* Notify application about terminal state change */
493 ctx->ops->terminal_update_cb(dev, cfg->as_terminals[as_idx], alternate,
494 microframes, ctx->user_data);
495
496 if (alternate == 0) {
497 /* Mark interface as inactive, any pending endpoint transfers
498 * were already cancelled by the USB stack.
499 */
500 atomic_clear_bit(&ctx->as_active, as_idx);
501 return;
502 }
503
504 atomic_set_bit(&ctx->as_active, as_idx);
505
506 data_ep = get_as_data_ep(c_data, as_idx);
507 /* External interfaces (i.e. NULL data_ep) do not have alternate
508 * configuration and therefore data_ep must be valid here.
509 */
510 __ASSERT_NO_MSG(data_ep);
511
512 if (USB_EP_DIR_IS_OUT(data_ep->bEndpointAddress)) {
513 schedule_iso_out_read(c_data, data_ep->bEndpointAddress,
514 sys_le16_to_cpu(data_ep->wMaxPacketSize),
515 cfg->as_terminals[as_idx]);
516
517 fb_ep = get_as_feedback_ep(c_data, as_idx);
518 if (fb_ep) {
519 write_explicit_feedback(c_data, fb_ep->bEndpointAddress,
520 cfg->as_terminals[as_idx]);
521 }
522 }
523 }
524
525 /* 5.2.2 Control Request Layout: "As a general rule, when an attribute value
526 * is set, a Control will automatically adjust the passed value to the closest
527 * available valid value."
528 *
529 * The values array must be sorted ascending with at least 1 element.
530 */
find_closest(const uint32_t input,const uint32_t * values,const size_t values_count)531 static uint32_t find_closest(const uint32_t input, const uint32_t *values,
532 const size_t values_count)
533 {
534 size_t i;
535
536 __ASSERT_NO_MSG(values_count);
537
538 for (i = 0; i < values_count; i++) {
539 if (input == values[i]) {
540 /* Exact match */
541 return input;
542 } else if (input < values[i]) {
543 break;
544 }
545 }
546
547 if (i == values_count) {
548 /* All values are smaller than input, return largest value */
549 return values[i - 1];
550 }
551
552 if (i == 0) {
553 /* All values are larger than input, return smallest value */
554 return values[i];
555 }
556
557 /* At this point values[i] is larger than input and values[i - 1] is
558 * smaller than input, find and return the one that is closer, favoring
559 * bigger value if input is exactly in the middle between the two.
560 */
561 if ((values[i] - input) > (input - values[i - 1])) {
562 return values[i - 1];
563 } else {
564 return values[i];
565 }
566 }
567
568 /* Table 5-6: 4-byte Control CUR Parameter Block */
layout3_cur_response(struct net_buf * const buf,uint16_t length,const uint32_t value)569 static void layout3_cur_response(struct net_buf *const buf, uint16_t length,
570 const uint32_t value)
571 {
572 uint8_t tmp[4];
573
574 /* dCUR */
575 sys_put_le32(value, tmp);
576 net_buf_add_mem(buf, tmp, MIN(length, 4));
577 }
578
layout3_cur_request(const struct net_buf * const buf,uint32_t * out)579 static int layout3_cur_request(const struct net_buf *const buf, uint32_t *out)
580 {
581 uint8_t tmp[4];
582
583 if (buf->len != 4) {
584 return -EINVAL;
585 }
586
587 memcpy(tmp, buf->data, sizeof(tmp));
588 *out = sys_get_le32(tmp);
589 return 0;
590 }
591
592 /* 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)593 static void layout3_range_response(struct net_buf *const buf, uint16_t length,
594 const uint32_t *min, const uint32_t *max,
595 const uint32_t *res, int n)
596 {
597 uint16_t to_add;
598 uint8_t tmp[4];
599 int i;
600 int item;
601
602 /* wNumSubRanges */
603 sys_put_le16(n, tmp);
604 to_add = MIN(length, 2);
605 net_buf_add_mem(buf, tmp, to_add);
606 length -= to_add;
607
608 /* Keep adding dMIN, dMAX, dRES as long as we have entries to add and
609 * we didn't reach wLength response limit.
610 */
611 i = item = 0;
612 while ((length > 0) && (i < n)) {
613 to_add = MIN(length, 4);
614 if (item == 0) {
615 sys_put_le32(min[i], tmp);
616 } else if (item == 1) {
617 sys_put_le32(max[i], tmp);
618 } else if (item == 2) {
619 if (res) {
620 sys_put_le32(res[i], tmp);
621 } else {
622 memset(tmp, 0, 4);
623 }
624 }
625 net_buf_add_mem(buf, tmp, to_add);
626 length -= to_add;
627
628 if (++item == 3) {
629 item = 0;
630 i++;
631 }
632 }
633 }
634
get_clock_source_request(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,struct net_buf * const buf)635 static int get_clock_source_request(struct usbd_class_data *const c_data,
636 const struct usb_setup_packet *const setup,
637 struct net_buf *const buf)
638 {
639 const struct device *dev = usbd_class_get_private(c_data);
640 struct uac2_ctx *ctx = dev->data;
641 const uint32_t *frequencies;
642 const uint32_t clock_id = CONTROL_ENTITY_ID(setup);
643 size_t count;
644
645 /* Channel Number must be zero */
646 if (CONTROL_CHANNEL_NUMBER(setup) != 0) {
647 LOG_DBG("Clock source control with channel %d",
648 CONTROL_CHANNEL_NUMBER(setup));
649 errno = -EINVAL;
650 return 0;
651 }
652
653 count = clock_frequencies(c_data, clock_id, &frequencies);
654
655 if (CONTROL_SELECTOR(setup) == CS_SAM_FREQ_CONTROL) {
656 if (CONTROL_ATTRIBUTE(setup) == CUR) {
657 if (count == 1) {
658 layout3_cur_response(buf, setup->wLength,
659 frequencies[0]);
660 return 0;
661 }
662
663 if (ctx->ops->get_sample_rate) {
664 uint32_t hz;
665
666 hz = ctx->ops->get_sample_rate(dev, clock_id,
667 ctx->user_data);
668 layout3_cur_response(buf, setup->wLength, hz);
669 return 0;
670 }
671 } else if (CONTROL_ATTRIBUTE(setup) == RANGE) {
672 layout3_range_response(buf, setup->wLength, frequencies,
673 frequencies, NULL, count);
674 return 0;
675 }
676 } else {
677 LOG_DBG("Unhandled clock control selector 0x%02x",
678 CONTROL_SELECTOR(setup));
679 }
680
681 errno = -ENOTSUP;
682 return 0;
683 }
684
set_clock_source_request(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,const struct net_buf * const buf)685 static int set_clock_source_request(struct usbd_class_data *const c_data,
686 const struct usb_setup_packet *const setup,
687 const struct net_buf *const buf)
688 {
689 const struct device *dev = usbd_class_get_private(c_data);
690 struct uac2_ctx *ctx = dev->data;
691 const uint32_t *frequencies;
692 const uint32_t clock_id = CONTROL_ENTITY_ID(setup);
693 size_t count;
694
695 /* Channel Number must be zero */
696 if (CONTROL_CHANNEL_NUMBER(setup) != 0) {
697 LOG_DBG("Clock source control with channel %d",
698 CONTROL_CHANNEL_NUMBER(setup));
699 errno = -EINVAL;
700 return 0;
701 }
702
703 count = clock_frequencies(c_data, clock_id, &frequencies);
704
705 if (CONTROL_SELECTOR(setup) == CS_SAM_FREQ_CONTROL) {
706 if (CONTROL_ATTRIBUTE(setup) == CUR) {
707 uint32_t requested, hz;
708 int err;
709
710 err = layout3_cur_request(buf, &requested);
711 if (err) {
712 errno = err;
713 return 0;
714 }
715
716 hz = find_closest(requested, frequencies, count);
717
718 if (ctx->ops->set_sample_rate == NULL) {
719 /* The set_sample_rate() callback is optional
720 * if there is only one supported sample rate.
721 */
722 if (count > 1) {
723 errno = -ENOTSUP;
724 }
725 return 0;
726 }
727
728 err = ctx->ops->set_sample_rate(dev, clock_id, hz,
729 ctx->user_data);
730 if (err) {
731 errno = err;
732 }
733
734 return 0;
735 }
736 } else {
737 LOG_DBG("Unhandled clock control selector 0x%02x",
738 CONTROL_SELECTOR(setup));
739 }
740
741 errno = -ENOTSUP;
742 return 0;
743 }
744
uac2_control_to_dev(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,const struct net_buf * const buf)745 static int uac2_control_to_dev(struct usbd_class_data *const c_data,
746 const struct usb_setup_packet *const setup,
747 const struct net_buf *const buf)
748 {
749 entity_type_t entity_type;
750
751 if (CONTROL_ATTRIBUTE(setup) != CUR) {
752 errno = -ENOTSUP;
753 return 0;
754 }
755
756 if (setup->bmRequestType == SET_CLASS_REQUEST_TYPE) {
757 entity_type = id_type(c_data, CONTROL_ENTITY_ID(setup));
758 if (entity_type == ENTITY_TYPE_CLOCK_SOURCE) {
759 return set_clock_source_request(c_data, setup, buf);
760 }
761 }
762
763 errno = -ENOTSUP;
764 return 0;
765 }
766
uac2_control_to_host(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,struct net_buf * const buf)767 static int uac2_control_to_host(struct usbd_class_data *const c_data,
768 const struct usb_setup_packet *const setup,
769 struct net_buf *const buf)
770 {
771 entity_type_t entity_type;
772
773 if ((CONTROL_ATTRIBUTE(setup) != CUR) &&
774 (CONTROL_ATTRIBUTE(setup) != RANGE)) {
775 errno = -ENOTSUP;
776 return 0;
777 }
778
779 if (setup->bmRequestType == GET_CLASS_REQUEST_TYPE) {
780 entity_type = id_type(c_data, CONTROL_ENTITY_ID(setup));
781 if (entity_type == ENTITY_TYPE_CLOCK_SOURCE) {
782 return get_clock_source_request(c_data, setup, buf);
783 }
784 }
785
786 errno = -ENOTSUP;
787 return 0;
788 }
789
uac2_request(struct usbd_class_data * const c_data,struct net_buf * buf,int err)790 static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *buf,
791 int err)
792 {
793 const struct device *dev = usbd_class_get_private(c_data);
794 const struct uac2_cfg *cfg = dev->config;
795 struct uac2_ctx *ctx = dev->data;
796 struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
797 struct udc_buf_info *bi;
798 uint8_t ep, terminal;
799 uint16_t mps;
800 int as_idx;
801 bool is_feedback;
802
803 bi = udc_get_buf_info(buf);
804 if (err) {
805 if (err == -ECONNABORTED) {
806 LOG_WRN("request ep 0x%02x, len %u cancelled",
807 bi->ep, buf->len);
808 } else {
809 LOG_ERR("request ep 0x%02x, len %u failed",
810 bi->ep, buf->len);
811 }
812 }
813
814 mps = buf->size;
815 ep = bi->ep;
816 as_idx = ep_to_as_interface(dev, ep, &is_feedback);
817 __ASSERT_NO_MSG((as_idx >= 0) && (as_idx < cfg->num_ifaces));
818 terminal = cfg->as_terminals[as_idx];
819
820 if (is_feedback) {
821 bool clear_double = buf->frags;
822
823 if (ctx->fb_queued & BIT(as_idx)) {
824 ctx->fb_queued &= ~BIT(as_idx);
825 } else {
826 clear_double = true;
827 }
828
829 if (clear_double) {
830 ctx->fb_double &= ~BIT(as_idx);
831 }
832 } else if (!atomic_test_and_clear_bit(&ctx->as_queued, as_idx) || buf->frags) {
833 atomic_clear_bit(&ctx->as_double, as_idx);
834 }
835
836 if (USB_EP_DIR_IS_OUT(ep)) {
837 ctx->ops->data_recv_cb(dev, terminal, buf->__buf, buf->len,
838 ctx->user_data);
839 if (buf->frags) {
840 ctx->ops->data_recv_cb(dev, terminal, buf->frags->__buf,
841 buf->frags->len, ctx->user_data);
842 }
843 } else if (!is_feedback) {
844 ctx->ops->buf_release_cb(dev, terminal, buf->__buf, ctx->user_data);
845 if (buf->frags) {
846 ctx->ops->buf_release_cb(dev, terminal, buf->frags->__buf, ctx->user_data);
847 }
848 }
849
850 usbd_ep_buf_free(uds_ctx, buf);
851 if (err) {
852 return 0;
853 }
854
855 /* Reschedule the read or explicit feedback write */
856 if (USB_EP_DIR_IS_OUT(ep)) {
857 schedule_iso_out_read(c_data, ep, mps, terminal);
858 } else if (is_feedback) {
859 write_explicit_feedback(c_data, ep, cfg->as_terminals[as_idx]);
860 }
861
862 return 0;
863 }
864
uac2_sof(struct usbd_class_data * const c_data)865 static void uac2_sof(struct usbd_class_data *const c_data)
866 {
867 const struct device *dev = usbd_class_get_private(c_data);
868 const struct usb_ep_descriptor *data_ep;
869 const struct usb_ep_descriptor *feedback_ep;
870 const struct uac2_cfg *cfg = dev->config;
871 struct uac2_ctx *ctx = dev->data;
872 int as_idx;
873
874 ctx->ops->sof_cb(dev, ctx->user_data);
875
876 for (as_idx = 0; as_idx < cfg->num_ifaces; as_idx++) {
877 /* Make sure OUT endpoint has read request pending. The request
878 * won't be pending only if there was buffer underrun, i.e. the
879 * application failed to supply receive buffer.
880 */
881 data_ep = get_as_data_ep(c_data, as_idx);
882 if (data_ep && USB_EP_DIR_IS_OUT(data_ep->bEndpointAddress)) {
883 schedule_iso_out_read(c_data, data_ep->bEndpointAddress,
884 sys_le16_to_cpu(data_ep->wMaxPacketSize),
885 cfg->as_terminals[as_idx]);
886 }
887
888 /* Skip interfaces without explicit feedback endpoint */
889 feedback_ep = get_as_feedback_ep(c_data, as_idx);
890 if (feedback_ep == NULL) {
891 continue;
892 }
893
894 /* We didn't get feedback write request callback yet, skip it
895 * for now to allow faster recovery (i.e. reduce workload to be
896 * done during this frame).
897 */
898 if (ctx->fb_queued & ctx->fb_double & BIT(as_idx)) {
899 continue;
900 }
901
902 /* Only send feedback if host has enabled alternate interface */
903 if (!atomic_test_bit(&ctx->as_active, as_idx)) {
904 continue;
905 }
906
907 /* Make feedback available on every frame (value "sent" in
908 * previous SOF is "gone" even if USB host did not attempt to
909 * read it).
910 */
911 write_explicit_feedback(c_data, feedback_ep->bEndpointAddress,
912 cfg->as_terminals[as_idx]);
913 }
914 }
915
uac2_get_desc(struct usbd_class_data * const c_data,const enum usbd_speed speed)916 static void *uac2_get_desc(struct usbd_class_data *const c_data,
917 const enum usbd_speed speed)
918 {
919 struct device *dev = usbd_class_get_private(c_data);
920 const struct uac2_cfg *cfg = dev->config;
921
922 if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
923 return cfg->hs_descriptors;
924 }
925
926 return cfg->fs_descriptors;
927 }
928
uac2_init(struct usbd_class_data * const c_data)929 static int uac2_init(struct usbd_class_data *const c_data)
930 {
931 const struct device *dev = usbd_class_get_private(c_data);
932 struct uac2_ctx *ctx = dev->data;
933
934 if (ctx->ops == NULL) {
935 LOG_ERR("Application did not register UAC2 ops");
936 return -EINVAL;
937 }
938
939 return 0;
940 }
941
942 struct usbd_class_api uac2_api = {
943 .update = uac2_update,
944 .control_to_dev = uac2_control_to_dev,
945 .control_to_host = uac2_control_to_host,
946 .request = uac2_request,
947 .sof = uac2_sof,
948 .get_desc = uac2_get_desc,
949 .init = uac2_init,
950 };
951
952 #define DEFINE_ENTITY_TYPES(node) \
953 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \
954 ENTITY_TYPE_CLOCK_SOURCE \
955 )) \
956 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_input_terminal), ( \
957 ENTITY_TYPE_INPUT_TERMINAL \
958 )) \
959 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_output_terminal), ( \
960 ENTITY_TYPE_OUTPUT_TERMINAL \
961 )) \
962 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
963 ENTITY_TYPE_INVALID \
964 )) \
965 , /* Comma here causes unknown types to fail at compile time */
966 #define DEFINE_AS_EP_INDEXES(node) \
967 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
968 COND_CODE_1(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), \
969 (UAC2_DESCRIPTOR_AS_DATA_EP_INDEX(node),), (0,)) \
970 ))
971 #define DEFINE_AS_FB_INDEXES(node) \
972 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
973 COND_CODE_1(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), \
974 (UAC2_DESCRIPTOR_AS_FEEDBACK_EP_INDEX(node),), (0,)) \
975 ))
976 #define DEFINE_AS_TERMINALS(node) \
977 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
978 ENTITY_ID(DT_PROP(node, linked_terminal)), \
979 ))
980
981 #define FREQUENCY_TABLE_NAME(node, i) \
982 UTIL_CAT(frequencies_##i##_, ENTITY_ID(node))
983 #define DEFINE_CLOCK_SOURCES(node, i) \
984 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \
985 static const uint32_t FREQUENCY_TABLE_NAME(node, i)[] = \
986 DT_PROP(node, sampling_frequencies); \
987 ))
988
989 #define DEFINE_LOOKUP_TABLES(i) \
990 static const entity_type_t entity_types_##i[] = { \
991 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_ENTITY_TYPES) \
992 }; \
993 static const uint16_t ep_indexes_##i[] = { \
994 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_AS_EP_INDEXES) \
995 }; \
996 static const uint16_t fb_indexes_##i[] = { \
997 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_AS_FB_INDEXES) \
998 }; \
999 static const uint8_t as_terminals_##i[] = { \
1000 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, DEFINE_AS_TERMINALS) \
1001 }; \
1002 DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(i, DEFINE_CLOCK_SOURCES, i)
1003
1004 #define DEFINE_UAC2_CLASS_DATA(inst) \
1005 VALIDATE_INSTANCE(DT_DRV_INST(inst)) \
1006 static struct uac2_ctx uac2_ctx_##inst; \
1007 UAC2_DESCRIPTOR_ARRAYS(DT_DRV_INST(inst)) \
1008 IF_ENABLED(UAC2_ALLOWED_AT_FULL_SPEED(DT_DRV_INST(inst)), ( \
1009 static const struct usb_desc_header *uac2_fs_desc_##inst[] = \
1010 UAC2_FS_DESCRIPTOR_PTRS_ARRAY(DT_DRV_INST(inst)); \
1011 )) \
1012 IF_ENABLED(UAC2_ALLOWED_AT_HIGH_SPEED(DT_DRV_INST(inst)), ( \
1013 static const struct usb_desc_header *uac2_hs_desc_##inst[] = \
1014 UAC2_HS_DESCRIPTOR_PTRS_ARRAY(DT_DRV_INST(inst)); \
1015 )) \
1016 USBD_DEFINE_CLASS(uac2_##inst, &uac2_api, \
1017 (void *)DEVICE_DT_GET(DT_DRV_INST(inst)), NULL); \
1018 DEFINE_LOOKUP_TABLES(inst) \
1019 static const struct uac2_cfg uac2_cfg_##inst = { \
1020 .c_data = &uac2_##inst, \
1021 COND_CODE_1(UAC2_ALLOWED_AT_FULL_SPEED(DT_DRV_INST(inst)), \
1022 (.fs_descriptors = uac2_fs_desc_##inst,), \
1023 (.fs_descriptors = NULL,) \
1024 ) \
1025 COND_CODE_1(UAC2_ALLOWED_AT_HIGH_SPEED(DT_DRV_INST(inst)), \
1026 (.hs_descriptors = uac2_hs_desc_##inst,), \
1027 (.hs_descriptors = NULL,) \
1028 ) \
1029 .entity_types = entity_types_##inst, \
1030 .ep_indexes = ep_indexes_##inst, \
1031 .fb_indexes = fb_indexes_##inst, \
1032 .as_terminals = as_terminals_##inst, \
1033 .num_ifaces = ARRAY_SIZE(ep_indexes_##inst), \
1034 .num_entities = ARRAY_SIZE(entity_types_##inst), \
1035 }; \
1036 BUILD_ASSERT(ARRAY_SIZE(ep_indexes_##inst) <= 32, \
1037 "UAC2 implementation supports up to 32 AS interfaces"); \
1038 BUILD_ASSERT(ARRAY_SIZE(entity_types_##inst) <= 255, \
1039 "UAC2 supports up to 255 entities"); \
1040 DEVICE_DT_DEFINE(DT_DRV_INST(inst), NULL, NULL, \
1041 &uac2_ctx_##inst, &uac2_cfg_##inst, \
1042 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
1043 NULL);
DT_INST_FOREACH_STATUS_OKAY(DEFINE_UAC2_CLASS_DATA)1044 DT_INST_FOREACH_STATUS_OKAY(DEFINE_UAC2_CLASS_DATA)
1045
1046 static size_t clock_frequencies(struct usbd_class_data *const c_data,
1047 const uint8_t id, const uint32_t **frequencies)
1048 {
1049 const struct device *dev = usbd_class_get_private(c_data);
1050 size_t count;
1051
1052 #define GET_FREQUENCY_TABLE(node, i) \
1053 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \
1054 } else if (id == ENTITY_ID(node)) { \
1055 *frequencies = FREQUENCY_TABLE_NAME(node, i); \
1056 count = ARRAY_SIZE(FREQUENCY_TABLE_NAME(node, i)); \
1057 ))
1058
1059 if (0) {
1060 #define SELECT_FREQUENCY_TABLE(i) \
1061 } else if (dev == DEVICE_DT_GET(DT_DRV_INST(i))) { \
1062 if (0) { \
1063 DT_INST_FOREACH_CHILD_VARGS(i, GET_FREQUENCY_TABLE, i) \
1064 } else { \
1065 *frequencies = NULL; \
1066 count = 0; \
1067 }
1068 DT_INST_FOREACH_STATUS_OKAY(SELECT_FREQUENCY_TABLE)
1069 } else {
1070 *frequencies = NULL;
1071 count = 0;
1072 }
1073
1074 return count;
1075 }
1076