arduino-audio-tools
USBDeviceAudioAPI.h
1 #pragma once
2 
3 #include "class/audio/audio.h"
4 #include "common/tusb_mcu.h"
5 #include "common/tusb_verify.h"
6 #include "device/usbd.h"
7 #include "device/usbd_pvt.h"
8 #include "osal/osal.h"
9 #include "tusb.h"
10 #include "tusb_option.h"
11 #include "vector"
12 
13 #undef OUT_SW_BUF_MEM_SECTION
14 #undef CFG_TUSB_MEM_ALIGN
15 #define OUT_SW_BUF_MEM_SECTION
16 #define CFG_TUSB_MEM_ALIGN
17 
18 class USBDeviceAudio;
19 
20 enum {
21  AUDIO_FEEDBACK_METHOD_DISABLED,
22  AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
23  AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
24  AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only
25  AUDIO_FEEDBACK_METHOD_FIFO_COUNT
26 };
27 
29  uint8_t method;
30  uint32_t sample_freq; // sample frequency in Hz
31 
32  union {
33  struct {
34  uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to
35  // which sample clock is based on
36  } frequency;
37  };
38 };
39 
44  public:
45  int rh_port = 0;
46  uint8_t channels = 2;
47  uint32_t sample_rate = 48000;
48  uint8_t bits_per_sample = 16;
49  bool enable_feedback_ep = true;
50  bool enable_interrupt_ep = true;
51  bool enable_feedback_forward_correction = false;
52  bool enable_feedback_interval_isr = false;
53  bool enable_ep_in_flow_control = true;
54  bool enable_linear_buffer_tx = true;
55  bool enable_linear_buffer_rx = true;
56  bool enable_fifo_mutex = CFG_FIFO_MUTEX;
57  int func_n_as_int = 1;
58  int func_ctl_buffer_size = 0;
59  int func_ep_in_sw_buffer_size = 0;
60  int func_ep_out_sw_buffer_size = 0;
61  int func_ep_in_size_max = 0; // CFG_TUD_AUDIO_EP_SZ_IN
62  int func_ep_out_size_max = 0; // CFG_TUD_AUDIO_EP_SZ_OUT
63  size_t (*p_write_callback)(const uint8_t *data, size_t len,
64  USBDeviceAudio &ref) = nullptr;
65  size_t (*p_read_callback)(uint8_t *data, size_t len,
66  USBDeviceAudio &ref) = nullptr;
67 
68  bool is_ep_out() { return p_write_callback != nullptr; }
69  bool is_ep_in() { return p_read_callback != nullptr; };
70 
71  // setup (missing) default values
72  void begin() {
73  if (func_ctl_buffer_size == 0) func_ctl_buffer_size = 64;
74  if (func_ep_in_size_max == 0)
75  func_ep_in_size_max =
76  TUD_AUDIO_EP_SIZE(sample_rate, bits_per_sample / 8, channels);
77  if (func_ep_out_size_max == 0)
78  func_ep_out_size_max =
79  TUD_AUDIO_EP_SIZE(sample_rate, bits_per_sample / 8, channels);
80  if (func_ep_out_size_max == 0)
81  func_ep_in_sw_buffer_size =
82  (TUD_OPT_HIGH_SPEED ? 32 : 4) *
83  func_ep_in_size_max; // Example write FIFO every 1ms, so it should be
84  // 8 times larger for HS device
85  if (func_ep_out_sw_buffer_size == 0)
86  func_ep_out_sw_buffer_size =
87  (TUD_OPT_HIGH_SPEED ? 32 : 4) *
88  func_ep_out_size_max; // Example write FIFO every 1ms, so it should
89  // be 8 times larger for HS device
90  }
91  void clear() {
92  func_ctl_buffer_size = 0;
93  func_ep_in_size_max = 0;
94  func_ep_out_size_max = 0;
95  func_ep_in_sw_buffer_size = 0;
96  func_ep_out_sw_buffer_size = 0;
97  }
98 };
99 
100 /***
101  * @brief Basic TinyUSB Audio User Callbacks
102  */
103 class USBAudioCB {
104  public:
105  USBAudioCB() = default;
106  virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
107  uint16_t bufsize) = 0;
108 
109  virtual size_t getInterfaceDescriptorLength(uint8_t itfnum) = 0;
110 
111  // Invoked when set interface is called, typically on start/stop streaming or
112  // format change
113  virtual bool set_itf_cb(uint8_t rhport,
114  tusb_control_request_t const *p_request) = 0;
115 
116  // Invoked when audio class specific set request received for an EP
117  virtual bool set_req_ep_cb(uint8_t rhport,
118  tusb_control_request_t const *p_request,
119  uint8_t *pBuff) = 0;
120 
121  // Invoked when audio class specific set request received for an interface
122  virtual bool set_req_itf_cb(uint8_t rhport,
123  tusb_control_request_t const *p_request,
124  uint8_t *pBuff) = 0;
125 
126  // Invoked when audio class specific set request received for an entity
127  virtual bool set_req_entity_cb(uint8_t rhport,
128  tusb_control_request_t const *p_request,
129  uint8_t *pBuff) = 0;
130  // Invoked when audio class specific get request received for an EP
131  virtual bool get_req_ep_cb(uint8_t rhport,
132  tusb_control_request_t const *p_request) = 0;
133 
134  // Invoked when audio class specific get request received for an interface
135  virtual bool get_req_itf_cb(uint8_t rhport,
136  tusb_control_request_t const *p_request) = 0;
137 
138  // Invoked when audio class specific get request received for an entity
139  virtual bool get_req_entity_cb(uint8_t rhport,
140  tusb_control_request_t const *p_request) = 0;
141  virtual bool tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in,
142  uint8_t cur_alt_setting) = 0;
143 
144  virtual bool tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied,
145  uint8_t itf, uint8_t ep_in,
146  uint8_t cur_alt_setting) = 0;
147 
148  virtual bool rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received,
149  uint8_t func_id, uint8_t ep_out,
150  uint8_t cur_alt_setting) = 0;
151  virtual bool rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received,
152  uint8_t func_id, uint8_t ep_out,
153  uint8_t cur_alt_setting) = 0;
154 
155  virtual bool set_itf_close_EP_cb(uint8_t rhport,
156  tusb_control_request_t const *p_request) = 0;
157 
158  // for speaker
159  virtual void feedback_params_cb(uint8_t func_id, uint8_t alt_itf,
160  audio_feedback_params_t *feedback_param) = 0;
161 
162  virtual void int_done_cb(uint8_t rhport) {};
163  virtual void fb_done_cb(uint8_t func_id) {};
164  virtual void feedback_interval_isr(uint8_t func_id, uint32_t frame_number,
165  uint8_t interval_shift) {}
166 
167  virtual uint8_t allocInterface(uint8_t count = 1) = 0;
168  virtual uint8_t allocEndpoint(uint8_t in) = 0;
169 
170  int func_id = 0;
171 };
172 
173 /***
174  * @brief Baisc TinyUSB Audio Device Driver as C++ class which does not rely on
175  * preprocesser defines!.
176  */
178  public:
179  bool tud_audio_n_mounted(uint8_t func_id) {
180  TU_VERIFY(func_id < cfg.func_n_as_int);
181  audiod_function_t *audio = &_audiod_fct[func_id];
182 
183  return audio->mounted;
184  }
185 
186  //--------------------------------------------------------------------+
187  // READ API
188  //--------------------------------------------------------------------+
189 
190  uint16_t tud_audio_n_available(uint8_t func_id) {
191  TU_VERIFY(func_id < cfg.func_n_as_int &&
192  _audiod_fct[func_id].p_desc != NULL);
193  return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff);
194  }
195 
196  uint16_t tud_audio_n_read(uint8_t func_id, void *buffer, uint16_t bufsize) {
197  TU_VERIFY(func_id < cfg.func_n_as_int &&
198  _audiod_fct[func_id].p_desc != NULL);
199  return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize);
200  }
201 
202  bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) {
203  TU_VERIFY(func_id < cfg.func_n_as_int &&
204  _audiod_fct[func_id].p_desc != NULL);
205  return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff);
206  }
207 
208  tu_fifo_t *tud_audio_n_get_ep_out_ff(uint8_t func_id) {
209  if (func_id < cfg.func_n_as_int && _audiod_fct[func_id].p_desc != NULL)
210  return &_audiod_fct[func_id].ep_out_ff;
211  return NULL;
212  }
213 
214  //--------------------------------------------------------------------+
215  // WRITE API
216  //--------------------------------------------------------------------+
217 
231  uint16_t tud_audio_n_write(uint8_t func_id, const void *data, uint16_t len) {
232  TU_VERIFY(func_id < cfg.func_n_as_int &&
233  _audiod_fct[func_id].p_desc != NULL);
234  return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len);
235  }
236 
237  bool tud_audio_n_clear_ep_in_ff(
238  uint8_t func_id) // Delete all content in the EP IN FIFO
239  {
240  TU_VERIFY(func_id < cfg.func_n_as_int &&
241  _audiod_fct[func_id].p_desc != NULL);
242  return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff);
243  }
244 
245  tu_fifo_t *tud_audio_n_get_ep_in_ff(uint8_t func_id) {
246  if (func_id < cfg.func_n_as_int && _audiod_fct[func_id].p_desc != NULL)
247  return &_audiod_fct[func_id].ep_in_ff;
248  return NULL;
249  }
250 
251  // If no interrupt transmit is pending bytes get written into buffer and a
252  // transmit is scheduled - once transmit completed tud_audio_int_done_cb() is
253  // called in inform user
254  bool tud_audio_int_n_write(uint8_t func_id,
255  const audio_interrupt_data_t *data) {
256  TU_VERIFY(func_id < cfg.func_n_as_int &&
257  _audiod_fct[func_id].p_desc != NULL);
258 
259  TU_VERIFY(_audiod_fct[func_id].ep_int != 0);
260 
261  // We write directly into the EP's buffer - abort if previous transfer not
262  // complete
263  TU_VERIFY(usbd_edpt_claim(_audiod_fct[func_id].rhport,
264  _audiod_fct[func_id].ep_int));
265 
266  // Check length
267  if (tu_memcpy_s(_audiod_fct[func_id].ep_int_buf,
268  sizeof(_audiod_fct[func_id].ep_int_buf), data,
269  sizeof(audio_interrupt_data_t)) == 0) {
270  // Schedule transmit
271  TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport,
272  _audiod_fct[func_id].ep_int,
273  _audiod_fct[func_id].ep_int_buf,
274  sizeof(_audiod_fct[func_id].ep_int_buf)),
275  0);
276  } else {
277  // Release endpoint since we don't make any transfer
278  usbd_edpt_release(_audiod_fct[func_id].rhport,
279  _audiod_fct[func_id].ep_int);
280  }
281 
282  return true;
283  }
284 
285  //--------------------------------------------------------------------+
286  // USBD Driver API
287  //--------------------------------------------------------------------+
288  void begin(USBAudioCB *cb, USBAudioConfig config) {
289  p_cb = cb;
290  cfg = config;
291  cfg.begin();
292  }
293 
294  void audiod_init() {
295  if (p_cb == nullptr) return;
296  _audiod_fct.resize(cfg.func_n_as_int);
297  ctrl_buf_1.resize(cfg.func_ctl_buffer_size);
298  alt_setting_1.resize(cfg.func_n_as_int);
299 
300  if (cfg.is_ep_in()) {
301  if (cfg.enable_linear_buffer_rx)
302  lin_buf_in_1.resize(cfg.func_ep_in_size_max);
303  audio_ep_in_sw_buf_1.resize(cfg.func_ep_in_sw_buffer_size);
304  }
305 
306  if (cfg.is_ep_out()) {
307  if (cfg.enable_linear_buffer_tx)
308  audio_ep_out_sw_buf_1.resize(cfg.func_ep_out_sw_buffer_size);
309  lin_buf_out_1.resize(cfg.func_ep_out_sw_buffer_size);
310  }
311 
312  audiod_function_t *audio = &_audiod_fct[0];
313 
314  audio->ctrl_buf = ctrl_buf_1.data();
315  audio->ctrl_buf_sz = cfg.func_ctl_buffer_size;
316  audio->alt_setting = alt_setting_1.data();
317 
318  // Initialize IN EP FIFO if required
319  if (cfg.is_ep_in()) {
320  tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1.data(),
321  cfg.func_ep_in_sw_buffer_size, 1, true);
322  if (cfg.enable_fifo_mutex)
323  tu_fifo_config_mutex(&audio->ep_in_ff,
324  osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL);
325  }
326  // cfg.is_ep_in() && !ENABLE_ENCODING
327 
328  // Initialize linear buffers
329  if (cfg.enable_linear_buffer_tx) audio->lin_buf_in = lin_buf_in_1.data();
330 
331  // Initialize OUT EP FIFO if required
332  if (cfg.is_ep_out()) {
333  tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1.data(),
334  cfg.func_ep_in_sw_buffer_size, 1, true);
335  if (cfg.enable_fifo_mutex)
336  tu_fifo_config_mutex(&audio->ep_out_ff, NULL,
337  osal_mutex_create(&ep_out_ff_mutex_rd_1));
338  }
339 
340  // Initialize linear buffers
341  if (cfg.enable_linear_buffer_rx) audio->lin_buf_out = lin_buf_out_1.data();
342  }
343 
344  bool audiod_deinit(void) { return true; }
345 
346  void audiod_reset(uint8_t rhport) {
347  (void)rhport;
348 
349  for (uint8_t i = 0; i < cfg.func_n_as_int; i++) {
350  audiod_function_t *audio = &_audiod_fct[i];
351  tu_memclr(audio, sizeof(audiod_function_t));
352 
353  if (cfg.is_ep_in()) tu_fifo_clear(&audio->ep_in_ff);
354 
355  if (cfg.is_ep_out()) tu_fifo_clear(&audio->ep_out_ff);
356  }
357  }
358 
359  uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc,
360  uint16_t max_len) {
361  (void)max_len;
362  if (p_cb == nullptr) return 0;
363 
364  int cls_tobe = TUSB_CLASS_AUDIO;
365  int cls_is = itf_desc->bInterfaceClass;
366 
367  // TU_VERIFY(TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass &&
368  // AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass);
369 
370  // // Verify version is correct - this check can be omitted
371  // TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2);
372 
373  // Verify interrupt control EP is enabled if demanded by descriptor
374  TU_ASSERT(itf_desc->bNumEndpoints <= 1); // 0 or 1 EPs are allowed
375  if (itf_desc->bNumEndpoints == 1) {
376  TU_ASSERT(cfg.enable_interrupt_ep);
377  }
378 
379  // Alternate setting MUST be zero - this check can be omitted
380  TU_VERIFY(itf_desc->bAlternateSetting == 0);
381 
382  // Find available audio driver interface
383  uint8_t i;
384  for (i = 0; i < cfg.func_n_as_int; i++) {
385  if (!_audiod_fct[i].p_desc) {
386  int len = p_cb->getInterfaceDescriptor(i, nullptr, 0);
387  _audiod_fct[i].desc_length = len;
388  descriptor.resize(len);
389  _audiod_fct[i].p_desc = descriptor.data();
390  p_cb->getInterfaceDescriptor(i, descriptor.data(), len);
391  _audiod_fct[i].rhport = rhport;
392 
393 #ifdef TUP_DCD_EDPT_ISO_ALLOC
394  {
395  uint8_t ep_in = 0;
396  uint16_t ep_in_size = 0;
397 
398  uint8_t ep_out = 0;
399  uint16_t ep_out_size = 0;
400 
401  uint8_t ep_fb = 0;
402  uint8_t const *p_desc = _audiod_fct[i].p_desc;
403  uint8_t const *p_desc_end =
404  p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
405  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
406  // strict-overflow warning
407  while (p_desc_end - p_desc > 0) {
408  if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
409  tusb_desc_endpoint_t const *desc_ep =
410  (tusb_desc_endpoint_t const *)p_desc;
411  if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
412  if (cfg.enable_feedback_ep) {
413  // Explicit feedback EP
414  if (desc_ep->bmAttributes.usage == 1) {
415  ep_fb = desc_ep->bEndpointAddress;
416  }
417  }
418  // Data EP
419  if (desc_ep->bmAttributes.usage == 0) {
420  if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
421  if (cfg.is_ep_in()) {
422  ep_in = desc_ep->bEndpointAddress;
423  ep_in_size =
424  TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
425  }
426  } else {
427  if (cfg.is_ep_out()) {
428  ep_out = desc_ep->bEndpointAddress;
429  ep_out_size =
430  TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
431  }
432  }
433  }
434  }
435  }
436 
437  p_desc = tu_desc_next(p_desc);
438  }
439 
440  if (cfg.is_ep_in() && ep_in) {
441  usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
442  }
443 
444 
445  if (cfg.is_ep_out() && ep_out) {
446  usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
447  }
448 
449  if (cfg.enable_feedback_ep) {
450  if (ep_fb) {
451  usbd_edpt_iso_alloc(rhport, ep_fb, 4);
452  }
453  }
454  }
455 
456 #endif // TUP_DCD_EDPT_ISO_ALLOC
457 
458  if (cfg.is_ep_in() && cfg.enable_ep_in_flow_control) {
459  uint8_t const *p_desc = _audiod_fct[i].p_desc;
460  uint8_t const *p_desc_end =
461  p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
462  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
463  // strict-overflow warning
464  while (p_desc_end - p_desc > 0) {
465  if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
466  tusb_desc_endpoint_t const *desc_ep =
467  (tusb_desc_endpoint_t const *)p_desc;
468  if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
469  if (desc_ep->bmAttributes.usage == 0) {
470  if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
471  _audiod_fct[i].interval_tx = desc_ep->bInterval;
472  }
473  }
474  }
475  } else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
476  tu_desc_subtype(p_desc) ==
477  AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
478  if (tu_unaligned_read16(p_desc + 4) ==
479  AUDIO_TERM_TYPE_USB_STREAMING) {
480  _audiod_fct[i].bclock_id_tx = p_desc[8];
481  }
482  }
483  p_desc = tu_desc_next(p_desc);
484  }
485  } // CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
486 
487  if (cfg.enable_interrupt_ep) {
488  uint8_t const *p_desc = _audiod_fct[i].p_desc;
489  uint8_t const *p_desc_end =
490  p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
491  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
492  // strict-overflow warning
493  while (p_desc_end - p_desc > 0) {
494  // For each endpoint
495  if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
496  tusb_desc_endpoint_t const *desc_ep =
497  (tusb_desc_endpoint_t const *)p_desc;
498  uint8_t const ep_addr = desc_ep->bEndpointAddress;
499  // If endpoint is input-direction and interrupt-type
500  if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
501  desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) {
502  // Store endpoint number and open endpoint
503  _audiod_fct[i].ep_int = ep_addr;
504  TU_ASSERT(usbd_edpt_open(_audiod_fct[i].rhport, desc_ep));
505  }
506  }
507  p_desc = tu_desc_next(p_desc);
508  }
509  }
510 
511  _audiod_fct[i].mounted = true;
512  break;
513  }
514  }
515 
516  // Verify we found a free one
517  TU_ASSERT(i < cfg.func_n_as_int);
518 
519  // This is all we need so far - the EPs are setup by a later set_interface
520  // request (as per UAC2 specification)
521  uint16_t drv_len =
522  _audiod_fct[i].desc_length -
523  TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB
524  // already handles the IAD descriptor
525 
526  return drv_len;
527  }
528 
529  // Handle class co
530  bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage,
531  tusb_control_request_t const *request) {
532  if (stage == CONTROL_STAGE_SETUP) {
533  return audiod_control_request(rhport, request);
534  } else if (stage == CONTROL_STAGE_DATA) {
535  return audiod_control_complete(rhport, request);
536  }
537 
538  return true;
539  }
540 
541  bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
542  uint32_t xferred_bytes) {
543  (void)result;
544  (void)xferred_bytes;
545 
546  // Search for interface belonging to given end point address and proceed
547  // as required
548  for (uint8_t func_id = 0; func_id < cfg.func_n_as_int; func_id++) {
549  audiod_function_t *audio = &_audiod_fct[func_id];
550 
551  if (cfg.enable_interrupt_ep) {
552  // Data transmission of control interrupt finished
553  if (audio->ep_int == ep_addr) {
554  // According to USB2 specification, maximum payload of interrupt EP
555  // is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes
556  // on high speed (but only if an alternate interface other than 0 is
557  // used
558  // - see specification p. 49) In case there is nothing to send we
559  // have to return a NAK - this is taken care of by PHY ??? In case
560  // of an erroneous transmission a retransmission is conducted - this
561  // is taken care of by PHY ???
562 
563  // I assume here, that things above are handled by PHY
564  // All transmission is done - what remains to do is to inform job
565  // was completed
566 
567  if (p_cb) p_cb->int_done_cb(rhport);
568  return true;
569  }
570  }
571  if (cfg.is_ep_in()) {
572  // Data transmission of audio packet finished
573  if (audio->ep_in == ep_addr && audio->alt_setting != 0) {
574  // USB 2.0, section 5.6.4, third paragraph, states "An isochronous
575  // endpoint must specify its required bus access period. However, an
576  // isochronous endpoint must be prepared to handle poll rates faster
577  // than the one specified." That paragraph goes on to say "An
578  // isochronous IN endpoint must return a zero-length packet whenever
579  // data is requested at a faster interval than the specified
580  // interval and data is not available." This can only be solved
581  // reliably if we load a ZLP after every IN transmission since we
582  // can not say if the host requests samples earlier than we
583  // declared! Once all samples are collected we overwrite the loaded
584  // ZLP.
585 
586  // Check if there is data to load into EPs buffer - if not load it
587  // with ZLP Be aware - we as a device are not able to know if the
588  // host polls for data with a faster rate as we stated this in the
589  // descriptors. Therefore we always have to put something into the
590  // EPs buffer. However, once we did that, there is no way of
591  // aborting this or replacing what we put into the buffer before!
592  // This is the only place where we can fill something into the EPs
593  // buffer!
594 
595  // Load new data
596  TU_VERIFY(audiod_tx_done_cb(rhport, audio));
597 
598  // Transmission of ZLP is done by audiod_tx_done_cb()
599  return true;
600  }
601  }
602 
603  if (cfg.is_ep_out()) {
604  // New audio packet received
605  if (audio->ep_out == ep_addr) {
606  TU_VERIFY(audiod_rx_done_cb(rhport, audio, (uint16_t)xferred_bytes));
607  return true;
608  }
609 
610  if (cfg.enable_feedback_ep) {
611  // Transmission of feedback EP finished
612  if (audio->ep_fb == ep_addr) {
613  if (p_cb) p_cb->fb_done_cb(func_id);
614 
615  // Schedule a transmit with the new value if EP is not busy
616  if (!usbd_edpt_busy(rhport, audio->ep_fb)) {
617  // Schedule next transmission - value is changed
618  // bytud_audio_n_fb_set() in the meantime or the old value gets
619  // sent
620  return audiod_fb_send(rhport, audio);
621  }
622  }
623  }
624  }
625  }
626 
627  return false;
628  }
629 
630  bool tud_audio_buffer_and_schedule_control_xfer(
631  uint8_t rhport, tusb_control_request_t const *p_request, void *data,
632  uint16_t len) {
633  // Handles only sending of data not receiving
634  if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false;
635 
636  // Get corresponding driver index
637  uint8_t func_id;
638  uint8_t itf = TU_U16_LOW(p_request->wIndex);
639 
640  // Conduct checks which depend on the recipient
641  switch (p_request->bmRequestType_bit.recipient) {
642  case TUSB_REQ_RCPT_INTERFACE: {
643  uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
644 
645  // Verify if entity is present
646  if (entityID != 0) {
647  // Find index of audio driver structure and verify entity really
648  // exists
649  TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
650  } else {
651  // Find index of audio driver structure and verify interface really
652  // exists
653  TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
654  }
655  } break;
656 
657  case TUSB_REQ_RCPT_ENDPOINT: {
658  uint8_t ep = TU_U16_LOW(p_request->wIndex);
659 
660  // Find index of audio driver structure and verify EP really exists
661  TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
662  } break;
663 
664  // Unknown/Unsupported recipient
665  default:
666  TU_LOG2(" Unsupported recipient: %d\r\n",
667  p_request->bmRequestType_bit.recipient);
668  TU_BREAKPOINT();
669  return false;
670  }
671 
672  // Crop length
673  if (len > _audiod_fct[func_id].ctrl_buf_sz)
674  len = _audiod_fct[func_id].ctrl_buf_sz;
675 
676  // Copy into buffer
677  TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf,
678  _audiod_fct[func_id].ctrl_buf_sz, data,
679  (size_t)len));
680 
681  if (cfg.is_ep_in() && cfg.enable_ep_in_flow_control) {
682  // Find data for sampling_frequency_control
683  if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
684  p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) {
685  uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
686  uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
687  if (_audiod_fct[func_id].bclock_id_tx == entityID &&
688  ctrlSel == AUDIO_CS_CTRL_SAM_FREQ &&
689  p_request->bRequest == AUDIO_CS_REQ_CUR) {
690  _audiod_fct[func_id].sample_rate_tx =
691  tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf);
692  }
693  }
694  }
695 
696  // Schedule transmit
697  return tud_control_xfer(rhport, p_request,
698  (void *)_audiod_fct[func_id].ctrl_buf, len);
699  }
700 
701  bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) {
702  TU_VERIFY(func_id < cfg.func_n_as_int &&
703  _audiod_fct[func_id].p_desc != NULL);
704 
705  // Format the feedback value
706  if (cfg.enable_feedback_forward_correction) {
707  if (TUSB_SPEED_FULL == tud_speed_get()) {
708  uint8_t *fb = (uint8_t *)&_audiod_fct[func_id].feedback.value;
709 
710  // For FS format is 10.14
711  *(fb++) = (feedback >> 2) & 0xFF;
712  *(fb++) = (feedback >> 10) & 0xFF;
713  *(fb++) = (feedback >> 18) & 0xFF;
714  // 4th byte is needed to work correctly with MS Windows
715  *fb = 0;
716  }
717  } else {
718  // Send value as-is, caller will choose the appropriate format
719  _audiod_fct[func_id].feedback.value = feedback;
720  }
721  // Schedule a transmit with the new value if EP is not busy - this
722  // triggers repetitive scheduling of the feedback value
723  if (!usbd_edpt_busy(_audiod_fct[func_id].rhport,
724  _audiod_fct[func_id].ep_fb)) {
725  return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]);
726  }
727 
728  return true;
729  }
730 
731  void audiod_sof_isr(uint8_t rhport, uint32_t frame_count) {
732  (void)rhport;
733  (void)frame_count;
734 
735  if (cfg.is_ep_out() && cfg.enable_feedback_ep) {
736  // Determine feedback value - The feedback method is described
737  // in 5.12.4.2 of the USB 2.0 spec Boiled down, the feedback value Ff =
738  // n_samples / (micro)frame. Since an accuracy of less than 1 Sample /
739  // second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames
740  // need to be measured, where K = 10 for full speed and K = 13 for high
741  // speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu
742  // clock frequency e.g. 100 MHz (or any other master clock whose clock
743  // count is available and locked to f_s) The update interval in the
744  // (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K
745  // - P), where P = min( ceil(log2(f_m / f_s)), K) feedback = n_cycles /
746  // n_frames * f_s / f_m in 16.16 format, where n_cycles are the number
747  // of main clock cycles within fb_n_frames
748 
749  // Iterate over audio functions and set feedback value
750  for (uint8_t i = 0; i < cfg.func_n_as_int; i++) {
751  audiod_function_t *audio = &_audiod_fct[i];
752 
753  if (audio->ep_fb != 0) {
754  // HS shift need to be adjusted since SOF event is generated for
755  // frame only
756  uint8_t const hs_adjust =
757  (TUSB_SPEED_HIGH == tud_speed_get()) ? 3 : 0;
758  uint32_t const interval =
759  1UL << (audio->feedback.frame_shift - hs_adjust);
760  if (0 == (frame_count & (interval - 1))) {
761  if (cfg.enable_feedback_interval_isr && p_cb)
762  p_cb->feedback_interval_isr(i, frame_count,
763  audio->feedback.frame_shift);
764  }
765  }
766  }
767  } // cfg.is_ep_out() && cfg.enable_feedback_ep
768  }
769 
770  USBAudioConfig &config() { return cfg; }
771 
772  protected:
773  USBAudioCB *p_cb = nullptr;
774  USBAudioConfig cfg;
775  // Linear buffer TX in case:
776  // - target MCU is not capable of handling a ring buffer FIFO e.g. no
777  // hardware buffer is available or driver is would need to be changed
778  // dramatically OR
779  // - the software encoding is used - in this case the linear buffers serve
780  // as a target memory where logical channels are encoded into
781  std::vector<CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
782  lin_buf_in_1; //[cfg.func_ep_in_size_max];
783 
784  std::vector<OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
785  audio_ep_in_sw_buf_1; //[cfg.func_ep_in_sw_buffer_size];
786 
787  std::vector<OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
788  audio_ep_out_sw_buf_1; //[cfg.func_ep_in_sw_buffer_size];
789 
790  // Linear buffer RX in case:
791  // - target MCU is not capable of handling a ring buffer FIFO e.g. no
792  // hardware buffer is available or driver is would need to be changed
793  // dramatically OR
794  // - the software encoding is used - in this case the linear buffers serve
795  // as a target memory where logical channels are encoded into
796  std::vector<CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
797  lin_buf_out_1; //[FUNC_1_EP_OUT_SZ_MAX];
798 
799  // Control buffers
800  std::vector<CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
801  ctrl_buf_1; //[cfg.func_ctl_buffer_size];
802 
803  // Active alternate setting of interfaces
804  std::vector<uint8_t> alt_setting_1; //[cfg.func_n_as_int];
805 
806  // buffer for descriptor
807  std::vector<uint8_t> descriptor;
808 
809  // EP IN software buffers and mutexes
810  // TUP_DCD_EDPT_ISO_ALLOC[cfg.func_ep_in_sw_buffer_size];
811  osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB
812  // driver reads from FIFO
813 
814  osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only
815  // USB driver writes into FIFO
816 
819  memset(this,0, sizeof(audiod_function_t));
820  }
821  uint8_t n_bytes_per_sample_tx;
822  uint8_t n_channels_tx;
823  uint8_t format_type_tx = AUDIO_FORMAT_TYPE_I;
824 
825  uint8_t rhport;
826  uint8_t const
827  *p_desc = nullptr; // Pointer pointing to Standard AC Interface
828  // Descriptor(4.7.1)
829  // - Audio Control descriptor defining audio function
830 
831  uint8_t ep_in; // TX audio data EP.
832  uint16_t ep_in_sz; // Current size of TX EP
833  uint8_t
834  ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor
835  // (4.9.1) belonging to output terminal to which
836  // this EP belongs - 0 is invalid (this fits to
837  // UAC2 specification since AS interfaces can not
838  // have interface number equal to zero)
839  uint8_t ep_out; // Incoming (into uC) audio data EP.
840  uint16_t ep_out_sz; // Current size of RX EP
841  uint8_t
842  ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor
843  // (4.9.1) belonging to input terminal to which
844  // this EP belongs - 0 is invalid (this fits to
845  // UAC2 specification since AS interfaces can not
846  // have interface number equal to zero)
847 
848  uint8_t ep_fb; // Feedback EP.
849 
850  uint8_t ep_int; // Audio control interrupt EP.
851 
852  bool mounted; // Device opened
853 
854  /*------------- From this point, data is not cleared by bus reset
855  * -------------*/
856 
857  uint16_t desc_length; // Length of audio function descriptor
858 
859  struct feedback {
860  CFG_TUSB_MEM_ALIGN uint32_t
861  value; // Feedback value for asynchronous mode (in 16.16 format).
862  uint32_t
863  min_value; // min value according to UAC2 FMT-2.0 section 2.3.1.1.
864  uint32_t
865  max_value; // max value according to UAC2 FMT-2.0 section 2.3.1.1.
866 
867  uint8_t
868  frame_shift; // bInterval-1 in unit of frame (FS), micro-frame (HS)
869  uint8_t compute_method;
870 
871  union {
872  uint8_t power_of_2; // pre-computed power of 2 shift
873  float float_const; // pre-computed float constant
874 
875  struct {
876  uint32_t sample_freq;
877  uint32_t mclk_freq;
878  } fixed;
879 
880  } compute;
881 
882  } feedback;
883 
884  // Decoding parameters - parameters are set when alternate AS interface is
885  // set by host Coding is currently only supported for EP. Software coding
886  // corresponding to AS interfaces without EPs are not supported currently.
887  uint32_t sample_rate_tx;
888  uint16_t packet_sz_tx[3];
889  uint8_t bclock_id_tx;
890  uint8_t interval_tx;
891 
892  // Encoding parameters - parameters are set when alternate AS interface is
893  // set by host
894 
895  // Buffer for control requests
896  uint8_t *ctrl_buf;
897  uint8_t ctrl_buf_sz;
898 
899  // Current active alternate settings
900  uint8_t *alt_setting; // We need to save the current alternate setting
901  // this way, because it is possible that there are
902  // AS interfaces which do not have an EP!
903 
904  // EP Transfer buffers and FIFOs
905  tu_fifo_t ep_out_ff;
906  tu_fifo_t ep_in_ff;
907 
908  // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2
909  // specification (p. 74)
910  CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6];
911 
912  // Linear buffer in case target MCU is not capable of handling a ring
913  // buffer FIFO e.g. no hardware buffer is available or driver is would
914  // need to be changed dramatically OR the support FIFOs are used
915  uint8_t *lin_buf_out;
916  uint8_t *lin_buf_in;
917  };
918 
919  //--------------------------------------------------------------------+
920  // INTERNAL OBJECT & FUNCTION DECLARATION
921  //--------------------------------------------------------------------+
922  std::vector<CFG_TUD_MEM_SECTION audiod_function_t> _audiod_fct;
923 
924  // No security checks here - internal function only which should always
925  // succeed
926  uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio) {
927  for (uint8_t cnt = 0; cnt < cfg.func_n_as_int; cnt++) {
928  if (&_audiod_fct[cnt] == audio) return cnt;
929  }
930  return 0;
931  }
932 
933  inline uint8_t tu_desc_subtype(void const *desc) {
934  return ((uint8_t const *)desc)[2];
935  }
936 
937  bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio,
938  uint16_t n_bytes_received) {
939  uint8_t idxItf = 0;
940  uint8_t const *dummy2;
941  uint8_t idx_audio_fct = 0;
942 
943  if (p_cb) {
944  idx_audio_fct = audiod_get_audio_fct_idx(audio);
945  TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio,
946  &idxItf, &dummy2));
947  }
948 
949  // Call a weak callback here - a possibility for user to get informed an
950  // audio packet was received and data gets now loaded into EP FIFO (or
951  // decoded into support RX software FIFO)
952  if (p_cb) {
953  TU_VERIFY(p_cb->rx_done_pre_read_cb(rhport, n_bytes_received,
954  idx_audio_fct, audio->ep_out,
955  audio->alt_setting[idxItf]));
956  }
957 
958  if (cfg.enable_linear_buffer_rx) {
959  // Data currently is in linear buffer, copy into EP OUT FIFO
960  TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out,
961  n_bytes_received));
962 
963  // Schedule for next receive
964  TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out,
965  audio->ep_out_sz),
966  false);
967  } else {
968  // Data is already placed in EP FIFO, schedule for next receive
969  TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff,
970  audio->ep_out_sz),
971  false);
972  }
973 
974  // Call a weak callback here - a possibility for user to get informed
975  // decoding was completed
976  if (p_cb) {
977  TU_VERIFY(p_cb->rx_done_post_read_cb(rhport, n_bytes_received,
978  idx_audio_fct, audio->ep_out,
979  audio->alt_setting[idxItf]));
980  }
981 
982  return true;
983  }
984 
985  // This function is called once a transmit of an audio packet was
986  // successfully completed. Here, we encode samples and place it in IN EP's
987  // buffer for next transmission. If you prefer your own (more efficient)
988  // implementation suiting your purpose set ENABLE_ENCODING = 0 and use
989  // tud_audio_n_write.
990 
991  // n_bytes_copied - Informs caller how many bytes were loaded. In case
992  // n_bytes_copied = 0, a ZLP is scheduled to inform host no data is
993  // available for current frame.
994 
995  bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) {
996  uint8_t idxItf;
997  uint8_t const *dummy2;
998 
999  uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio);
1000  TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio,
1001  &idxItf, &dummy2));
1002 
1003  // Only send something if current alternate interface is not 0 as in this
1004  // case nothing is to be sent due to UAC2 specifications
1005  if (audio->alt_setting[idxItf] == 0) return false;
1006 
1007  // Call a weak callback here - a possibility for user to get informed
1008  // former TX was completed and data gets now loaded into EP in buffer (in
1009  // case FIFOs are used) or if no FIFOs are used the user may use this call
1010  // back to load its data into the EP IN buffer by use of
1011  // tud_audio_n_write_ep_in_buffer().
1012  if (p_cb)
1013  TU_VERIFY(p_cb->tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in,
1014  audio->alt_setting[idxItf]));
1015 
1016  // Send everything in ISO EP FIFO
1017  uint16_t n_bytes_tx;
1018 
1019  // If support FIFOs are used, encode and schedule transmit
1020  // No support FIFOs, if no linear buffer required schedule transmit, else
1021  // put data into linear buffer and schedule
1022  if (cfg.enable_ep_in_flow_control) {
1023  // packet_sz_tx is based on total packet size, here we want size for
1024  // each support buffer.
1025  n_bytes_tx = audiod_tx_packet_size(
1026  audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff),
1027  audio->ep_in_ff.depth, audio->ep_in_sz);
1028  } else {
1029  n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff),
1030  audio->ep_in_sz); // Limit up to max packet size,
1031  // more can not be done for ISO
1032  }
1033  if (cfg.enable_linear_buffer_tx) {
1034  tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx);
1035  TU_VERIFY(
1036  usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx));
1037  } else {
1038  // Send everything in ISO EP FIFO
1039  TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff,
1040  n_bytes_tx));
1041  }
1042 
1043  // Call a weak callback here - a possibility for user to get informed
1044  // former TX was completed and how many bytes were loaded for the next
1045  // frame
1046  if (p_cb)
1047  TU_VERIFY(p_cb->tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct,
1048  audio->ep_in,
1049  audio->alt_setting[idxItf]));
1050  return true;
1051  }
1052 
1053  // This function is called once a transmit of a feedback packet was
1054  // successfully completed. Here, we get the next feedback value to be sent
1055 
1056  inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) {
1057  return usbd_edpt_xfer(rhport, audio->ep_fb,
1058  (uint8_t *)&audio->feedback.value, 4);
1059  }
1060 
1061  bool audiod_set_interface(uint8_t rhport,
1062  tusb_control_request_t const *p_request) {
1063  (void)rhport;
1064 
1065  // Here we need to do the following:
1066 
1067  // 1. Find the audio driver assigned to the given interface to be set
1068  // Since one audio driver interface has to be able to cover an unknown
1069  // number of interfaces (AC, AS + its alternate settings), the best memory
1070  // efficient way to solve this is to always search through the
1071  // descriptors. The audio driver is mapped to an audio function by a
1072  // reference pointer to the corresponding AC interface of this audio
1073  // function which serves as a starting point for searching
1074 
1075  // 2. Close EPs which are currently open
1076  // To do so it is not necessary to know the current active alternate
1077  // interface since we already save the current EP addresses - we simply
1078  // close them
1079 
1080  // 3. Open new EP
1081 
1082  uint8_t const itf = tu_u16_low(p_request->wIndex);
1083  uint8_t const alt = tu_u16_low(p_request->wValue);
1084 
1085  TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt);
1086 
1087  // Find index of audio streaming interface and index of interface
1088  uint8_t func_id, idxItf;
1089  uint8_t const *p_desc;
1090  TU_VERIFY(
1091  audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc));
1092 
1093  audiod_function_t *audio = &_audiod_fct[func_id];
1094 
1095  // Look if there is an EP to be closed - for this driver, there are only 3
1096  // possible EPs which may be closed (only AS related EPs can be closed, AC
1097  // EP (if present) is always open)
1098  if (cfg.is_ep_in()) {
1099  if (audio->ep_in_as_intf_num == itf) {
1100  audio->ep_in_as_intf_num = 0;
1101 #ifndef TUP_DCD_EDPT_ISO_ALLOC
1102  usbd_edpt_close(rhport, audio->ep_in);
1103 #endif
1104 
1105  // Clear FIFOs, since data is no longer valid
1106  tu_fifo_clear(&audio->ep_in_ff);
1107 
1108  // Invoke callback - can be used to stop data sampling
1109  if (p_cb) TU_VERIFY(p_cb->set_itf_close_EP_cb(rhport, p_request));
1110 
1111  audio->ep_in = 0; // Necessary?
1112 
1113  if (cfg.enable_ep_in_flow_control) {
1114  audio->packet_sz_tx[0] = 0;
1115  audio->packet_sz_tx[1] = 0;
1116  audio->packet_sz_tx[2] = 0;
1117  }
1118  }
1119  }
1120 
1121  if (cfg.is_ep_out()) {
1122  if (audio->ep_out_as_intf_num == itf) {
1123  audio->ep_out_as_intf_num = 0;
1124 #ifndef TUP_DCD_EDPT_ISO_ALLOC
1125  usbd_edpt_close(rhport, audio->ep_out);
1126 #endif
1127 
1128  // Clear FIFOs, since data is no longer valid
1129  tu_fifo_clear(&audio->ep_out_ff);
1130  // Invoke callback - can be used to stop data sampling
1131  if (p_cb) TU_VERIFY(p_cb->set_itf_close_EP_cb(rhport, p_request));
1132 
1133  audio->ep_out = 0; // Necessary?
1134 
1135  // Close corresponding feedback EP
1136  if (cfg.enable_feedback_ep) {
1137 #ifndef TUP_DCD_EDPT_ISO_ALLOC
1138  usbd_edpt_close(rhport, audio->ep_fb);
1139 #endif
1140  audio->ep_fb = 0;
1141  tu_memclr(&audio->feedback, sizeof(audio->feedback));
1142  }
1143  }
1144  } // cfg.is_ep_out()
1145 
1146  // Save current alternative interface setting
1147  audio->alt_setting[idxItf] = alt;
1148 
1149  // Open new EP if necessary - EPs are only to be closed or opened for AS
1150  // interfaces - Look for AS interface with correct alternate interface Get
1151  // pointer at end
1152  uint8_t const *p_desc_end =
1153  audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1154 
1155  // p_desc starts at required interface with alternate setting zero
1156  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1157  // strict-overflow warning
1158  while (p_desc_end - p_desc > 0) {
1159  // Find correct interface
1160  if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1161  ((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber == itf &&
1162  ((tusb_desc_interface_t const *)p_desc)->bAlternateSetting == alt) {
1163  uint8_t const *p_desc_parse_for_params = p_desc;
1164  // From this point forward follow the EP descriptors associated to the
1165  // current alternate setting interface - Open EPs if necessary
1166  uint8_t foundEPs = 0,
1167  nEps = ((tusb_desc_interface_t const *)p_desc)->bNumEndpoints;
1168  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1169  // strict-overflow warning
1170  while (foundEPs < nEps && (p_desc_end - p_desc > 0)) {
1171  if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
1172  tusb_desc_endpoint_t const *desc_ep =
1173  (tusb_desc_endpoint_t const *)p_desc;
1174 #ifdef TUP_DCD_EDPT_ISO_ALLOC
1175  TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep));
1176 #else
1177  TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
1178 #endif
1179  uint8_t const ep_addr = desc_ep->bEndpointAddress;
1180 
1181  // TODO: We need to set EP non busy since this is not taken care
1182  // of right now in ep_close() - THIS IS A WORKAROUND!
1183  usbd_edpt_clear_stall(rhport, ep_addr);
1184 
1185  if (cfg.is_ep_in()) {
1186  if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1187  desc_ep->bmAttributes.usage ==
1188  0x00) // Check if usage is data EP
1189  {
1190  // Save address
1191  audio->ep_in = ep_addr;
1192  audio->ep_in_as_intf_num = itf;
1193  audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
1194 
1195  // If software encoding is enabled, parse for the
1196  // corresponding parameters - doing this here means only AS
1197  // interfaces with EPs get scanned for parameters
1198  if (cfg.enable_ep_in_flow_control)
1199  audiod_parse_for_AS_params(audio, p_desc_parse_for_params,
1200  p_desc_end, itf);
1201 
1202  // Reconfigure size of support FIFOs - this is necessary to
1203  // avoid samples to get split in case of a wrap
1204 
1205  // Schedule first transmit if alternate interface is not zero
1206  // i.e. streaming is disabled - in case no sample data is
1207  // available a ZLP is loaded It is necessary to trigger this
1208  // here since the refill is done with an RX FIFO empty
1209  // interrupt which can only trigger if something was in there
1210  TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id]));
1211  }
1212  } // cfg.is_ep_in()
1213 
1214  if (cfg.is_ep_out()) {
1215  if (tu_edpt_dir(ep_addr) ==
1216  TUSB_DIR_OUT) // Checking usage not necessary
1217  {
1218  // Save address
1219  audio->ep_out = ep_addr;
1220  audio->ep_out_as_intf_num = itf;
1221  audio->ep_out_sz = tu_edpt_packet_size(desc_ep);
1222 
1223  // Prepare for incoming data
1224  if (cfg.enable_linear_buffer_rx) {
1225  TU_VERIFY(
1226  usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out,
1227  audio->ep_out_sz),
1228  false);
1229  } else {
1230  TU_VERIFY(
1231  usbd_edpt_xfer_fifo(rhport, audio->ep_out,
1232  &audio->ep_out_ff, audio->ep_out_sz),
1233  false);
1234  }
1235  }
1236 
1237  if (cfg.enable_feedback_ep) {
1238  if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1239  desc_ep->bmAttributes.usage ==
1240  1) // Check if usage is explicit data feedback
1241  {
1242  audio->ep_fb = ep_addr;
1243  audio->feedback.frame_shift = desc_ep->bInterval - 1;
1244 
1245  // Enable SOF interrupt if callback is implemented
1246  if (cfg.enable_feedback_interval_isr)
1247  usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, true);
1248  }
1249  }
1250  } // cfg.is_ep_out()
1251 
1252  foundEPs += 1;
1253  }
1254  p_desc = tu_desc_next(p_desc);
1255  }
1256 
1257  TU_VERIFY(foundEPs == nEps);
1258 
1259  // Invoke one callback for a final set interface
1260  if (p_cb) TU_VERIFY(p_cb->set_itf_cb(rhport, p_request));
1261 
1262  if (cfg.enable_feedback_ep) {
1263  // Prepare feedback computation if callback is available
1264  if (p_cb) {
1265  audio_feedback_params_t fb_param;
1266 
1267  p_cb->feedback_params_cb(func_id, alt, &fb_param);
1268  audio->feedback.compute_method = fb_param.method;
1269 
1270  // Minimal/Maximum value in 16.16 format for full speed (1ms per
1271  // frame) or high speed (125 us per frame)
1272  uint32_t const frame_div =
1273  (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000;
1274  audio->feedback.min_value = (fb_param.sample_freq / frame_div - 1)
1275  << 16;
1276  audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1)
1277  << 16;
1278 
1279  switch (fb_param.method) {
1280  case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
1281  case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1282  case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1283  set_fb_params_freq(audio, fb_param.sample_freq,
1284  fb_param.frequency.mclk_freq);
1285  break;
1286 
1287  // nothing to do
1288  default:
1289  break;
1290  }
1291  }
1292  } // cfg.enable_feedback_ep
1293 
1294  // We are done - abort loop
1295  break;
1296  }
1297 
1298  // Moving forward
1299  p_desc = tu_desc_next(p_desc);
1300  }
1301 
1302  if (cfg.enable_feedback_ep) {
1303  // Disable SOF interrupt if no driver has any enabled feedback EP
1304  bool disable = true;
1305  for (uint8_t i = 0; i < cfg.func_n_as_int; i++) {
1306  if (_audiod_fct[i].ep_fb != 0) {
1307  disable = false;
1308  break;
1309  }
1310  }
1311  if (disable) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, false);
1312  }
1313 
1314  if (cfg.is_ep_in() && cfg.enable_ep_in_flow_control)
1315  audiod_calc_tx_packet_sz(audio);
1316 
1317  tud_control_status(rhport, p_request);
1318 
1319  return true;
1320  }
1321 
1322  // Invoked when class request DATA stage is finished.
1323  // return false to stall control EP (e.g Host send non-sense DATA)
1324  bool audiod_control_complete(uint8_t rhport,
1325  tusb_control_request_t const *p_request) {
1326  // Handle audio class specific set requests
1327  if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
1328  p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
1329  uint8_t func_id;
1330 
1331  switch (p_request->bmRequestType_bit.recipient) {
1332  case TUSB_REQ_RCPT_INTERFACE: {
1333  uint8_t itf = TU_U16_LOW(p_request->wIndex);
1334  uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1335 
1336  if (entityID != 0) {
1337  if (p_cb) {
1338  // Check if entity is present and get corresponding driver index
1339  TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1340 
1341  // Invoke callback
1342  return p_cb->set_req_entity_cb(rhport, p_request,
1343  _audiod_fct[func_id].ctrl_buf);
1344  } else {
1345  TU_LOG2(" No entity set request callback available!\r\n");
1346  return false; // In case no callback function is present or
1347  // request can not be conducted we stall it
1348  }
1349  } else {
1350  if (p_cb) {
1351  // Find index of audio driver structure and verify interface
1352  // really exists
1353  TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1354 
1355  // Invoke callback
1356  return p_cb->set_req_itf_cb(rhport, p_request,
1357  _audiod_fct[func_id].ctrl_buf);
1358  } else {
1359  TU_LOG2(" No interface set request callback available!\r\n");
1360  return false; // In case no callback function is present or
1361  // request can not be conducted we stall it
1362  }
1363  }
1364  } break;
1365 
1366  case TUSB_REQ_RCPT_ENDPOINT: {
1367  uint8_t ep = TU_U16_LOW(p_request->wIndex);
1368 
1369  if (p_cb) {
1370  // Check if entity is present and get corresponding driver index
1371  TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1372 
1373  // Invoke callback
1374  return p_cb->set_req_ep_cb(rhport, p_request,
1375  _audiod_fct[func_id].ctrl_buf);
1376  } else {
1377  TU_LOG2(" No EP set request callback available!\r\n");
1378  return false; // In case no callback function is present or
1379  // request can not be conducted we stall it
1380  }
1381  } break;
1382  // Unknown/Unsupported recipient
1383  default:
1384  TU_BREAKPOINT();
1385  return false;
1386  }
1387  }
1388  return true;
1389  }
1390 
1391  // return false to stall control endpoint (e.g unsupported request)
1392  bool audiod_control_request(uint8_t rhport,
1393  tusb_control_request_t const *p_request) {
1394  (void)rhport;
1395 
1396  // Handle standard requests - standard set requests usually have no data
1397  // stage so we also handle set requests here
1398  if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
1399  switch (p_request->bRequest) {
1400  case TUSB_REQ_GET_INTERFACE:
1401  return audiod_get_interface(rhport, p_request);
1402 
1403  case TUSB_REQ_SET_INTERFACE:
1404  return audiod_set_interface(rhport, p_request);
1405 
1406  case TUSB_REQ_CLEAR_FEATURE:
1407  return true;
1408 
1409  // Unknown/Unsupported request
1410  default:
1411  TU_BREAKPOINT();
1412  return false;
1413  }
1414  }
1415 
1416  // Handle class requests
1417  if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
1418  uint8_t itf = TU_U16_LOW(p_request->wIndex);
1419  uint8_t func_id;
1420 
1421  // Conduct checks which depend on the recipient
1422  switch (p_request->bmRequestType_bit.recipient) {
1423  case TUSB_REQ_RCPT_INTERFACE: {
1424  uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1425 
1426  // Verify if entity is present
1427  if (entityID != 0) {
1428  // Find index of audio driver structure and verify entity really
1429  // exists
1430  TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1431 
1432  // In case we got a get request invoke callback - callback needs
1433  // to answer as defined in UAC2 specification page 89 - 5.
1434  // Requests
1435  if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1436  if (p_cb) {
1437  return p_cb->get_req_entity_cb(rhport, p_request);
1438  } else {
1439  TU_LOG2(" No entity get request callback available!\r\n");
1440  return false; // Stall
1441  }
1442  }
1443  } else {
1444  // Find index of audio driver structure and verify interface
1445  // really exists
1446  TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1447 
1448  // In case we got a get request invoke callback - callback needs
1449  // to answer as defined in UAC2 specification page 89 - 5.
1450  // Requests
1451  if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1452  if (p_cb) {
1453  return p_cb->set_itf_cb(rhport, p_request);
1454  } else {
1455  TU_LOG2(" No interface get request callback available!\r\n");
1456  return false; // Stall
1457  }
1458  }
1459  }
1460  } break;
1461 
1462  case TUSB_REQ_RCPT_ENDPOINT: {
1463  uint8_t ep = TU_U16_LOW(p_request->wIndex);
1464 
1465  // Find index of audio driver structure and verify EP really exists
1466  TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1467 
1468  // In case we got a get request invoke callback - callback needs to
1469  // answer as defined in UAC2 specification page 89 - 5. Requests
1470  if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1471  if (p_cb) {
1472  return p_cb->get_req_ep_cb(rhport, p_request);
1473  } else {
1474  TU_LOG2(" No EP get request callback available!\r\n");
1475  return false; // Stall
1476  }
1477  }
1478  } break;
1479 
1480  // Unknown/Unsupported recipient
1481  default:
1482  TU_LOG2(" Unsupported recipient: %d\r\n",
1483  p_request->bmRequestType_bit.recipient);
1484  TU_BREAKPOINT();
1485  return false;
1486  }
1487 
1488  // If we end here, the received request is a set request - we schedule a
1489  // receive for the data stage and return true here. We handle the rest
1490  // later in audiod_control_complete() once the data stage was finished
1491  TU_VERIFY(tud_control_xfer(rhport, p_request,
1492  _audiod_fct[func_id].ctrl_buf,
1493  _audiod_fct[func_id].ctrl_buf_sz));
1494  return true;
1495  }
1496 
1497  // There went something wrong - unsupported control request type
1498  TU_BREAKPOINT();
1499  return false;
1500  }
1501 
1502  bool audiod_get_interface(uint8_t rhport,
1503  tusb_control_request_t const *p_request) {
1504  uint8_t const itf = tu_u16_low(p_request->wIndex);
1505 
1506  // Find index of audio streaming interface
1507  uint8_t func_id, idxItf;
1508  uint8_t const *dummy;
1509 
1510  TU_VERIFY(
1511  audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy));
1512  TU_VERIFY(tud_control_xfer(rhport, p_request,
1513  &_audiod_fct[func_id].alt_setting[idxItf], 1));
1514 
1515  TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf,
1516  _audiod_fct[func_id].alt_setting[idxItf]);
1517 
1518  return true;
1519  }
1520 
1521  // Invoked when class request DATA stage is finished.
1522  // return false to stall control EP (e.g Host send non-sense DATA)
1523  bool audiod_control_completeX(uint8_t rhport,
1524  tusb_control_request_t const *p_request) {
1525  // Handle audio class specific set requests
1526  if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
1527  p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
1528  uint8_t func_id;
1529 
1530  switch (p_request->bmRequestType_bit.recipient) {
1531  case TUSB_REQ_RCPT_INTERFACE: {
1532  uint8_t itf = TU_U16_LOW(p_request->wIndex);
1533  uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1534 
1535  if (entityID != 0) {
1536  if (p_cb) {
1537  // Check if entity is present and get corresponding driver index
1538  TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1539 
1540  // Invoke callback
1541  return p_cb->set_req_entity_cb(rhport, p_request,
1542  _audiod_fct[func_id].ctrl_buf);
1543  } else {
1544  TU_LOG2(" No entity set request callback available!\r\n");
1545  return false; // In case no callback function is present or
1546  // request can not be conducted we stall it
1547  }
1548  } else {
1549  if (p_cb) {
1550  // Find index of audio driver structure and verify interface
1551  // really exists
1552  TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1553 
1554  // Invoke callback
1555  return p_cb->set_req_itf_cb(rhport, p_request,
1556  _audiod_fct[func_id].ctrl_buf);
1557  } else {
1558  TU_LOG2(" No interface set request callback available!\r\n");
1559  return false; // In case no callback function is present or
1560  // request can not be conducted we stall it
1561  }
1562  }
1563  } break;
1564 
1565  case TUSB_REQ_RCPT_ENDPOINT: {
1566  uint8_t ep = TU_U16_LOW(p_request->wIndex);
1567 
1568  if (p_cb) {
1569  // Check if entity is present and get corresponding driver index
1570  TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1571 
1572  // Invoke callback
1573  return p_cb->set_req_ep_cb(rhport, p_request,
1574  _audiod_fct[func_id].ctrl_buf);
1575  } else {
1576  TU_LOG2(" No EP set request callback available!\r\n");
1577  return false; // In case no callback function is present or
1578  // request can not be conducted we stall it
1579  }
1580  } break;
1581  // Unknown/Unsupported recipient
1582  default:
1583  TU_BREAKPOINT();
1584  return false;
1585  }
1586  }
1587  return true;
1588  }
1589 
1590  bool set_fb_params_freq(audiod_function_t *audio, uint32_t sample_freq,
1591  uint32_t mclk_freq) {
1592  // Check if frame interval is within sane limits
1593  // The interval value n_frames was taken from the descriptors within
1594  // audiod_set_interface()
1595 
1596  // n_frames_min is ceil(2^10 * f_s / f_m) for full speed and ceil(2^13 *
1597  // f_s / f_m) for high speed this lower limit ensures the measures
1598  // feedback value has sufficient precision
1599  uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13;
1600  uint32_t const n_frame = (1UL << audio->feedback.frame_shift);
1601 
1602  if ((((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame) {
1603  TU_LOG1(" UAC2 feedback interval too small\r\n");
1604  TU_BREAKPOINT();
1605  return false;
1606  }
1607 
1608  // Check if parameters really allow for a power of two division
1609  if ((mclk_freq % sample_freq) == 0 &&
1610  tu_is_power_of_two(mclk_freq / sample_freq)) {
1611  audio->feedback.compute_method =
1612  AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2;
1613  audio->feedback.compute.power_of_2 =
1614  16 - audio->feedback.frame_shift - tu_log2(mclk_freq / sample_freq);
1615  } else if (audio->feedback.compute_method ==
1616  AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) {
1617  audio->feedback.compute.float_const =
1618  (float)sample_freq / mclk_freq *
1619  (1UL << (16 - audio->feedback.frame_shift));
1620  } else {
1621  audio->feedback.compute.fixed.sample_freq = sample_freq;
1622  audio->feedback.compute.fixed.mclk_freq = mclk_freq;
1623  }
1624 
1625  return true;
1626  }
1627 
1628  uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) {
1629  audiod_function_t *audio = &_audiod_fct[func_id];
1630  uint32_t feedback;
1631 
1632  switch (audio->feedback.compute_method) {
1633  case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1634  feedback = (cycles << audio->feedback.compute.power_of_2);
1635  break;
1636 
1637  case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1638  feedback =
1639  (uint32_t)((float)cycles * audio->feedback.compute.float_const);
1640  break;
1641 
1642  case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: {
1643  uint64_t fb64 =
1644  (((uint64_t)cycles) * audio->feedback.compute.fixed.sample_freq)
1645  << (16 - audio->feedback.frame_shift);
1646  feedback = (uint32_t)(fb64 / audio->feedback.compute.fixed.mclk_freq);
1647  } break;
1648 
1649  default:
1650  return 0;
1651  }
1652 
1653  // For Windows:
1654  // https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers
1655  // The size of isochronous packets created by the device must be within
1656  // the limits specified in FMT-2.0 section 2.3.1.1. This means that the
1657  // deviation of actual packet size from nominal size must not exceed ±
1658  // one audio slot (audio slot = channel count samples).
1659  if (feedback > audio->feedback.max_value)
1660  feedback = audio->feedback.max_value;
1661  if (feedback < audio->feedback.min_value)
1662  feedback = audio->feedback.min_value;
1663 
1664  tud_audio_n_fb_set(func_id, feedback);
1665 
1666  return feedback;
1667  }
1668 
1669  // This helper function finds for a given audio function and AS interface
1670  // number the index of the attached driver structure, the index of the
1671  // interface in the audio function (e.g. the std. AS interface with
1672  // interface number 15 is the first AS interface for the given audio
1673  // function and thus gets index zero), and finally a pointer to the std. AS
1674  // interface, where the pointer always points to the first alternate setting
1675  // i.e. alternate interface zero.
1676  bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t *audio,
1677  uint8_t *idxItf,
1678  uint8_t const **pp_desc_int) {
1679  if (audio->p_desc) {
1680  // Get pointer at end
1681  uint8_t const *p_desc_end =
1682  audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1683 
1684  // Advance past AC descriptors
1685  uint8_t const *p_desc = tu_desc_next(audio->p_desc);
1686  p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength;
1687 
1688  uint8_t tmp = 0;
1689  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1690  // strict-overflow warning
1691  while (p_desc_end - p_desc > 0) {
1692  // We assume the number of alternate settings is increasing thus we
1693  // return the index of alternate setting zero!
1694  if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1695  ((tusb_desc_interface_t const *)p_desc)->bAlternateSetting == 0) {
1696  if (((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber ==
1697  itf) {
1698  *idxItf = tmp;
1699  *pp_desc_int = p_desc;
1700  return true;
1701  }
1702  // Increase index, bytes read, and pointer
1703  tmp++;
1704  }
1705  p_desc = tu_desc_next(p_desc);
1706  }
1707  }
1708  return false;
1709  }
1710 
1711  // This helper function finds for a given AS interface number the index of
1712  // the attached driver structure, the index of the interface in the audio
1713  // function (e.g. the std. AS interface with interface number 15 is the
1714  // first AS interface for the given audio function and thus gets index
1715  // zero), and finally a pointer to the std. AS interface, where the pointer
1716  // always points to the first alternate setting i.e. alternate interface
1717  // zero.
1718  bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id,
1719  uint8_t *idxItf,
1720  uint8_t const **pp_desc_int) {
1721  // Loop over audio driver interfaces
1722  uint8_t i;
1723  for (i = 0; i < cfg.func_n_as_int; i++) {
1724  if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf,
1725  pp_desc_int)) {
1726  *func_id = i;
1727  return true;
1728  }
1729  }
1730 
1731  return false;
1732  }
1733 
1734  // Verify an entity with the given ID exists and returns also the
1735  // corresponding driver index
1736  bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID,
1737  uint8_t *func_id) {
1738  uint8_t i;
1739  for (i = 0; i < cfg.func_n_as_int; i++) {
1740  // Look for the correct driver by checking if the unique standard AC
1741  // interface number fits
1742  if (_audiod_fct[i].p_desc &&
1743  ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)
1744  ->bInterfaceNumber == itf) {
1745  // Get pointers after class specific AC descriptors and end of AC
1746  // descriptors - entities are defined in between
1747  uint8_t const *p_desc =
1748  tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor
1749  uint8_t const *p_desc_end =
1750  ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength +
1751  p_desc;
1752  p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor
1753 
1754  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1755  // strict-overflow warning
1756  while (p_desc_end - p_desc > 0) {
1757  if (p_desc[3] == entityID) // Entity IDs are always at offset 3
1758  {
1759  *func_id = i;
1760  return true;
1761  }
1762  p_desc = tu_desc_next(p_desc);
1763  }
1764  }
1765  }
1766  return false;
1767  }
1768 
1769  bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) {
1770  uint8_t i;
1771  for (i = 0; i < cfg.func_n_as_int; i++) {
1772  if (_audiod_fct[i].p_desc) {
1773  // Get pointer at beginning and end
1774  uint8_t const *p_desc = _audiod_fct[i].p_desc;
1775  uint8_t const *p_desc_end = _audiod_fct[i].p_desc +
1776  _audiod_fct[i].desc_length -
1777  TUD_AUDIO_DESC_IAD_LEN;
1778  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1779  // strict-overflow warning
1780  while (p_desc_end - p_desc > 0) {
1781  if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1782  ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)
1783  ->bInterfaceNumber == itf) {
1784  *func_id = i;
1785  return true;
1786  }
1787  p_desc = tu_desc_next(p_desc);
1788  }
1789  }
1790  }
1791  return false;
1792  }
1793 
1794  bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) {
1795  uint8_t i;
1796  for (i = 0; i < cfg.func_n_as_int; i++) {
1797  if (_audiod_fct[i].p_desc) {
1798  // Get pointer at end
1799  uint8_t const *p_desc_end =
1800  _audiod_fct[i].p_desc + _audiod_fct[i].desc_length;
1801 
1802  // Advance past AC descriptors - EP we look for are streaming EPs
1803  uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc);
1804  p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength;
1805 
1806  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1807  // strict-overflow warning
1808  while (p_desc_end - p_desc > 0) {
1809  if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT &&
1810  ((tusb_desc_endpoint_t const *)p_desc)->bEndpointAddress == ep) {
1811  *func_id = i;
1812  return true;
1813  }
1814  p_desc = tu_desc_next(p_desc);
1815  }
1816  }
1817  }
1818  return false;
1819  }
1820 
1821  // p_desc points to the AS interface of alternate setting zero
1822  // itf is the interface number of the corresponding interface - we check if
1823  // the interface belongs to EP in or EP out to see if it is a TX or RX
1824  // parameter Currently, only AS interfaces with an EP (in or out) are
1825  // supposed to be parsed for!
1826  void audiod_parse_for_AS_params(audiod_function_t *audio,
1827  uint8_t const *p_desc,
1828  uint8_t const *p_desc_end,
1829  uint8_t const as_itf) {
1830  if (cfg.is_ep_in() && cfg.is_ep_out()) {
1831  if (as_itf != audio->ep_in_as_intf_num &&
1832  as_itf != audio->ep_out_as_intf_num)
1833  return; // Abort, this interface has no EP, this driver does not
1834  // support this currently
1835  }
1836  if (cfg.is_ep_in() && !cfg.is_ep_out()) {
1837  if (as_itf != audio->ep_in_as_intf_num) return;
1838  }
1839  if (!cfg.is_ep_in() && cfg.is_ep_out()) {
1840  if (as_itf != audio->ep_out_as_intf_num) return;
1841  }
1842 
1843  p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor
1844  // of current alternate interface descriptor
1845  // Condition modified from p_desc < p_desc_end to prevent gcc>=12
1846  // strict-overflow warning
1847  while (p_desc_end - p_desc > 0) {
1848  // Abort if follow up descriptor is a new standard interface descriptor
1849  // - indicates the last AS descriptor was already finished
1850  if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break;
1851 
1852  // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify
1853  // format type and format and also to get number of physical channels
1854  if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
1855  tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) {
1856  if (cfg.is_ep_in()) {
1857  if (as_itf == audio->ep_in_as_intf_num) {
1858  audio->n_channels_tx =
1859  ((audio_desc_cs_as_interface_t const *)p_desc)->bNrChannels;
1860  audio->format_type_tx =
1861  (audio_format_type_t)(((audio_desc_cs_as_interface_t const *)
1862  p_desc)
1863  ->bFormatType);
1864  }
1865  }
1866 
1867  // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats)
1868  if (cfg.enable_ep_in_flow_control) {
1869  if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
1870  tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE &&
1871  ((audio_desc_type_I_format_t const *)p_desc)->bFormatType ==
1872  AUDIO_FORMAT_TYPE_I) {
1873  if (cfg.is_ep_in() && cfg.is_ep_out()) {
1874  if (as_itf != audio->ep_in_as_intf_num &&
1875  as_itf != audio->ep_out_as_intf_num)
1876  break; // Abort loop, this interface has no EP, this driver
1877  // does not support this currently
1878  }
1879  if (cfg.is_ep_in() && !cfg.is_ep_out()) {
1880  if (as_itf != audio->ep_in_as_intf_num) break;
1881  }
1882  if (!cfg.is_ep_in() && cfg.is_ep_out()) {
1883  if (as_itf != audio->ep_out_as_intf_num) break;
1884  }
1885 
1886  if (cfg.is_ep_in()) {
1887  if (as_itf == audio->ep_in_as_intf_num) {
1888  audio->n_bytes_per_sample_tx =
1889  ((audio_desc_type_I_format_t const *)p_desc)->bSubslotSize;
1890  }
1891  }
1892  }
1893  }
1894  }
1895  // Other format types are not supported yet
1896 
1897  p_desc = tu_desc_next(p_desc);
1898  }
1899  }
1900 
1901  bool audiod_calc_tx_packet_sz(audiod_function_t *audio) {
1902  TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
1903  TU_VERIFY(audio->n_channels_tx);
1904  TU_VERIFY(audio->n_bytes_per_sample_tx);
1905  TU_VERIFY(audio->interval_tx);
1906  TU_VERIFY(audio->sample_rate_tx);
1907 
1908  const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL)
1909  ? audio->interval_tx
1910  : 1 << (audio->interval_tx - 1);
1911 
1912  const uint16_t sample_normimal =
1913  (uint16_t)(audio->sample_rate_tx * interval /
1914  ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1915  const uint16_t sample_reminder =
1916  (uint16_t)(audio->sample_rate_tx * interval %
1917  ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1918 
1919  const uint16_t packet_sz_tx_min =
1920  (uint16_t)((sample_normimal - 1) * audio->n_channels_tx *
1921  audio->n_bytes_per_sample_tx);
1922  const uint16_t packet_sz_tx_norm =
1923  (uint16_t)(sample_normimal * audio->n_channels_tx *
1924  audio->n_bytes_per_sample_tx);
1925  const uint16_t packet_sz_tx_max =
1926  (uint16_t)((sample_normimal + 1) * audio->n_channels_tx *
1927  audio->n_bytes_per_sample_tx);
1928 
1929  // Endpoint size must larger than packet size
1930  TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
1931 
1932  // Frmt20.pdf 2.3.1.1 USB Packets
1933  if (sample_reminder) {
1934  // All virtual frame packets must either contain INT(nav) audio slots
1935  // (small VFP) or INT(nav)+1 (large VFP) audio slots
1936  audio->packet_sz_tx[0] = packet_sz_tx_norm;
1937  audio->packet_sz_tx[1] = packet_sz_tx_norm;
1938  audio->packet_sz_tx[2] = packet_sz_tx_max;
1939  } else {
1940  // In the case where nav = INT(nav), ni may vary between INT(nav)-1
1941  // (small VFP), INT(nav) (medium VFP) and INT(nav)+1 (large VFP).
1942  audio->packet_sz_tx[0] = packet_sz_tx_min;
1943  audio->packet_sz_tx[1] = packet_sz_tx_norm;
1944  audio->packet_sz_tx[2] = packet_sz_tx_max;
1945  }
1946 
1947  return true;
1948  }
1949 
1950  uint16_t audiod_tx_packet_size(const uint16_t *norminal_size,
1951  uint16_t data_count, uint16_t fifo_depth,
1952  uint16_t max_depth) {
1953  // Flow control need a FIFO size of at least 4*Navg
1954  if (norminal_size[1] && norminal_size[1] <= fifo_depth * 4) {
1955  // Use blackout to prioritize normal size packet
1956  int ctrl_blackout = 0;
1957  uint16_t packet_size;
1958  uint16_t slot_size = norminal_size[2] - norminal_size[1];
1959  if (data_count < norminal_size[0]) {
1960  // If you get here frequently, then your I2S clock deviation is too
1961  // big !
1962  packet_size = 0;
1963  } else if (data_count < fifo_depth / 2 - slot_size && !ctrl_blackout) {
1964  packet_size = norminal_size[0];
1965  ctrl_blackout = 10;
1966  } else if (data_count > fifo_depth / 2 + slot_size && !ctrl_blackout) {
1967  packet_size = norminal_size[2];
1968  if (norminal_size[0] == norminal_size[1]) {
1969  // nav > INT(nav), eg. 44.1k, 88.2k
1970  ctrl_blackout = 0;
1971  } else {
1972  // nav = INT(nav), eg. 48k, 96k
1973  ctrl_blackout = 10;
1974  }
1975  } else {
1976  packet_size = norminal_size[1];
1977  if (ctrl_blackout) {
1978  ctrl_blackout--;
1979  }
1980  }
1981  // Normally this cap is not necessary
1982  return tu_min16(packet_size, max_depth);
1983  } else {
1984  return tu_min16(data_count, max_depth);
1985  }
1986  }
1987 };
1988 
1989 // TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id,
1990 // uint32_t frame_number, uint8_t interval_shift){
1991 // // call audiod_sof_isr
1992 // }
Definition: USBDeviceAudioAPI.h:103
Configuration for TinyUSB Audio.
Definition: USBDeviceAudioAPI.h:43
Definition: USBDeviceAudioAPI.h:177
uint16_t tud_audio_n_write(uint8_t func_id, const void *data, uint16_t len)
Write data to EP in buffer.
Definition: USBDeviceAudioAPI.h:231
Definition: USBDeviceAudio.h:104
Definition: USBDeviceAudioAPI.h:859
Definition: USBDeviceAudioAPI.h:817
Definition: USBDeviceAudioAPI.h:28