Open FFBoard
Open source force feedback firmware
audio_device.h
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2020 Ha Thach (tinyusb.org)
5 * Copyright (c) 2020 Reinhard Panhuber
6 * Copyright (c) 2023 HiFiPhile
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 *
26 * This file is part of the TinyUSB stack.
27 */
28
29#ifndef _TUSB_AUDIO_DEVICE_H_
30#define _TUSB_AUDIO_DEVICE_H_
31
32#include "audio.h"
33
34//--------------------------------------------------------------------+
35// Class Driver Configuration
36//--------------------------------------------------------------------+
37
38// All sizes are in bytes!
39
40#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN
41#error You must tell the driver the length of the audio function descriptor including IAD descriptor
42#endif
43#if CFG_TUD_AUDIO > 1
44#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN
45#error You must tell the driver the length of the audio function descriptor including IAD descriptor
46#endif
47#endif
48#if CFG_TUD_AUDIO > 2
49#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN
50#error You must tell the driver the length of the audio function descriptor including IAD descriptor
51#endif
52#endif
53
54// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces
55#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT
56#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor!
57#endif
58#if CFG_TUD_AUDIO > 1
59#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT
60#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor!
61#endif
62#endif
63#if CFG_TUD_AUDIO > 2
64#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT
65#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor!
66#endif
67#endif
68
69// 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
70#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ
71#error You must define an audio class control request buffer size!
72#endif
73
74#if CFG_TUD_AUDIO > 1
75#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ
76#error You must define an audio class control request buffer size!
77#endif
78#endif
79
80#if CFG_TUD_AUDIO > 2
81#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ
82#error You must define an audio class control request buffer size!
83#endif
84#endif
85
86// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024
87#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN
88#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX
89#endif
90
91#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT
92#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX
93#endif
94
95// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation
96#if CFG_TUD_AUDIO_ENABLE_EP_IN
97#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX
98#error You must tell the driver the biggest EP IN size!
99#endif
100#if CFG_TUD_AUDIO > 1
101#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX
102#error You must tell the driver the biggest EP IN size!
103#endif
104#endif
105#if CFG_TUD_AUDIO > 2
106#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX
107#error You must tell the driver the biggest EP IN size!
108#endif
109#endif
110#endif // CFG_TUD_AUDIO_ENABLE_EP_IN
111
112#if CFG_TUD_AUDIO_ENABLE_EP_OUT
113#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX
114#error You must tell the driver the biggest EP OUT size!
115#endif
116#if CFG_TUD_AUDIO > 1
117#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX
118#error You must tell the driver the biggest EP OUT size!
119#endif
120#endif
121#if CFG_TUD_AUDIO > 2
122#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX
123#error You must tell the driver the biggest EP OUT size!
124#endif
125#endif
126#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
127
128// Software EP FIFO buffer sizes - must be >= max EP SIZEs!
129#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ
130#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0
131#endif
132#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ
133#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0
134#endif
135#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ
136#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0
137#endif
138
139#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ
140#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0
141#endif
142#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ
143#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0
144#endif
145#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ
146#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0
147#endif
148
149#if CFG_TUD_AUDIO_ENABLE_EP_IN
150#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX
151#error EP software buffer size MUST BE at least as big as maximum EP size
152#endif
153
154#if CFG_TUD_AUDIO > 1
155#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX
156#error EP software buffer size MUST BE at least as big as maximum EP size
157#endif
158#endif
159
160#if CFG_TUD_AUDIO > 2
161#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX
162#error EP software buffer size MUST BE at least as big as maximum EP size
163#endif
164#endif
165#endif
166
167#if CFG_TUD_AUDIO_ENABLE_EP_OUT
168#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX
169#error EP software buffer size MUST BE at least as big as maximum EP size
170#endif
171
172#if CFG_TUD_AUDIO > 1
173#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX
174#error EP software buffer size MUST BE at least as big as maximum EP size
175#endif
176#endif
177
178#if CFG_TUD_AUDIO > 2
179#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX
180#error EP software buffer size MUST BE at least as big as maximum EP size
181#endif
182#endif
183#endif
184
185// (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.
186#ifndef CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
187#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1
188#endif
189
190// Enable/disable feedback EP (required for asynchronous RX applications)
191#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
192#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1
193#endif
194
195// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set().
196// Can be override by tud_audio_feedback_format_correction_cb()
197#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION
198#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1
199#endif
200
201// Enable/disable interrupt EP (required for notifying host of control changes)
202#ifndef CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
203#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0 // Feedback - 0 or 1
204#endif
205
206// Use software encoding/decoding
207
208// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved
209// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4.
210//
211// Currently, only PCM type I encoding/decoding is supported!
212//
213// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below.
214
215// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the
216// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using
217// - tud_audio_n_write() or
218// - tud_audio_n_read().
219// To write/read to/from the support FIFOs use
220// - tud_audio_n_write_support_ff() or
221// - tud_audio_n_read_support_ff().
222//
223// The encoding/decoding format type done is defined below.
224//
225// The encoding/decoding starts when the private callback functions
226// - audio_tx_done_cb()
227// - audio_rx_done_cb()
228// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there.
229// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions
230// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb()
231// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb()
232// if you want to get informed what happened.
233//
234// If you don't use the support FIFOs you may use the public callback functions
235// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb()
236// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb()
237// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time.
238//
239// If you need a different encoding which is not support so far implement it in the
240// - audio_tx_done_cb()
241// - audio_rx_done_cb()
242// functions.
243
244// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size
245// The actual coding parameters of active AS alternate interface is parsed from the descriptors
246
247// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple
248// of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sample_sz) * sample_sz)!
249// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!!
250
251// For PCM encoding/decoding
252
253#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING
254#define CFG_TUD_AUDIO_ENABLE_ENCODING 0
255#endif
256
257#ifndef CFG_TUD_AUDIO_ENABLE_DECODING
258#define CFG_TUD_AUDIO_ENABLE_DECODING 0
259#endif
260
261// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding
262#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
263#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0
264#endif
265
266#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
267#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0
268#endif
269
270// Type I Coding parameters not given within UAC2 descriptors
271// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined!
272#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
273#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX
274#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO
275#endif
276#if CFG_TUD_AUDIO > 1
277#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX
278#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO
279#endif
280#endif
281#if CFG_TUD_AUDIO > 2
282#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX
283#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO
284#endif
285#endif
286#endif
287
288#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
289#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX
290#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO
291#endif
292#if CFG_TUD_AUDIO > 1
293#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX
294#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO
295#endif
296#endif
297#if CFG_TUD_AUDIO > 2
298#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX
299#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO
300#endif
301#endif
302#endif
303
304// Remaining types not support so far
305
306// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface
307#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO
308#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0
309#endif
310#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO
311#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0
312#endif
313#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO
314#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0
315#endif
316
317#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO
318#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0
319#endif
320#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO
321#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0
322#endif
323#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO
324#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0
325#endif
326
327// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO
328#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ
329#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample)
330#endif
331#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ
332#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0
333#endif
334#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ
335#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0
336#endif
337
338#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ
339#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample)
340#endif
341#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ
342#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0
343#endif
344#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ
345#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0
346#endif
347
348//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!");
349
350// Supported types of this driver:
351// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL
352
353#ifdef __cplusplus
354extern "C" {
355#endif
356
362//--------------------------------------------------------------------+
363// Application API (Multiple Interfaces)
364// CFG_TUD_AUDIO > 1
365//--------------------------------------------------------------------+
366bool tud_audio_n_mounted (uint8_t func_id);
367
368#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
369uint16_t tud_audio_n_available (uint8_t func_id);
370uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize);
371bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO
372tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id);
373#endif
374
375#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
376bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs
377uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx);
378uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize);
379tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx);
380#endif
381
382#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
383uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len);
384bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO
385tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id);
386#endif
387
388#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
389uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO
390bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx);
391uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len);
392tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx);
393#endif
394
395#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
396bool tud_audio_int_n_write (uint8_t func_id, const audio_interrupt_data_t * data);
397#endif
398
399
400//--------------------------------------------------------------------+
401// Application API (Interface0)
402//--------------------------------------------------------------------+
403
404static inline bool tud_audio_mounted (void);
405
406// RX API
407
408#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
409static inline uint16_t tud_audio_available (void);
410static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO
411static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize);
412static inline tu_fifo_t* tud_audio_get_ep_out_ff (void);
413#endif
414
415#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
416static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx);
417static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx);
418static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize);
419static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx);
420#endif
421
422// TX API
423
424#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
425static inline uint16_t tud_audio_write (const void * data, uint16_t len);
426static inline bool tud_audio_clear_ep_in_ff (void);
427static inline tu_fifo_t* tud_audio_get_ep_in_ff (void);
428#endif
429
430#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
431static inline uint16_t tud_audio_flush_tx_support_ff (void);
432static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx);
433static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len);
434static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx);
435#endif
436
437// INT CTR API
438
439#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
440static inline bool tud_audio_int_write (const audio_interrupt_data_t * data);
441#endif
442
443// Buffer control EP data and schedule a transmit
444// 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
445// 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.
446// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such
447// 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.
448// If the request's wLength is zero, a status packet is sent instead.
449bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len);
450
451//--------------------------------------------------------------------+
452// Application Callback API
453//--------------------------------------------------------------------+
454
455#if CFG_TUD_AUDIO_ENABLE_EP_IN
456bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
457bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
458#endif
459
460#if CFG_TUD_AUDIO_ENABLE_EP_OUT
461bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
462bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
463#endif
464
465#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
466void tud_audio_fb_done_cb(uint8_t func_id);
467
468
469// Note about feedback calculation
470//
471// Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT
472// Feedback value is calculated within the audio driver by regulating the FIFO level to half fill.
473// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, well tested
474// (Windows, Linux, OSX) with a reliable result so far.
475// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is introduced.
476//
477// Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT
478// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from
479// 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).
480// See tud_audio_set_fb_params() and tud_audio_feedback_update()
481// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a smaller delay is possible.
482// 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.
483// 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).
484// Long-term drift could occur since error is accumulated.
485//
486// Option 3 - manual
487// 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.
488// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load.
489// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay is introduced.
490
491
492// 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.
493//
494// 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). By default,
495// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set or tud_audio_feedback_format_correction_cb()
496// return true, then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS.
497//
498// 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
499// driver can work with either format.
500//
501// 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.
502//
503// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec
504// Boiled down, the feedback value Ff = n_samples / (micro)frame.
505// 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
506// 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)
507// 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)
508// 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
509bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
510
511// Update feedback value with passed MCLK cycles since last time this update function is called.
512// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented
513// This function will also call tud_audio_feedback_set()
514// return feedback value in 16.16 for reference (0 for error)
515// Example :
516// binterval=3 (4ms); FS = 48kHz; MCLK = 12.288MHz
517// In 4 SOF MCLK counted 49152 cycles
518uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles);
519
520enum {
524 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only
527
528typedef struct {
529 uint8_t method;
530 uint32_t sample_freq; // sample frequency in Hz
531
532 union {
533 struct {
534 uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on
535 }frequency;
536
537 };
539
540// Invoked when needed to set feedback parameters
541void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
542
543// Callback in ISR context, invoked periodically according to feedback endpoint bInterval.
544// Could be used to compute and update feedback value, should be placed in RAM if possible
545// frame_number : current SOF count
546// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor
547TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
548
549// (Full-Speed only) Callback to set feedback format correction is applied or not,
550// default to CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION if not implemented.
551bool tud_audio_feedback_format_correction_cb(uint8_t func_id);
552#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
553
554#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
555void tud_audio_int_done_cb(uint8_t rhport);
556#endif
557
558// Invoked when audio set interface request received
559bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
560
561// Invoked when audio set interface request received which closes an EP
562bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request);
563
564// Invoked when audio class specific set request received for an EP
565bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
566
567// Invoked when audio class specific set request received for an interface
568bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
569
570// Invoked when audio class specific set request received for an entity
571bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
572
573// Invoked when audio class specific get request received for an EP
574bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);
575
576// Invoked when audio class specific get request received for an interface
577bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
578
579// Invoked when audio class specific get request received for an entity
580bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);
581
582//--------------------------------------------------------------------+
583// Inline Functions
584//--------------------------------------------------------------------+
585
586static inline bool tud_audio_mounted(void)
587{
588 return tud_audio_n_mounted(0);
589}
590
591// RX API
592
593#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
594
595static inline uint16_t tud_audio_available(void)
596{
597 return tud_audio_n_available(0);
598}
599
600static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize)
601{
602 return tud_audio_n_read(0, buffer, bufsize);
603}
604
605static inline bool tud_audio_clear_ep_out_ff(void)
606{
608}
609
611{
613}
614
615#endif
616
617#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
618
619static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx)
620{
621 return tud_audio_n_clear_rx_support_ff(0, ff_idx);
622}
623
624static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx)
625{
626 return tud_audio_n_available_support_ff(0, ff_idx);
627}
628
629static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize)
630{
631 return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize);
632}
633
634static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx)
635{
636 return tud_audio_n_get_rx_support_ff(0, ff_idx);
637}
638
639#endif
640
641// TX API
642
643#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
644
645static inline uint16_t tud_audio_write(const void * data, uint16_t len)
646{
647 return tud_audio_n_write(0, data, len);
648}
649
650static inline bool tud_audio_clear_ep_in_ff(void)
651{
653}
654
656{
657 return tud_audio_n_get_ep_in_ff(0);
658}
659
660#endif
661
662#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
663
664static inline uint16_t tud_audio_flush_tx_support_ff(void)
665{
667}
668
669static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx)
670{
671 return tud_audio_n_clear_tx_support_ff(0, ff_idx);
672}
673
674static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len)
675{
676 return tud_audio_n_write_support_ff(0, ff_idx, data, len);
677}
678
679static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx)
680{
681 return tud_audio_n_get_tx_support_ff(0, ff_idx);
682}
683
684#endif
685
686#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
688{
689 return tud_audio_int_n_write(0, data);
690}
691#endif
692
693#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
694
695static inline bool tud_audio_fb_set(uint32_t feedback)
696{
697 return tud_audio_n_fb_set(0, feedback);
698}
699
700#endif
701
702//--------------------------------------------------------------------+
703// Internal Class Driver API
704//--------------------------------------------------------------------+
705void audiod_init (void);
706bool audiod_deinit (void);
707void audiod_reset (uint8_t rhport);
708uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
709bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
710bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
711void audiod_sof_isr (uint8_t rhport, uint32_t frame_count);
712
713#ifdef __cplusplus
714}
715#endif
716
717#endif /* _TUSB_AUDIO_DEVICE_H_ */
718
static struct @612 data
uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
void audiod_sof_isr(uint8_t rhport, uint32_t frame_count)
void tud_audio_int_done_cb(uint8_t rhport)
Definition: audio_device.c:502
bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const *p_request, void *data, uint16_t len)
static tu_fifo_t * tud_audio_get_ep_out_ff(void)
Definition: audio_device.h:610
bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data)
Definition: audio_device.c:957
bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request)
Definition: audio_device.c:557
bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting)
Definition: audio_device.c:468
bool audiod_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes)
static uint16_t tud_audio_write(const void *data, uint16_t len)
Definition: audio_device.h:645
bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting)
Definition: audio_device.c:440
static uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx)
Definition: audio_device.h:669
static uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void *buffer, uint16_t bufsize)
Definition: audio_device.h:629
static tu_fifo_t * tud_audio_get_rx_support_ff(uint8_t ff_idx)
Definition: audio_device.h:634
static bool tud_audio_int_write(const audio_interrupt_data_t *data)
Definition: audio_device.h:687
void audiod_init(void)
bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting)
Definition: audio_device.c:448
void tud_audio_fb_done_cb(uint8_t func_id)
Definition: audio_device.c:479
bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request)
Definition: audio_device.c:549
bool audiod_deinit(void)
tu_fifo_t * tud_audio_n_get_ep_out_ff(uint8_t func_id)
Definition: audio_device.c:654
uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx)
Definition: audio_device.c:670
uint16_t tud_audio_n_read(uint8_t func_id, void *buffer, uint16_t bufsize)
Definition: audio_device.c:642
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
tu_fifo_t * tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx)
Definition: audio_device.c:682
tu_fifo_t * tud_audio_n_get_ep_in_ff(uint8_t func_id)
Definition: audio_device.c:909
static bool tud_audio_mounted(void)
Definition: audio_device.h:586
bool tud_audio_n_clear_ep_in_ff(uint8_t func_id)
Definition: audio_device.c:903
static uint16_t tud_audio_read(void *buffer, uint16_t bufsize)
Definition: audio_device.h:600
TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift)
Definition: audio_device.c:495
uint16_t tud_audio_n_write(uint8_t func_id, const void *data, uint16_t len)
Write data to EP in buffer.
Definition: audio_device.c:897
static uint16_t tud_audio_available(void)
Definition: audio_device.h:595
void audiod_reset(uint8_t rhport)
uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void *data, uint16_t len)
Definition: audio_device.c:940
bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting)
Definition: audio_device.c:459
static uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void *data, uint16_t len)
Definition: audio_device.h:674
void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t *feedback_param)
Definition: audio_device.c:483
uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles)
static bool tud_audio_clear_rx_support_ff(uint8_t ff_idx)
Definition: audio_device.h:619
tu_fifo_t * tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx)
Definition: audio_device.c:946
static bool tud_audio_clear_ep_out_ff(void)
Definition: audio_device.h:605
bool tud_audio_feedback_format_correction_cb(uint8_t func_id)
Definition: audio_device.c:489
bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request)
Definition: audio_device.c:565
bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff)
Definition: audio_device.c:522
static bool tud_audio_clear_ep_in_ff(void)
Definition: audio_device.h:650
bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx)
Definition: audio_device.c:934
bool tud_audio_n_clear_ep_out_ff(uint8_t func_id)
Definition: audio_device.c:648
bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx)
Definition: audio_device.c:664
static uint16_t tud_audio_available_support_ff(uint8_t ff_idx)
Definition: audio_device.h:624
static bool tud_audio_fb_set(uint32_t feedback)
Definition: audio_device.h:695
uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id)
Definition: audio_device.c:919
uint16_t tud_audio_n_available(uint8_t func_id)
Definition: audio_device.c:636
bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request)
Definition: audio_device.c:508
static tu_fifo_t * tud_audio_get_tx_support_ff(uint8_t ff_idx)
Definition: audio_device.h:679
bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request)
Definition: audio_device.c:515
uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void *buffer, uint16_t bufsize)
Definition: audio_device.c:676
bool tud_audio_n_mounted(uint8_t func_id)
Definition: audio_device.c:622
bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff)
Definition: audio_device.c:540
static uint16_t tud_audio_flush_tx_support_ff(void)
Definition: audio_device.h:664
bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff)
Definition: audio_device.c:531
static tu_fifo_t * tud_audio_get_ep_in_ff(void)
Definition: audio_device.h:655
@ AUDIO_FEEDBACK_METHOD_FIFO_COUNT
Definition: audio_device.h:525
@ AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED
Definition: audio_device.h:522
@ AUDIO_FEEDBACK_METHOD_DISABLED
Definition: audio_device.h:521
@ AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2
Definition: audio_device.h:524
@ AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT
Definition: audio_device.h:523
uint8_t const * buffer
Definition: midi_device.h:100
uint32_t bufsize
Definition: midi_device.h:95
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
xfer_result_t
Definition: tusb_types.h:236
CFG_TUH_MEM_ALIGN tusb_control_request_t request
Definition: usbh.c:259
volatile uint8_t stage
Definition: usbh.c:265