Merge pull request #2 from kasjer/kasjer/uac2

UAC2 pre-master
This commit is contained in:
PanRe 2020-09-28 14:23:58 +02:00 committed by GitHub
commit 2196b0724f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 359 additions and 96 deletions

View File

@ -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

View File

@ -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

View File

@ -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, bufsize);
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
{
#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);
}

View File

@ -377,6 +377,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \
TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay)
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */
#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7
#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \
TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval
// AUDIO simple descriptor (UAC2) for 1 microphone input
// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source
@ -426,6 +431,56 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
// AUDIO simple descriptor (UAC2) for mono speaker
// - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source
#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\
+ TUD_AUDIO_DESC_STD_AC_LEN\
+ TUD_AUDIO_DESC_CS_AC_LEN\
+ TUD_AUDIO_DESC_CLK_SRC_LEN\
+ TUD_AUDIO_DESC_INPUT_TERM_LEN\
+ TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
+ TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
+ TUD_AUDIO_DESC_CS_AS_INT_LEN\
+ TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
+ TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
+ TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN)
#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \
/* Standard Interface Association Descriptor (IAD) */\
TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\
/* Clock Source Descriptor(4.7.2.1) */\
TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\
/* Input Terminal Descriptor(4.7.2.4) */\
TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
/* Output Terminal Descriptor(4.7.2.5) */\
TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
/* Feature Unit Descriptor(4.7.2.8) */\
TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\
/* Standard AS Interface Descriptor(4.9.1) */\
/* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\
/* Standard AS Interface Descriptor(4.9.1) */\
/* Interface 1, Alternate 1 - alternate interface for data streaming */\
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\
/* Class-Specific AS Interface Descriptor(4.9.2) */\
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\
//------------- TUD_USBTMC/USB488 -------------//
#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC)
#define TUD_USBTMC_APP_SUBCLASS 0x03u

View File

@ -136,6 +136,7 @@ typedef struct {
uint8_t * buffer;
uint16_t total_len;
uint16_t max_size;
uint8_t interval;
} xfer_ctl_t;
// EP size and transfer type report
@ -440,7 +441,7 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
// For ISO endpoint set correct odd/even bit for next frame.
if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0)
if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1)
{
// Take odd/even bit from frame counter.
uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos));
@ -457,6 +458,12 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk);
out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
if ((out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP) == USB_OTG_DOEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1)
{
// Take odd/even bit from frame counter.
uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos));
out_ep[epnum].DOEPCTL |= (odd_frame_now ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DOEPCTL_SODDFRM_Msk);
}
}
}
@ -608,6 +615,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
xfer->max_size = desc_edpt->wMaxPacketSize.size;
xfer->interval = desc_edpt->bInterval;
if(dir == TUSB_DIR_OUT)
{
@ -809,20 +817,7 @@ static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall)
*/
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
{
USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
dcd_edpt_disable(rhport, ep_addr, false);
// if (dir == TUSB_DIR_IN)
// {
// uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos;
// uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos;
// // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss.
// TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,);
// _allocated_fifo_words -= fifo_size;
// }
}
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
@ -1241,34 +1236,43 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration
// Determine number of used out EPs of current configuration and size of two biggest out EPs
uint8_t nUsedOutEPs = 0, cnt_ep, cnt_tt;
bool tmp;
uint16_t sz[2] = {0, 0};
uint16_t fifo_depth;
for (cnt_ep = 0; cnt_ep < EP_MAX; cnt_ep++)
{
tmp = false;
for (cnt_tt = 0; cnt_tt <= TUSB_XFER_INTERRUPT; cnt_tt++)
{
tmp |= report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt];
if (report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt])
{
nUsedOutEPs++;
break;
}
}
nUsedOutEPs += tmp;
if (sz[0] < report.ep_size[cnt_ep][TUSB_DIR_OUT])
fifo_depth = report.ep_size[cnt_ep][TUSB_DIR_OUT] / 4 + 1;
if (sz[0] < fifo_depth)
{
sz[1] = sz[0];
sz[0] = report.ep_size[cnt_ep][TUSB_DIR_OUT];
sz[0] = fifo_depth;
}
else if (sz[1] < report.ep_size[cnt_ep][TUSB_DIR_OUT])
{
sz[1] = fifo_depth;
}
}
// For configuration use the approach as explained in bus_reset()
_allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work
_allocated_fifo_words = 13 + 1 + 1 + 2 * nUsedOutEPs + sz[0] + sz[1] + 2; // again, i do not really know why we need + 2 but otherwise it does not work
usb_otg->GRXFSIZ = _allocated_fifo_words;
// Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word )
usb_otg->DIEPTXF0_HNPTXFSIZ = (report.ep_size[0][TUSB_DIR_IN]/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words;
fifo_depth = report.ep_size[0][TUSB_DIR_IN] / 4;
fifo_depth = tu_max16(16, fifo_depth);
usb_otg->DIEPTXF0_HNPTXFSIZ = (fifo_depth << USB_OTG_TX0FD_Pos) | _allocated_fifo_words;
_allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders
_allocated_fifo_words += fifo_depth;
// For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that:
// - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more.
@ -1307,11 +1311,14 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration
// Required space by EPs in words, number of bulk and control EPs
uint16_t ep_sz_total = 0;
// Number of bulk and control EPs
uint8_t nbc = 0;
// EP0 is already taken care of so exclude that here
for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++)
{
ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders!
fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4; // Since we need full words take care of remainders!
if (fifo_depth > 0 && fifo_depth < 16) fifo_depth = 16; // Minimum FIFO depth is 16
ep_sz_total += fifo_depth;
nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]);
}
@ -1321,8 +1328,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration
return false;
}
uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused
uint16_t fifo_size;
uint16_t extra_space = nbc > 0 ? (fifo_remaining - ep_sz_total) / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused
// Setup FIFOs
for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++)
@ -1330,9 +1336,10 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration
// If EP is used
if (report.ep_size[cnt_ep][TUSB_DIR_IN] > 0)
{
fifo_size = report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0) + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0);
usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words;
_allocated_fifo_words += fifo_size;
fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4 + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0);
fifo_depth = tu_max16(16, fifo_depth);
usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_depth << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words;
_allocated_fifo_words += fifo_depth;
}
}