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