Skip to content

Commit 016831a

Browse files
committed
fix(uac): improve uac compatibility for full-speed device
1 parent 907caa1 commit 016831a

File tree

3 files changed

+26
-9
lines changed

3 files changed

+26
-9
lines changed

host/class/uac/usb_host_uac/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
All notable changes to this component will be documented in this file.
44

5-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
7+
## [1.3.3] - 2025-11-4
8+
9+
### Changed
10+
11+
- Fixed a playback stuttering issue when bInterval was not equal to 1 in the full-speed device audio endpoint descriptor, and forced bInterval = 1 to make it compatible with these non-standard devices.
612

713
## [1.3.2] - 2025-10-21
814

host/class/uac/usb_host_uac/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## IDF Component Manager Manifest File
2-
version: "1.3.2"
2+
version: "1.3.3"
33
description: USB Host UAC driver
44
url: https://github.com/espressif/esp-usb/tree/master/host/class/uac/usb_host_uac
55
dependencies:

host/class/uac/usb_host_uac/uac_host.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,11 @@ static esp_err_t uac_host_interface_add(uac_device_t *uac_device, uint8_t iface_
739739

740740
usb_host_get_active_config_descriptor(uac_device->dev_hdl, &config_desc);
741741
UAC_GOTO_ON_FALSE(config_desc, ESP_ERR_INVALID_STATE, "No active configuration descriptor");
742+
// Query device speed once to decide whether to force bInterval for Full-Speed
743+
usb_device_info_t dev_info_local;
744+
usb_host_device_info(uac_device->dev_hdl, &dev_info_local);
745+
ESP_RETURN_ON_FALSE(dev_info_local.speed != USB_SPEED_LOW, ESP_ERR_NOT_SUPPORTED, TAG, "Low-Speed device not supported");
746+
const bool is_full_speed = (dev_info_local.speed == USB_SPEED_FULL);
742747
const size_t total_length = config_desc->wTotalLength;
743748
int iface_alt_offset = 0;
744749
int iface_alt_idx = 0;
@@ -803,6 +808,12 @@ static esp_err_t uac_host_interface_add(uac_device_t *uac_device, uint8_t iface_
803808
iface_alt->ep_addr = ep_desc->bEndpointAddress;
804809
iface_alt->ep_mps = ep_desc->wMaxPacketSize;
805810
iface_alt->ep_attr = ep_desc->bmAttributes;
811+
if (is_full_speed && ep_desc->bInterval != 1) {
812+
// Full-Speed isochronous endpoints must have bInterval = 1
813+
ESP_LOGW(TAG, "UAC Full-Speed device, Endpoint %d, bInterval %d, set to 1", USB_EP_DESC_GET_EP_NUM(ep_desc), ep_desc->bInterval);
814+
uint8_t *_bInterval = (uint8_t *) & (ep_desc->bInterval);
815+
*_bInterval = 1;
816+
}
806817
iface_alt->interval = ep_desc->bInterval;
807818
uac_iface->dev_info.type = (ep_desc->bEndpointAddress & UAC_EP_DIR_IN) ? UAC_STREAM_RX : UAC_STREAM_TX;
808819
uac_ac_feature_unit_desc_t *feature_unit_desc = _uac_host_device_find_feature_unit((uint8_t *)uac_device->cs_ac_desc,
@@ -823,7 +834,7 @@ static esp_err_t uac_host_interface_add(uac_device_t *uac_device, uint8_t iface_
823834
ESP_LOGD(TAG, "UAC %s Feature Unit ID %d, Volume Ch Map %02X, Mute Ch Map %02X", uac_iface->dev_info.type == UAC_STREAM_RX ? "RX" : "TX",
824835
feature_unit_desc->bUnitID, iface_alt->vol_ch_map, iface_alt->mute_ch_map);
825836
}
826-
ESP_LOGD(TAG, "UAC Endpoint 0x%02X, Max Packet Size %d, Attributes 0x%02X, Interval %d", ep_desc->bEndpointAddress, ep_desc->wMaxPacketSize, ep_desc->bmAttributes, ep_desc->bInterval);
837+
ESP_LOGD(TAG, "UAC Endpoint 0x%02X, Max Packet Size %d, Attributes 0x%02X, Interval %d", USB_EP_DESC_GET_EP_NUM(ep_desc), ep_desc->wMaxPacketSize, ep_desc->bmAttributes, ep_desc->bInterval);
827838
break;
828839
}
829840
case UAC_CS_ENDPOINT: {
@@ -1305,9 +1316,9 @@ static esp_err_t uac_host_interface_suspend(uac_iface_t *iface)
13051316
memcpy(&uac_request, &usb_request, sizeof(usb_setup_packet_t));
13061317
esp_err_t ret = uac_cs_request_set(iface->parent, &uac_request);
13071318
if (ret != ESP_OK) {
1308-
ESP_LOGW(TAG, "Set Interface %d-%d Failed", iface->dev_info.iface_num, 0);
1319+
ESP_LOGW(TAG, "Suspend Interface %d-%d Failed", iface->dev_info.iface_num, 0);
13091320
} else {
1310-
ESP_LOGI(TAG, "Set Interface %d-%d", iface->dev_info.iface_num, 0);
1321+
ESP_LOGI(TAG, "Suspend Interface %d-%d", iface->dev_info.iface_num, 0);
13111322
}
13121323

13131324
uint8_t ep_addr = iface->iface_alt[iface->cur_alt].ep_addr;
@@ -1353,16 +1364,16 @@ static esp_err_t uac_host_interface_resume(uac_iface_t *iface)
13531364
uac_cs_request_t uac_request = {0};
13541365
memcpy(&uac_request, &usb_request, sizeof(usb_setup_packet_t));
13551366
UAC_RETURN_ON_ERROR(uac_cs_request_set(iface->parent, &uac_request), "Unable to set Interface alternate");
1356-
ESP_LOGI(TAG, "Set Interface %d-%d", iface->dev_info.iface_num, iface->cur_alt + 1);
1367+
ESP_LOGI(TAG, "Resume Interface %d-%d", iface->dev_info.iface_num, iface->cur_alt + 1);
13571368
// Set endpoint frequency control
13581369
if (iface->iface_alt[iface->cur_alt].freq_ctrl_supported) {
1359-
ESP_LOGI(TAG, "Set EP %02X frequency %"PRIu32, iface->iface_alt[iface->cur_alt].ep_addr, iface->iface_alt[iface->cur_alt].cur_sampling_freq);
1370+
ESP_LOGI(TAG, "Set EP %d frequency %"PRIu32, iface->iface_alt[iface->cur_alt].ep_addr & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK, iface->iface_alt[iface->cur_alt].cur_sampling_freq);
13601371
UAC_RETURN_ON_ERROR(uac_cs_request_set_ep_frequency(iface, iface->iface_alt[iface->cur_alt].ep_addr,
13611372
iface->iface_alt[iface->cur_alt].cur_sampling_freq), "Unable to set endpoint frequency");
13621373
}
13631374
// for RX, we just submit all the transfers
13641375
if (iface->dev_info.type == UAC_STREAM_RX) {
1365-
assert(iface->iface_alt[iface->cur_alt].ep_addr & 0x80);
1376+
assert(iface->iface_alt[iface->cur_alt].ep_addr & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK);
13661377
for (int i = 0; i < iface->xfer_num; i++) {
13671378
assert(iface->free_xfer_list[i]);
13681379
iface->free_xfer_list[i]->device_handle = iface->parent->dev_hdl;
@@ -1381,7 +1392,7 @@ static esp_err_t uac_host_interface_resume(uac_iface_t *iface)
13811392
UAC_RETURN_ON_ERROR(usb_host_transfer_submit(iface->xfer_list[i]), "Unable to submit RX transfer");
13821393
}
13831394
} else if (iface->dev_info.type == UAC_STREAM_TX) {
1384-
assert(!(iface->iface_alt[iface->cur_alt].ep_addr & 0x80));
1395+
assert(!(iface->iface_alt[iface->cur_alt].ep_addr & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK));
13851396
// for TX, we submit the first transfer with data 0 to make the speaker quiet
13861397
for (int i = 0; i < iface->xfer_num; i++) {
13871398
assert(iface->free_xfer_list[i]);

0 commit comments

Comments
 (0)