Fix audiod_get_AS_interface_index in audio class.

Enhance uac2_headset example with multiple sample rates.
Add macro to calculate EP size.
This commit is contained in:
MasterPhi
2021-06-29 22:40:21 +02:00
parent 681a61d479
commit 6e9da70c18
6 changed files with 77 additions and 36 deletions

View File

@@ -34,9 +34,11 @@
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
#ifndef AUDIO_SAMPLE_RATE
#define AUDIO_SAMPLE_RATE 48000
#endif
// List of supported sample rates
const uint32_t sample_rates[] = {44100, 48000, 88200, 96000};
uint32_t current_sample_rate = 44100;
#define N_SAMPLE_RATES (sizeof(sample_rates) / 4)
/* Blink pattern
* - 25 ms : streaming data
@@ -166,24 +168,30 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t
{
TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
// Example supports only single frequency, same value will be used for current value and range
if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ)
{
if (request->bRequest == AUDIO_CS_REQ_CUR)
{
TU_LOG2("Clock get current freq %u\r\n", AUDIO_SAMPLE_RATE);
TU_LOG1("Clock get current freq %u\r\n", current_sample_rate);
audio_control_cur_4_t curf = { tu_htole32(AUDIO_SAMPLE_RATE) };
audio_control_cur_4_t curf = { tu_htole32(current_sample_rate) };
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf));
}
else if (request->bRequest == AUDIO_CS_REQ_RANGE)
{
audio_control_range_4_n_t(1) rangef =
audio_control_range_4_n_t(N_SAMPLE_RATES) rangef =
{
.wNumSubRanges = tu_htole16(1),
.subrange[0] = { tu_htole32(AUDIO_SAMPLE_RATE), tu_htole32(AUDIO_SAMPLE_RATE), 0}
.wNumSubRanges = tu_htole16(N_SAMPLE_RATES)
};
TU_LOG2("Clock get freq range (%d, %d, %d)\r\n", (int)rangef.subrange[0].bMin, (int)rangef.subrange[0].bMax, (int)rangef.subrange[0].bRes);
TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES);
for(uint8_t i = 0; i < N_SAMPLE_RATES; i++)
{
rangef.subrange[i].bMin = sample_rates[i];
rangef.subrange[i].bMax = sample_rates[i];
rangef.subrange[i].bRes = 0;
TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes);
}
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef));
}
}
@@ -191,7 +199,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t
request->bRequest == AUDIO_CS_REQ_CUR)
{
audio_control_cur_1_t cur_valid = { .bCur = 1 };
TU_LOG2("Clock get is valid %u\r\n", cur_valid.bCur);
TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur);
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid));
}
TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n",
@@ -199,6 +207,32 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t
return false;
}
// Helper for clock set requests
static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf)
{
(void)rhport;
TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT);
TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR);
if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ)
{
TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t));
current_sample_rate = ((audio_control_cur_4_t *)buf)->bCur;
TU_LOG1("Clock set current freq: %d\r\n", current_sample_rate);
return true;
}
else
{
TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n",
request->bEntityID, request->bControlSelector, request->bRequest);
return false;
}
}
// Helper for feature unit get requests
static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request)
{
@@ -207,7 +241,7 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req
if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR)
{
audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] };
TU_LOG2("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur);
TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur);
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1));
}
else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request->bControlSelector == AUDIO_FU_CTRL_VOLUME)
@@ -218,14 +252,14 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req
.wNumSubRanges = tu_htole16(1),
.subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) }
};
TU_LOG2("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber,
TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber,
range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256);
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol));
}
else if (request->bRequest == AUDIO_CS_REQ_CUR)
{
audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) };
TU_LOG2("Get channel %u volume %u dB\r\n", request->bChannelNumber, cur_vol.bCur);
TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256);
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol));
}
}
@@ -249,7 +283,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req
mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur;
TU_LOG2("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]);
TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]);
return true;
}
@@ -259,7 +293,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req
volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur;
TU_LOG2("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256);
TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256);
return true;
}
@@ -299,7 +333,8 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
return tud_audio_feature_unit_set_request(rhport, request, buf);
if (request->bEntityID == UAC2_ENTITY_CLOCK)
return tud_audio_clock_set_request(rhport, request, buf);
TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n",
request->bEntityID, request->bControlSelector, request->bRequest);