summaryrefslogtreecommitdiff
path: root/src/class
diff options
context:
space:
mode:
Diffstat (limited to 'src/class')
-rw-r--r--src/class/audio/audio.h4
-rw-r--r--src/class/audio/audio_device.c232
-rw-r--r--src/class/audio/audio_device.h99
3 files changed, 268 insertions, 67 deletions
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h
index 5e64549ed..0027217cb 100644
--- a/src/class/audio/audio.h
+++ b/src/class/audio/audio.h
@@ -497,11 +497,13 @@ typedef enum
/// Isochronous End Point Attributes
typedef enum
{
+ TUSB_ISO_EP_ATT_NO_SYNC = 0x00,
TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04,
TUSB_ISO_EP_ATT_ADAPTIVE = 0x08,
TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C,
TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point
- TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point
+ TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point
+ TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback
} tusb_iso_ep_attribute_t;
/// Audio Class-Control Values UAC2
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index ebb8434cd..1b9cfe13a 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -46,8 +46,22 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+
+#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
+#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT
+#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX
+#endif
+#endif
+
+#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
+#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT
+#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX
+#endif
+#endif
+
typedef struct
{
+ uint8_t rhport;
uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function
#if CFG_TUD_AUDIO_EPSIZE_IN
@@ -80,18 +94,18 @@ typedef struct
// FIFO
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
- tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX];
- CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE * CFG_TUD_AUDIO_TX_ITEMSIZE];
+ tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT];
+ CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE];
#if CFG_FIFO_MUTEX
- osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX];
+ osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT];
#endif
#endif
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
- tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX];
- CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE * CFG_TUD_AUDIO_RX_ITEMSIZE];
+ tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT];
+ CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE];
#if CFG_FIFO_MUTEX
- osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX];
+ osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT];
#endif
#endif
@@ -107,10 +121,9 @@ typedef struct
#if CFG_TUD_AUDIO_EPSIZE_OUT
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here)
- // TODO: required?
- //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- // uint16_t fb_val; // Feedback value for asynchronous mode!
- //#endif
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+ uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
+#endif
#endif
@@ -134,7 +147,7 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO];
extern const uint16_t tud_audio_desc_lengths[];
#if CFG_TUD_AUDIO_EPSIZE_OUT
-static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize);
+static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize);
#endif
#if CFG_TUD_AUDIO_EPSIZE_IN
@@ -189,7 +202,7 @@ bool tud_audio_n_mounted(uint8_t itf)
//--------------------------------------------------------------------+
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
-
+#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId)
{
TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX);
@@ -204,10 +217,25 @@ uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t
void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId)
{
- TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX);
+ TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, );
tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]);
}
+#else
+uint16_t tud_audio_n_available(uint8_t itf)
+{
+ return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]);
+}
+uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize)
+{
+ return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize);
+}
+
+void tud_audio_n_read_flush (uint8_t itf)
+{
+ tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]);
+}
+#endif
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
@@ -282,12 +310,14 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t*
// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0
#if CFG_TUD_AUDIO_RX_FIFO_SIZE
+#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize)
{
(void) rhport;
// We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel
- if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) {
+ if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0)
+ {
return false;
}
@@ -316,7 +346,23 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a
chId = 0;
}
}
-} }
+ return true;
+}
+#else
+static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *audio, uint8_t *buffer, uint16_t bufsize)
+{
+ (void) rhport;
+
+ // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel
+ if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0)
+ {
+ return false;
+ }
+
+ tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize);
+ return true;
+}
+#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE
//--------------------------------------------------------------------+
@@ -334,9 +380,9 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a
* \param[in] len: # of array elements to copy
* \return Number of bytes actually written
*/
-
+#if CFG_TUD_AUDIO_EPSIZE_IN
+#if !CFG_TUD_AUDIO_TX_FIFO_SIZE
/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers
-#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE
uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len)
{
audiod_interface_t* audio = &_audiod_itf[itf];
@@ -363,11 +409,23 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t
// Return number of bytes written
return len;
}
-#endif
-
*/
-#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
+#else
+
+#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1
+uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len)
+{
+ {
+ audiod_interface_t* audio = &_audiod_itf[itf];
+ if (audio->p_desc == NULL)
+ {
+ return 0;
+ }
+ return tu_fifo_write_n(&audio->tx_ff[0], data, len);
+ }
+}
+#else
uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len)
{
audiod_interface_t* audio = &_audiod_itf[itf];
@@ -379,6 +437,23 @@ uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, ui
}
#endif
+static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied);
+
+uint16_t tud_audio_n_write_flush(uint8_t itf)
+{
+ audiod_interface_t *audio = &_audiod_itf[itf];
+ if (audio->p_desc == NULL) {
+ return 0;
+ }
+
+ uint16_t n_bytes_copied;
+ TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied));
+ return n_bytes_copied;
+}
+
+#endif
+#endif
+
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize)
{
@@ -475,6 +550,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_
#endif //CFG_TUD_AUDIO_EPSIZE_IN
#if CFG_TUD_AUDIO_TX_FIFO_SIZE
+#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE)
static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio)
{
// We encode directly into IN EP's buffer - abort if previous transfer not complete
@@ -482,15 +558,15 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
// Determine amount of samples
uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX;
- uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]);
+ uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE;
uint16_t nBytesToSend;
uint8_t cntChannel;
for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++)
{
- if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend)
+ if (audio->tx_ff[cntChannel].count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend)
{
- nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count;
+ nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count * CFG_TUD_AUDIO_TX_ITEMSIZE;
}
}
@@ -522,7 +598,7 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++)
{
// Get sample from buffer
- tu_fifo_read(&audio->tx_ff[cntChannel], &sample);
+ tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE);
// Put it into EP's buffer - Let alignment problems be handled by memcpy
memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX);
@@ -537,23 +613,80 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
return true;
}
+#else
+static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio)
+{
+ // We encode directly into IN EP's buffer - abort if previous transfer not complete
+ TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in));
+
+ // Determine amount of samples
+ uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]);
+
+ nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN);
+
+ // Check if there is enough
+ if (nByteCount == 0)
+ {
+ return true;
+ }
+
+ nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount);
+ audio->epin_buf_cnt = nByteCount;
+
+ return true;
+}
+#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE)
+
#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE
// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
-static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio)
+static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio)
{
- (void) rhport;
- (void) audio;
+ uint8_t fb[4];
+ uint16_t len;
- // Here we need to return the feedback value
-#error RETURN YOUR FEEDBACK VALUE HERE!
+ if (audio->fb_val == 0)
+ {
+ len = 0;
+ return true;
+ }
+ else
+ {
+ len = 4;
+ // Here we need to return the feedback value
+ if (rhport == 0)
+ {
+ // For FS format is 10.14
+ fb[0] = (audio->fb_val >> 2) & 0xFF;
+ fb[1] = (audio->fb_val >> 10) & 0xFF;
+ fb[2] = (audio->fb_val >> 18) & 0xFF;
+ // 4th byte is needed to work correctly with MS Windows
+ fb[3] = 0;
+ }
+ else
+ {
+ // For HS format is 16.16
+ fb[0] = (audio->fb_val >> 0) & 0xFF;
+ fb[1] = (audio->fb_val >> 8) & 0xFF;
+ fb[2] = (audio->fb_val >> 16) & 0xFF;
+ fb[3] = (audio->fb_val >> 24) & 0xFF;
+ }
+ return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len);
+ }
- if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
- return 0;
}
+//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio)
+//{
+// (void) rhport;
+// (void) audio;
+//
+// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
+// return 0;
+//}
+
#endif
// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send
@@ -586,7 +719,6 @@ static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uin
//--------------------------------------------------------------------+
void audiod_init(void)
{
- uint8_t cnt;
tu_memclr(_audiod_itf, sizeof(_audiod_itf));
for(uint8_t i=0; i<CFG_TUD_AUDIO; i++)
@@ -595,9 +727,9 @@ void audiod_init(void)
// Initialize TX FIFOs if required
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++)
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++)
{
- tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true);
+ tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true);
#if CFG_FIFO_MUTEX
tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt]));
#endif
@@ -605,9 +737,9 @@ void audiod_init(void)
#endif
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++)
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++)
{
- tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true);
+ tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true);
#if CFG_FIFO_MUTEX
tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt]));
#endif
@@ -632,16 +764,15 @@ void audiod_reset(uint8_t rhport)
audiod_interface_t* audio = &_audiod_itf[i];
tu_memclr(audio, ITF_MEM_RESET_SIZE);
- uint8_t cnt;
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++)
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++)
{
tu_fifo_clear(&audio->tx_ff[cnt]);
}
#endif
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++)
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++)
{
tu_fifo_clear(&audio->rx_ff[cnt]);
}
@@ -673,6 +804,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
if (!_audiod_itf[i].p_desc)
{
_audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one
+ _audiod_itf[i].rhport = rhport;
break;
}
}
@@ -818,7 +950,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
}
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback
+ if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback
{
_audiod_itf[idxDriver].ep_fb = ep_addr;
@@ -1115,13 +1247,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
// Transmission of feedback EP finished
if (_audiod_itf[idxDriver].ep_fb == ep_addr)
{
- if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver]))
- {
- // Load with ZLP
- return usbd_edpt_xfer(rhport, ep_addr, NULL, 0);
- }
+ if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
- return true;
+ return audio_fb_send(rhport, &_audiod_itf[idxDriver]);
}
#endif
#endif
@@ -1303,4 +1431,16 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver)
return false;
}
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback)
+{
+ audiod_interface_t *audio = &_audiod_itf[0];
+
+ audio->fb_val = feedback;
+ TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true);
+
+ return audio_fb_send(rhport, audio);
+}
+#endif
+
#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO
diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h
index 11f444daa..f4029a84c 100644
--- a/src/class/audio/audio_device.h
+++ b/src/class/audio/audio_device.h
@@ -119,6 +119,7 @@
#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1
#endif
+#ifndef CFG_TUD_AUDIO_TX_ITEMSIZE
#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1
#define CFG_TUD_AUDIO_TX_ITEMSIZE 1
#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2
@@ -126,6 +127,11 @@
#else
#define CFG_TUD_AUDIO_TX_ITEMSIZE 4
#endif
+#endif
+
+#if CFG_TUD_AUDIO_TX_ITEMSIZE < CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX
+#error FIFO element size (ITEMSIZE) must not be smaller then sample size
+#endif
#endif
@@ -170,9 +176,15 @@ extern "C" {
bool tud_audio_n_mounted (uint8_t itf);
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
+#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId);
uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize);
void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId);
+#else
+uint16_t tud_audio_n_available (uint8_t itf);
+uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize);
+void tud_audio_n_read_flush (uint8_t itf);
+#endif
#endif
/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers
@@ -182,7 +194,12 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t
*/
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
+#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1
uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len);
+#else
+uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len);
+#endif
+uint16_t tud_audio_n_write_flush(uint8_t itf);
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
@@ -196,23 +213,27 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer,
// Application API (Interface0)
//--------------------------------------------------------------------+
-inline bool tud_audio_mounted (void);
+static inline bool tud_audio_mounted (void);
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
-inline uint16_t tud_audio_available (void);
-inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize);
-inline void tud_audio_read_flush (void);
+static inline uint16_t tud_audio_available (void);
+static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize);
+static inline void tud_audio_read_flush (void);
#endif
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
-inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize);
+#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1
+static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize);
+#else
+static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize);
+#endif
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
-inline uint32_t tud_audio_int_ctr_available (void);
-inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize);
-inline void tud_audio_int_ctr_read_flush (void);
-inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize);
+static inline uint32_t tud_audio_int_ctr_available (void);
+static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize);
+static inline void tud_audio_int_ctr_read_flush (void);
+static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize);
#endif
// Buffer control EP data and schedule a transmit
@@ -238,6 +259,11 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_
#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport);
+// User code should call this function with feedback value in 16.16 format for FS and HS.
+// Value will be corrected for FS to 10.14 format automatically.
+// (see Universal Serial Bus Specification Revision 2.0 5.12.4.2).
+// Feedback value will be sent at FB endpoint interval till it's changed.
+bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback);
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
@@ -269,52 +295,85 @@ TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_reque
// Inline Functions
//--------------------------------------------------------------------+
-inline bool tud_audio_mounted(void)
+static inline bool tud_audio_mounted(void)
{
return tud_audio_n_mounted(0);
}
-#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
-inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used
+#if CFG_TUD_AUDIO_EPSIZE_IN
+#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1
+static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used
+{
+ return tud_audio_n_write(0, channelId, buffer, n_bytes);
+}
+#else
+static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used
+{
+ return tud_audio_n_write(0, buffer, n_bytes);
+}
+#endif
+
+static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used
{
- return tud_audio_n_write(0, channelId, buffer, bufsize);
+#if CFG_TUD_AUDIO_TX_FIFO_SIZE
+ return tud_audio_n_write_flush(0);
+#else
+ return 0;
+#endif
}
#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
-inline uint16_t tud_audio_available(uint8_t channelId)
+#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
+static inline uint16_t tud_audio_available(uint8_t channelId)
{
return tud_audio_n_available(0, channelId);
}
-inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize)
+static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize)
{
return tud_audio_n_read(0, channelId, buffer, bufsize);
}
-inline void tud_audio_read_flush(uint8_t channelId)
+static inline void tud_audio_read_flush(uint8_t channelId)
{
tud_audio_n_read_flush(0, channelId);
}
+#else
+static inline uint16_t tud_audio_available(void)
+{
+ return tud_audio_n_available(0);
+}
+
+static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize)
+{
+ return tud_audio_n_read(0, buffer, bufsize);
+}
+
+static inline void tud_audio_read_flush(void)
+{
+ tud_audio_n_read_flush(0);
+}
+#endif
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
-inline uint16_t tud_audio_int_ctr_available(void)
+static inline uint16_t tud_audio_int_ctr_available(void)
{
return tud_audio_int_ctr_n_available(0);
}
-inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize)
+static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize)
{
return tud_audio_int_ctr_n_read(0, buffer, bufsize);
}
-inline void tud_audio_int_ctr_read_flush(void)
+static inline void tud_audio_int_ctr_read_flush(void)
{
return tud_audio_int_ctr_n_read_flush(0);
}
-inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize)
+static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize)
{
return tud_audio_int_ctr_n_write(0, buffer, bufsize);
}