summaryrefslogtreecommitdiff
path: root/src/class/audio
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-27 03:31:01 +0200
committerHiFiPHile <[email protected]>2026-08-27 10:34:34 +0200
commit178426720cbe2f170872cc1469329570d37726a3 (patch)
treea6b280b93ff8a4861065624c8761665a823bd4a0 /src/class/audio
parent6019e538125e9863a4fa4bcf0b026d3e639a1a4d (diff)
audio: normalize Feature Unit volume requests
Accept the defined silence value and round ordinary volume requests to the nearest supported resolution step within the cached range. Add tests for silence, clamping, and step alignment. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'src/class/audio')
-rw-r--r--src/class/audio/audio_host.c11
-rw-r--r--src/class/audio/audio_host.h4
2 files changed, 13 insertions, 2 deletions
diff --git a/src/class/audio/audio_host.c b/src/class/audio/audio_host.c
index ad2fd677f..c73e9f225 100644
--- a/src/class/audio/audio_host.c
+++ b/src/class/audio/audio_host.c
@@ -2592,7 +2592,16 @@ bool tuh_audio_volume_set(uint8_t idx, uint8_t stream_idx, int16_t volume, tuh_x
uintptr_t user_data) {
tuh_audio_volume_range_t range;
TU_VERIFY(tuh_audio_volume_range_get(idx, stream_idx, &range), false);
- TU_VERIFY(volume >= range.min && volume <= range.max, false);
+ if (volume != TUH_AUDIO_VOLUME_SILENCE) {
+ TU_VERIFY(volume >= range.min && volume <= range.max && range.res != 0, false);
+ const uint32_t offset = (uint32_t)((int32_t)volume - range.min);
+ const uint32_t steps = (offset + range.res / 2u) / range.res;
+ int32_t rounded = (int32_t)range.min + (int32_t)(steps * range.res);
+ if (rounded > range.max) {
+ rounded -= range.res;
+ }
+ volume = (int16_t)rounded;
+ }
return tuh_audio_feature_unit_set(idx, stream_idx, AUDIO10_FU_CTRL_VOLUME, 0, (uint16_t)volume, complete_cb,
user_data);
}
diff --git a/src/class/audio/audio_host.h b/src/class/audio/audio_host.h
index 42cf4b4e5..4807d376a 100644
--- a/src/class/audio/audio_host.h
+++ b/src/class/audio/audio_host.h
@@ -241,7 +241,9 @@ bool tuh_audio_feature_unit_get(uint8_t idx, uint8_t stream_idx, uint8_t control
uint16_t *value, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Master mute and volume controls. Capability and range information is cached
-// before tuh_audio_mount_cb() is invoked.
+// before tuh_audio_mount_cb() is invoked. Volume SET accepts
+// TUH_AUDIO_VOLUME_SILENCE or a value within the cached range; finite values
+// are rounded to the nearest resolution step measured from the range minimum.
bool tuh_audio_mute_set(uint8_t idx, uint8_t stream_idx, bool mute, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
bool tuh_audio_mute_get(uint8_t idx, uint8_t stream_idx, bool *mute, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
bool tuh_audio_volume_set(uint8_t idx, uint8_t stream_idx, int16_t volume, tuh_xfer_cb_t complete_cb,