From ef879e8a8a43dfa34160f50d7f432c3140dec7fa Mon Sep 17 00:00:00 2001 From: Valentin Milea Date: Mon, 6 Dec 2021 18:49:58 +0200 Subject: [PATCH 1/3] Support disabling feedback format correction #1234 --- src/class/audio/audio_device.c | 3 ++- src/class/audio/audio_device.h | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d9f2e284e..a461e97c5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2248,12 +2248,13 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically +// unless format correction is disabled. bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value -#if !TUD_OPT_HIGH_SPEED +#if !TUD_OPT_HIGH_SPEED && !CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; // For FS format is 10.14 diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5a469523c..731fd6c01 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -186,6 +186,11 @@ #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif +// Disable/enable conversion from 16.16 to 10.14 format on high-speed devices. See tud_audio_n_fb_set(). +#ifndef CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION +#define CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 +#endif + // Audio interrupt control EP size - disabled if 0 #ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN #define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) @@ -458,6 +463,11 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // 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. +// +// Note that the USB Audio 2.0 driver on Windows 10 is not following the spec and expects 16.16 +// format for FS. You can define CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION=1 as a workaround +// to transmit the feedback value unchanged. Be aware that this might break feedback on other hosts, +// though at least on Linux the ALSA driver will happily accept either format. bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); static inline bool tud_audio_fb_set(uint32_t feedback); #endif From a284e438f1952315631f354dee2b30b264afb324 Mon Sep 17 00:00:00 2001 From: Valentin Milea Date: Fri, 7 Jan 2022 15:02:52 +0200 Subject: [PATCH 2/3] Disable feedback format correction by default #1234 --- src/class/audio/audio_device.c | 6 ++---- src/class/audio/audio_device.h | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a461e97c5..5ffc9b0dc 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2247,14 +2247,12 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -// Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically -// unless format correction is disabled. bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value -#if !TUD_OPT_HIGH_SPEED && !CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION && !TUD_OPT_HIGH_SPEED uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; // For FS format is 10.14 @@ -2264,7 +2262,7 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) // 4th byte is needed to work correctly with MS Windows *fb = 0; #else - // For HS format is 16.16 as originally demanded + // Send value as-is, caller will choose the appropriate format _audiod_fct[func_id].fb_val = feedback; #endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 731fd6c01..f406cf281 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -186,9 +186,9 @@ #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -// Disable/enable conversion from 16.16 to 10.14 format on high-speed devices. See tud_audio_n_fb_set(). -#ifndef CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION -#define CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 +// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 #endif // Audio interrupt control EP size - disabled if 0 @@ -459,15 +459,15 @@ TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_byte #if CFG_TUD_AUDIO_ENABLE_EP_OUT && 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. + +// 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. // -// Note that the USB Audio 2.0 driver on Windows 10 is not following the spec and expects 16.16 -// format for FS. You can define CFG_TUD_AUDIO_DISABLE_FEEDBACK_FORMAT_CORRECTION=1 as a workaround -// to transmit the feedback value unchanged. Be aware that this might break feedback on other hosts, -// though at least on Linux the ALSA driver will happily accept either format. +// 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, +// 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, then tinyusb +// expects 16.16 format and handles the conversion to 10.14 on FS. +// +// 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 macOS it seems the +// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); static inline bool tud_audio_fb_set(uint32_t feedback); #endif From 45fb60e883b62a550420d88426e443d0a2e7dd45 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 16 Jan 2022 12:12:57 +0700 Subject: [PATCH 3/3] update format correction with actual bus speed --- src/class/audio/audio_device.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 5ffc9b0dc..d21980060 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2252,18 +2252,23 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION && !TUD_OPT_HIGH_SPEED - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION + if ( TUSB_SPEED_FULL == tud_speed_get() ) + { + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + }else #else - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].fb_val = feedback; + { + // Send value as-is, caller will choose the appropriate format + _audiod_fct[func_id].fb_val = feedback; + } #endif // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value