summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/unit-test/test/host/audio/test_audio_host.c166
1 files changed, 163 insertions, 3 deletions
diff --git a/test/unit-test/test/host/audio/test_audio_host.c b/test/unit-test/test/host/audio/test_audio_host.c
index 2b0f2fa3d..f02c44095 100644
--- a/test/unit-test/test/host/audio/test_audio_host.c
+++ b/test/unit-test/test/host/audio/test_audio_host.c
@@ -199,9 +199,11 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s) {
12, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL, _id, U16_TO_U8S_LE(_type), 0, _channels, \
U16_TO_U8S_LE(AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED), 0, 0
-#define TEST_UAC1_FEATURE_UNIT(_id, _source_id) \
- 9, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT, _id, _source_id, 2, \
- U16_TO_U8S_LE(AUDIO10_FU_CONTROL_BM_VOLUME), 0
+#define TEST_UAC1_FEATURE_UNIT_CTRL(_id, _source_id, _controls) \
+ 9, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT, _id, _source_id, 2, U16_TO_U8S_LE(_controls), 0
+
+#define TEST_UAC1_FEATURE_UNIT(_id, _source_id) \
+ TEST_UAC1_FEATURE_UNIT_CTRL(_id, _source_id, AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME)
#define TEST_UAC1_OUTPUT_TERM(_id, _type, _source_id) \
9, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL, _id, U16_TO_U8S_LE(_type), 0, _source_id, 0
@@ -311,6 +313,19 @@ static const uint8_t playback_fu_before_terminal[] = {
TEST_UAC1_CS_DATA_EP,
};
+static const uint8_t playback_fu_without_mute_volume[] = {
+ TEST_UAC1_AC_HEADER,
+ TEST_UAC1_FEATURE_UNIT_CTRL(PLAYBACK_FU, PLAYBACK_INPUT_TERM, AUDIO10_FU_CONTROL_BM_BASS),
+ TEST_UAC1_INPUT_TERM(PLAYBACK_INPUT_TERM, AUDIO_TERM_TYPE_USB_STREAMING, 2),
+ TEST_UAC1_OUTPUT_TERM(PLAYBACK_OUTPUT_TERM, AUDIO_TERM_TYPE_OUT_HEADPHONES, PLAYBACK_FU),
+ TEST_UAC1_AS_ALT0,
+ TEST_UAC1_AS_INTERFACE(1, 1),
+ TEST_UAC1_AS_GENERAL(PLAYBACK_INPUT_TERM),
+ TEST_UAC1_FORMAT(2, 2, 16, 48000),
+ TEST_UAC1_DATA_EP(0x01, TUSB_ISO_EP_ATT_ADAPTIVE, 192, 1),
+ TEST_UAC1_CS_DATA_EP,
+};
+
static const uint8_t capture_fu_before_usb_output[] = {
TEST_UAC1_AC_HEADER,
TEST_UAC1_INPUT_TERM(CAPTURE_INPUT_TERM, AUDIO_TERM_TYPE_IN_GENERIC_MIC, 1),
@@ -504,6 +519,13 @@ static void complete_control_xfer(tusb_xfer_result_t result) {
xfer.complete_cb(&xfer);
}
+static void complete_control_xfer_with_u16(uint16_t value) {
+ TEST_ASSERT_NOT_NULL(control_xfer.buffer);
+ tu_unaligned_write16(control_xfer.buffer, tu_htole16(value));
+ control_xfer.actual_len = 2;
+ complete_control_xfer(XFER_RESULT_SUCCESS);
+}
+
void setUp(void) {
interface_set_result = true;
memset(&interface_xfer, 0, sizeof(interface_xfer));
@@ -553,7 +575,24 @@ static void open_descriptors(const uint8_t *desc, uint16_t desc_len) {
static void mount_descriptors(const uint8_t *desc, uint16_t desc_len) {
open_descriptors(desc, desc_len);
TEST_ASSERT_TRUE(audioh_set_config(AUDIO_DEV_ADDR, AUDIO_AC_ITF));
+ while (!tuh_audio_mounted(0)) {
+ switch (control_request.bRequest) {
+ case AUDIO10_CS_REQ_GET_MIN:
+ complete_control_xfer_with_u16((uint16_t)(-90 * 256));
+ break;
+ case AUDIO10_CS_REQ_GET_MAX:
+ complete_control_xfer_with_u16(6 * 256);
+ break;
+ case AUDIO10_CS_REQ_GET_RES:
+ complete_control_xfer_with_u16(256);
+ break;
+ default:
+ TEST_FAIL_MESSAGE("Unexpected Feature Unit mount request");
+ break;
+ }
+ }
TEST_ASSERT_TRUE(tuh_audio_mounted(0));
+ control_xfer_count = 0;
}
void test_audio_host_ignores_explicit_feedback_endpoint(void) {
@@ -638,6 +677,22 @@ void test_audio_host_maps_duplex_fus_declared_before_usb_terminals(void) {
TEST_ASSERT_EQUAL_UINT8(CAPTURE_FU, tuh_audio_get_feature_unit_id(0, 1));
}
+void test_audio_host_reads_volume_ranges_for_both_streams_before_mount(void) {
+ const uint8_t feature_units[] = {PLAYBACK_FU, CAPTURE_FU};
+ open_descriptors(duplex_fus_before_usb_terminals, sizeof(duplex_fus_before_usb_terminals));
+
+ TEST_ASSERT_TRUE(audioh_set_config(AUDIO_DEV_ADDR, AUDIO_AC_ITF));
+ for (uint8_t i = 0; i < TU_ARRAY_SIZE(feature_units); i++) {
+ TEST_ASSERT_EQUAL_HEX8(AUDIO10_CS_REQ_GET_MIN, control_request.bRequest);
+ TEST_ASSERT_EQUAL_HEX16(tu_u16(feature_units[i], AUDIO_AC_ITF), tu_le16toh(control_request.wIndex));
+ complete_control_xfer_with_u16((uint16_t)(-90 * 256));
+ complete_control_xfer_with_u16(6 * 256);
+ complete_control_xfer_with_u16(256);
+ TEST_ASSERT_EQUAL(i == TU_ARRAY_SIZE(feature_units) - 1, tuh_audio_mounted(0));
+ }
+ TEST_ASSERT_EQUAL_UINT8(6, control_xfer_count);
+}
+
void test_audio_host_sets_sampling_frequency_after_each_stream_activation(void) {
mount_descriptors(capture_fu_before_usb_output, sizeof(capture_fu_before_usb_output));
@@ -836,6 +891,111 @@ void test_audio_host_uses_correct_feature_unit_widths_and_serializes_requests(vo
TEST_ASSERT_EQUAL_HEX32(0x5678, fu_cb_user_data);
}
+void test_audio_host_reads_and_caches_feature_unit_controls_before_mount(void) {
+ tuh_audio_volume_range_t range;
+ open_descriptors(playback_fu_before_terminal, sizeof(playback_fu_before_terminal));
+
+ TEST_ASSERT_TRUE(audioh_set_config(AUDIO_DEV_ADDR, AUDIO_AC_ITF));
+ TEST_ASSERT_FALSE(tuh_audio_mounted(0));
+ TEST_ASSERT_EQUAL_UINT8(1, control_xfer_count);
+ TEST_ASSERT_EQUAL_HEX8(AUDIO10_CS_REQ_GET_MIN, control_request.bRequest);
+ TEST_ASSERT_EQUAL_HEX16(tu_u16(AUDIO10_FU_CTRL_VOLUME, 0), tu_le16toh(control_request.wValue));
+ TEST_ASSERT_EQUAL_HEX16(tu_u16(PLAYBACK_FU, AUDIO_AC_ITF), tu_le16toh(control_request.wIndex));
+ TEST_ASSERT_EQUAL_UINT16(2, tu_le16toh(control_request.wLength));
+
+ complete_control_xfer_with_u16((uint16_t)(-90 * 256));
+ TEST_ASSERT_EQUAL_UINT8(2, control_xfer_count);
+ TEST_ASSERT_EQUAL_HEX8(AUDIO10_CS_REQ_GET_MAX, control_request.bRequest);
+ TEST_ASSERT_FALSE(tuh_audio_mounted(0));
+
+ complete_control_xfer_with_u16(6 * 256);
+ TEST_ASSERT_EQUAL_UINT8(3, control_xfer_count);
+ TEST_ASSERT_EQUAL_HEX8(AUDIO10_CS_REQ_GET_RES, control_request.bRequest);
+ TEST_ASSERT_FALSE(tuh_audio_mounted(0));
+
+ complete_control_xfer_with_u16(256);
+ TEST_ASSERT_TRUE(tuh_audio_mounted(0));
+ TEST_ASSERT_TRUE(tuh_audio_mute_supported(0, 0));
+ TEST_ASSERT_TRUE(tuh_audio_volume_range_get(0, 0, &range));
+ TEST_ASSERT_EQUAL_INT16(-90 * 256, range.min);
+ TEST_ASSERT_EQUAL_INT16(6 * 256, range.max);
+ TEST_ASSERT_EQUAL_UINT16(256, range.res);
+}
+
+void test_audio_host_mounts_with_mute_only_when_volume_range_fails(void) {
+ tuh_audio_volume_range_t range;
+ open_descriptors(playback_fu_before_terminal, sizeof(playback_fu_before_terminal));
+
+ TEST_ASSERT_TRUE(audioh_set_config(AUDIO_DEV_ADDR, AUDIO_AC_ITF));
+ complete_control_xfer_with_u16((uint16_t)(-40 * 256));
+ complete_control_xfer(XFER_RESULT_STALLED);
+
+ TEST_ASSERT_EQUAL_UINT8(2, control_xfer_count);
+ TEST_ASSERT_TRUE(tuh_audio_mounted(0));
+ TEST_ASSERT_TRUE(tuh_audio_mute_supported(0, 0));
+ TEST_ASSERT_FALSE(tuh_audio_volume_range_get(0, 0, &range));
+ TEST_ASSERT_EQUAL_UINT8(PLAYBACK_FU, tuh_audio_get_feature_unit_id(0, 0));
+}
+
+void test_audio_host_rejects_invalid_cached_volume_range(void) {
+ tuh_audio_volume_range_t range;
+ open_descriptors(playback_fu_before_terminal, sizeof(playback_fu_before_terminal));
+
+ TEST_ASSERT_TRUE(audioh_set_config(AUDIO_DEV_ADDR, AUDIO_AC_ITF));
+ complete_control_xfer_with_u16((uint16_t)(-20 * 256));
+ complete_control_xfer_with_u16(0);
+ complete_control_xfer_with_u16(0);
+
+ TEST_ASSERT_TRUE(tuh_audio_mounted(0));
+ TEST_ASSERT_TRUE(tuh_audio_mute_supported(0, 0));
+ TEST_ASSERT_FALSE(tuh_audio_volume_range_get(0, 0, &range));
+}
+
+void test_audio_host_ignores_feature_unit_without_master_mute_or_volume(void) {
+ tuh_audio_volume_range_t range;
+ mount_descriptors(playback_fu_without_mute_volume, sizeof(playback_fu_without_mute_volume));
+
+ TEST_ASSERT_EQUAL_UINT8(0, tuh_audio_get_feature_unit_id(0, 0));
+ TEST_ASSERT_FALSE(tuh_audio_mute_supported(0, 0));
+ TEST_ASSERT_FALSE(tuh_audio_volume_range_get(0, 0, &range));
+}
+
+void test_audio_host_typed_mute_and_volume_controls(void) {
+ bool mute = false;
+ int16_t volume = 0;
+ tuh_audio_volume_range_t range;
+ mount_descriptors(playback_fu_before_terminal, sizeof(playback_fu_before_terminal));
+
+ TEST_ASSERT_TRUE(tuh_audio_volume_range_get(0, 0, &range));
+ TEST_ASSERT_FALSE(tuh_audio_volume_set(0, 0, (int16_t)(range.max + 1), NULL, 0));
+
+ TEST_ASSERT_TRUE(tuh_audio_mute_set(0, 0, true, feature_unit_complete, 0x1234));
+ TEST_ASSERT_EQUAL_HEX8(AUDIO10_CS_REQ_SET_CUR, control_request.bRequest);
+ TEST_ASSERT_EQUAL_HEX16(tu_u16(AUDIO10_FU_CTRL_MUTE, 0), tu_le16toh(control_request.wValue));
+ TEST_ASSERT_EQUAL_UINT16(1, tu_le16toh(control_request.wLength));
+ TEST_ASSERT_EQUAL_HEX8(1, control_buffer[0]);
+ complete_control_xfer(XFER_RESULT_SUCCESS);
+
+ TEST_ASSERT_TRUE(tuh_audio_mute_get(0, 0, &mute, feature_unit_complete, 0x2345));
+ TEST_ASSERT_EQUAL_HEX8(AUDIO10_CS_REQ_GET_CUR, control_request.bRequest);
+ control_xfer.buffer[0] = 1;
+ control_xfer.actual_len = 1;
+ complete_control_xfer(XFER_RESULT_SUCCESS);
+ TEST_ASSERT_TRUE(mute);
+
+ TEST_ASSERT_TRUE(tuh_audio_volume_set(0, 0, -6 * 256, feature_unit_complete, 0x3456));
+ TEST_ASSERT_EQUAL_HEX16(tu_u16(AUDIO10_FU_CTRL_VOLUME, 0), tu_le16toh(control_request.wValue));
+ TEST_ASSERT_EQUAL_UINT16(2, tu_le16toh(control_request.wLength));
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(((uint8_t[]){0x00, 0xFA}), control_buffer, 2);
+ complete_control_xfer(XFER_RESULT_SUCCESS);
+
+ TEST_ASSERT_TRUE(tuh_audio_volume_get(0, 0, &volume, feature_unit_complete, 0x4567));
+ complete_control_xfer_with_u16((uint16_t)(-12 * 256));
+ TEST_ASSERT_EQUAL_INT16(-12 * 256, volume);
+ TEST_ASSERT_EQUAL_UINT8(4, fu_cb_count);
+ TEST_ASSERT_EQUAL_HEX32(0x4567, fu_cb_user_data);
+}
+
void test_audio_host_schedules_44100_hz_fractional_packets_with_max_packets_only(void) {
uint8_t samples[441 * 4] = {0};
mount_descriptors(playback_44100_max_packets_only, sizeof(playback_44100_max_packets_only));