summaryrefslogtreecommitdiff
path: root/src/class/audio/audio_device.h
blob: 41cc969d1d02f94e0a8947dfe45a611a37c26251 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
/*
 * SPDX-FileCopyrightText: Copyright (c) 2020 Ha Thach (tinyusb.org)
 * SPDX-FileCopyrightText: Copyright (c) 2020 Reinhard Panhuber
 * SPDX-FileCopyrightText: Copyright (c) 2023 HiFiPhile (Zixun LI)
 * SPDX-License-Identifier: MIT
 *
 * This file is part of the TinyUSB stack.
 */

#ifndef TUSB_AUDIO_DEVICE_H_
#define TUSB_AUDIO_DEVICE_H_

#include "audio.h"

//--------------------------------------------------------------------+
// Class Driver Configuration
//--------------------------------------------------------------------+

// All sizes are in bytes!

// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your
// biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors
#ifndef CFG_TUD_AUDIO_CTRL_BUF_SZ
#define CFG_TUD_AUDIO_CTRL_BUF_SZ    64
#endif

// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024
#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN
#define CFG_TUD_AUDIO_ENABLE_EP_IN 0   // TX
#endif

#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT
#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0  // RX
#endif

// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation
#if CFG_TUD_AUDIO_ENABLE_EP_IN
#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX
#error You must tell the driver the biggest EP IN size!
#endif
#if CFG_TUD_AUDIO > 1
#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX
#error You must tell the driver the biggest EP IN size!
#endif
#endif
#if CFG_TUD_AUDIO > 2
#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX
#error You must tell the driver the biggest EP IN size!
#endif
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN

#if CFG_TUD_AUDIO_ENABLE_EP_OUT
#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX
#error You must tell the driver the biggest EP OUT size!
#endif
#if CFG_TUD_AUDIO > 1
#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX
#error You must tell the driver the biggest EP OUT size!
#endif
#endif
#if CFG_TUD_AUDIO > 2
#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX
#error You must tell the driver the biggest EP OUT size!
#endif
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT

// Software EP FIFO buffer sizes - must be >= max EP SIZEs!
#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ                0
#endif
#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ
#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ                0
#endif
#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ
#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ                0
#endif

#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ
#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ               0
#endif
#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ
#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ               0
#endif
#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ
#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ               0
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_IN
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX
#error EP software buffer size MUST BE at least as big as maximum EP size
#endif

#if CFG_TUD_AUDIO > 1
#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX
#error EP software buffer size MUST BE at least as big as maximum EP size
#endif
#endif

#if CFG_TUD_AUDIO > 2
#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX
#error EP software buffer size MUST BE at least as big as maximum EP size
#endif
#endif
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_OUT
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX
#error EP software buffer size MUST BE at least as big as maximum EP size
#endif

#if CFG_TUD_AUDIO > 1
#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX
#error EP software buffer size MUST BE at least as big as maximum EP size
#endif
#endif

#if CFG_TUD_AUDIO > 2
#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX
#error EP software buffer size MUST BE at least as big as maximum EP size
#endif
#endif
#endif

// (For TYPE-I format only) Flow control is necessary to allow IN ep send correct amount of data, unless it's a
// virtual device where data is perfectly synchronized to USB clock.
#ifndef CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL  1
#endif

// Enable/disable feedback EP (required for asynchronous RX applications)
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP                    0                             // Feedback - 0 or 1
#endif

// Enable/disable interrupt EP (required for notifying host of control changes)
#ifndef CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP                   0                             // Feedback - 0 or 1
#endif

// Audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74)
#define CFG_TUD_AUDIO_INTERRUPT_EP_SZ                       6

#ifdef __cplusplus
extern "C" {
#endif

/** \addtogroup AUDIO_Serial Serial
 *  @{
 *  \defgroup   AUDIO_Serial_Device Device
 *  @{ */

//--------------------------------------------------------------------+
// Application API (Multiple Interfaces)
// CFG_TUD_AUDIO > 1
//--------------------------------------------------------------------+
bool tud_audio_n_mounted(uint8_t func_id);
uint8_t tud_audio_n_version(uint8_t func_id);

#if CFG_TUD_AUDIO_ENABLE_EP_OUT
uint16_t   tud_audio_n_available       (uint8_t func_id);
uint16_t   tud_audio_n_read            (uint8_t func_id, void* buffer, uint16_t bufsize);
bool       tud_audio_n_clear_ep_out_ff (uint8_t func_id);
tu_fifo_t* tud_audio_n_get_ep_out_ff   (uint8_t func_id);
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_IN
uint16_t   tud_audio_n_write          (uint8_t func_id, const void * data, uint16_t len);
bool       tud_audio_n_clear_ep_in_ff (uint8_t func_id);
tu_fifo_t* tud_audio_n_get_ep_in_ff   (uint8_t func_id);
uint16_t   tud_audio_n_get_ep_in_fifo_threshold(uint8_t func_id);
void       tud_audio_n_set_ep_in_fifo_threshold(uint8_t func_id, uint16_t threshold);
#endif

#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
bool    tud_audio_int_n_write                     (uint8_t func_id, const audio_interrupt_data_t * data);
#endif

//--------------------------------------------------------------------+
// Application API (Interface0)
//--------------------------------------------------------------------+
static inline bool         tud_audio_mounted                (void);
static inline uint8_t      tud_audio_version                (void);

#if CFG_TUD_AUDIO_ENABLE_EP_OUT
static inline uint16_t   tud_audio_available       (void);
static inline bool       tud_audio_clear_ep_out_ff (void);
static inline uint16_t   tud_audio_read            (void* buffer, uint16_t bufsize);
static inline tu_fifo_t* tud_audio_get_ep_out_ff   (void);
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_IN
static inline uint16_t   tud_audio_write          (const void * data, uint16_t len);
static inline bool       tud_audio_clear_ep_in_ff (void);
static inline tu_fifo_t* tud_audio_get_ep_in_ff   (void);
#endif

// INT CTR API

#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
static inline bool tud_audio_int_write                      (const audio_interrupt_data_t * data);
#endif

// Buffer control EP data and schedule a transmit
// This function is intended to be used if you do not have a persistent buffer or memory location available
// (e.g. non-local variables) and need to answer onto a get request. This function buffers your answer request
// frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it.
// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer
// pointer in pointing. If you already have such available you may directly use 'tud_control_xfer(...)'. In this
// case data does not need to be copied into an additional buffer and you save some time.
// If the request's wLength is zero, a status packet is sent instead.
bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request,
                                                 void* data, uint16_t len);

//--------------------------------------------------------------------+
// Application Callback API
//--------------------------------------------------------------------+

#if CFG_TUD_AUDIO_ENABLE_EP_IN
// Invoked in ISR context once an audio packet was sent successfully.
// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock),
// call tud_audio_write() in I2S receive callback.
bool tud_audio_tx_done_isr(uint8_t rhport, uint16_t n_bytes_sent, uint8_t func_id, uint8_t ep_in,
                           uint8_t cur_alt_setting);
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_OUT
// Invoked in ISR context once an audio packet was received successfully.
// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock),
// call tud_audio_read() in I2S transmit callback.
bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out,
                           uint8_t cur_alt_setting);
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP

// Note about feedback calculation
//
// Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT
// Feedback value is calculated within the audio driver by regulating the FIFO level to half fill.
// Advantage: No SOF interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus
// less CPU load, well tested (Windows, Linux, OSX) with a reliable result so far.
// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is
// introduced.
//
// Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT
// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information
// about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle
// count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter).
// See tud_audio_set_fb_params() and tud_audio_feedback_update()
// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a
// smaller delay is possible.
// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point
// is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -,
// hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is
// introduced). Long-term drift will cause the FIFO under/overflow, you still needs to correct it somehow.
//
// Option 3 - manual
// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined
// e.g. from some fill status of some FIFO buffer.
// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus
// less CPU load.
// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay
// is introduced.


// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at
// FB endpoint interval till it's changed.
//
// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus
// Specification Revision 2.0 5.12.4.2). For simplicity, this function always uses 16.16 format. For FS devices,
// the driver will automatically convert the value to 10.14 format.
//
// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0
// devices. On Linux and it seems the driver can work with either format.
//
// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the
// feature is used, the user can not set the feedback value.
//
// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec
// Boiled down, the feedback value Ff = n_samples / (micro)frame.
// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames
// need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency
// e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is
// available and locked to f_s)
// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where
// P = min( ceil(log2(f_m / f_s)), K)
// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles
// within fb_n_frames
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);

// Update feedback value with passed MCLK cycles since last time this update function is called.
// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented
// This function will also call tud_audio_feedback_set()
// return feedback value in 16.16 for reference (0 for error)
// Example :
//   binterval=3 (4ms); FS = 48kHz; MCLK = 12.288MHz
//   In 4 SOF MCLK counted 49152 cycles
uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles);

enum {
  AUDIO_FEEDBACK_METHOD_DISABLED,
  AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
  AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
  AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only
  AUDIO_FEEDBACK_METHOD_FIFO_COUNT
};

typedef struct {
  uint8_t method;
  uint32_t sample_freq;   //  sample frequency in Hz

  union {
    struct {
      uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on
    } frequency;
    struct {
      uint16_t fifo_threshold;  // Target FIFO threshold level, default to half FIFO if not set
    } fifo_count;
  };
} audio_feedback_params_t;

// Invoked when needed to set feedback parameters
void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);

// Callback in ISR context, invoked periodically according to feedback endpoint bInterval.
// Could be used to compute and update feedback value, should be placed in RAM if possible
// frame_number  : current SOF count
// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor
TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP

#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
// Invoked when an interrupt notification transfer is complete
void tud_audio_int_done_cb(uint8_t rhport);
#endif

// Invoked when audio set interface request received
bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);

// Invoked when audio set interface request received which closes an EP
bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);

// backward compatible for typo
#define tud_audio_set_itf_close_EP_cb   tud_audio_set_itf_close_ep_cb

// Invoked when audio class specific set request received for an EP
bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);

// Invoked when audio class specific set request received for an interface
bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);

// Invoked when audio class specific set request received for an entity
bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);

// Invoked when audio class specific get request received for an EP
bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);

// Invoked when audio class specific get request received for an interface
bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);

// Invoked when audio class specific get request received for an entity
bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);

//--------------------------------------------------------------------+
// Inline Functions
//--------------------------------------------------------------------+

TU_ATTR_ALWAYS_INLINE static inline bool tud_audio_mounted(void) {
  return tud_audio_n_mounted(0);
}

TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_audio_version(void) {
  return tud_audio_n_version(0);
}

#if CFG_TUD_AUDIO_ENABLE_EP_OUT

TU_ATTR_ALWAYS_INLINE static inline uint16_t tud_audio_available(void) {
  return tud_audio_n_available(0);
}

TU_ATTR_ALWAYS_INLINE static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) {
  return tud_audio_n_read(0, buffer, bufsize);
}

TU_ATTR_ALWAYS_INLINE static inline bool tud_audio_clear_ep_out_ff(void) {
  return tud_audio_n_clear_ep_out_ff(0);
}

TU_ATTR_ALWAYS_INLINE static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) {
  return tud_audio_n_get_ep_out_ff(0);
}

#endif

#if CFG_TUD_AUDIO_ENABLE_EP_IN

TU_ATTR_ALWAYS_INLINE static inline uint16_t tud_audio_write(const void * data, uint16_t len) {
  return tud_audio_n_write(0, data, len);
}

TU_ATTR_ALWAYS_INLINE static inline bool tud_audio_clear_ep_in_ff(void) {
  return tud_audio_n_clear_ep_in_ff(0);
}

TU_ATTR_ALWAYS_INLINE static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) {
  return tud_audio_n_get_ep_in_ff(0);
}

TU_ATTR_ALWAYS_INLINE static inline uint16_t tud_audio_get_ep_in_fifo_threshold(void)
{
  return tud_audio_n_get_ep_in_fifo_threshold(0);
}

TU_ATTR_ALWAYS_INLINE static inline void tud_audio_set_ep_in_fifo_threshold(uint16_t threshold)
{
  tud_audio_n_set_ep_in_fifo_threshold(0, threshold);
}

#endif

#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
TU_ATTR_ALWAYS_INLINE static inline bool tud_audio_int_write(const audio_interrupt_data_t * data) {
  return tud_audio_int_n_write(0, data);
}
#endif

#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
TU_ATTR_ALWAYS_INLINE static inline bool tud_audio_fb_set(uint32_t feedback) {
  return tud_audio_n_fb_set(0, feedback);
}
#endif

//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void     audiod_init           (void);
bool     audiod_deinit         (void);
void     audiod_reset          (uint8_t rhport);
uint16_t audiod_open           (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool     audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
bool     audiod_xfer_cb        (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
bool     audiod_xfer_isr       (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
void     audiod_sof_isr        (uint8_t rhport, uint32_t frame_count);

#ifdef __cplusplus
}
#endif

#endif /* TUSB_AUDIO_DEVICE_H_ */

/** @} */
/** @} */