Skip to content

Commit 3f17aa5

Browse files
Merge pull request #281 from espressif/fix/uac_ringbuf
fix(uac): Wait until requested bytes are read
2 parents bf10872 + 83446e5 commit 3f17aa5

File tree

4 files changed

+71
-31
lines changed

4 files changed

+71
-31
lines changed
Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,45 @@
11
# Changelog for USB Host UAC
22

3-
## 1.3.1
3+
All notable changes to this component will be documented in this file.
44

5-
1. Added support for ESP32-H4
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).
66

7-
## 1.3.0
7+
## [1.3.2] - 2025-10-21
88

9-
1. Added Linux target build for the UAC component, host tests (https://github.com/espressif/esp-usb/issues/143)
9+
### Changed
1010

11-
## 1.2.0 2024-09-27
11+
- uac_host_device_read() now waits for the full timeout duration until the required amount of data is read, preventing premature returns with partial data (https://github.com/espressif/esp-usb/issues/248)
1212

13-
### Breaking Changes:
13+
## [1.3.1] - 2025-09-24
14+
15+
- Added support for ESP32-H4
16+
17+
## [1.3.0] - 2025-03-28
1418

15-
1. Changed the parameter type of `uac_host_device_set_volume_db` from uint32_t to int16_t
19+
- Added Linux target build for the UAC component, host tests (https://github.com/espressif/esp-usb/issues/143)
20+
21+
## [1.2.0] - 2024-10-10
22+
23+
### Breaking Changes:
1624

25+
- Changed the parameter type of `uac_host_device_set_volume_db` from uint32_t to int16_t
1726

1827
### Improvements:
1928

20-
1. Support get current volume and mute status
29+
- Support get current volume and mute status
2130

2231
### Bugfixes:
2332

24-
1. Fixed incorrect volume conversion. Using actual device volume range.
25-
2. Fixed concurrency issues when suspend/stop during read/write
33+
- Fixed incorrect volume conversion. Using actual device volume range.
34+
- Fixed concurrency issues when suspend/stop during read/write
2635

27-
## 1.1.0
36+
## [1.1.0] - 2024-07-08
2837

2938
### Improvements
3039

3140
- Added add `uac_host_device_open_with_vid_pid` to open connected audio devices with known VID and PID
3241
- Print component version message `uac-host: Install Succeed, Version: 1.1.0` in `uac_host_install` function
3342

34-
## 1.0.0
43+
## [1.0.0] - 2024-05-23
3544

3645
- Initial version

host/class/uac/usb_host_uac/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# USB Host UAC Driver
22

33
[![Component Registry](https://components.espressif.com/components/espressif/usb_host_uac/badge.svg)](https://components.espressif.com/components/espressif/usb_host_uac)
4+
![maintenance-status](https://img.shields.io/badge/maintenance-actively--developed-brightgreen.svg)
5+
![changelog](https://img.shields.io/badge/Keep_a_Changelog-blue?logo=keepachangelog&logoColor=E05735)
46

57
This directory contains an implementation of a USB UAC Driver implemented on top of the [USB Host Library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_host.html).
68

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.1"
2+
version: "1.3.2"
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: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -276,25 +276,58 @@ static esp_err_t _ring_buffer_push(RingbufHandle_t ringbuf_hdl, uint8_t *buf, si
276276
static esp_err_t _ring_buffer_pop(RingbufHandle_t ringbuf_hdl, uint8_t *buf, size_t req_bytes, size_t *read_bytes, TickType_t ticks_to_wait)
277277
{
278278
assert(ringbuf_hdl && buf && read_bytes);
279-
uint8_t *buf_rcv = xRingbufferReceiveUpTo(ringbuf_hdl, read_bytes, ticks_to_wait, req_bytes);
280-
281-
if (!buf_rcv) {
282-
return ESP_FAIL;
279+
/* Read up to req_bytes, blocking up to ticks_to_wait in total.
280+
* xRingbufferReceiveUpTo may return fewer bytes than requested even if
281+
* the caller asked for more, so loop until we've collected the full
282+
* amount or the timeout expires. If nothing is read before timeout,
283+
* return ESP_ERR_TIMEOUT. If some bytes were read and timeout expires, return
284+
* ESP_OK with the actual number of bytes read.
285+
*/
286+
if (req_bytes == 0) {
287+
*read_bytes = 0;
288+
return ESP_OK;
283289
}
284290

285-
memcpy(buf, buf_rcv, *read_bytes);
286-
vRingbufferReturnItem(ringbuf_hdl, (void *)(buf_rcv));
291+
size_t total_read = 0;
292+
TickType_t start_ticks = xTaskGetTickCount();
287293

288-
size_t read_bytes2 = 0;
289-
if (*read_bytes < req_bytes) {
290-
buf_rcv = xRingbufferReceiveUpTo(ringbuf_hdl, &read_bytes2, 0, req_bytes - *read_bytes);
291-
if (buf_rcv) {
292-
memcpy(buf + *read_bytes, buf_rcv, read_bytes2);
293-
*read_bytes += read_bytes2;
294-
vRingbufferReturnItem(ringbuf_hdl, (void *)(buf_rcv));
294+
while (total_read < req_bytes) {
295+
size_t chunk_read = 0;
296+
size_t want = req_bytes - total_read;
297+
298+
/* compute remaining ticks to wait */
299+
TickType_t elapsed = xTaskGetTickCount() - start_ticks;
300+
TickType_t remain = 0;
301+
if (ticks_to_wait == portMAX_DELAY) {
302+
remain = portMAX_DELAY;
303+
} else if (elapsed >= ticks_to_wait) {
304+
remain = 0;
305+
} else {
306+
remain = ticks_to_wait - elapsed;
307+
}
308+
309+
uint8_t *buf_rcv = xRingbufferReceiveUpTo(ringbuf_hdl, &chunk_read, remain, want);
310+
311+
if (!buf_rcv) {
312+
/* nothing available within remaining timeout */
313+
break;
314+
}
315+
316+
/* copy received chunk */
317+
memcpy(buf + total_read, buf_rcv, chunk_read);
318+
vRingbufferReturnItem(ringbuf_hdl, (void *)buf_rcv);
319+
total_read += chunk_read;
320+
if (chunk_read == 0) {
321+
/* defensive: in case the chunk is zero length */
322+
break;
295323
}
296324
}
297325

326+
if (total_read == 0) {
327+
return ESP_ERR_TIMEOUT;
328+
}
329+
330+
*read_bytes = total_read;
298331
return ESP_OK;
299332
}
300333

@@ -2385,11 +2418,7 @@ esp_err_t uac_host_device_read(uac_host_device_handle_t uac_dev_handle, uint8_t
23852418
}
23862419
uac_host_interface_unlock(iface);
23872420

2388-
size_t data_len = _ring_buffer_get_len(iface->ringbuf);
2389-
if (data_len > size) {
2390-
data_len = size;
2391-
}
2392-
esp_err_t ret = _ring_buffer_pop(iface->ringbuf, data, data_len, (size_t *)bytes_read, timeout);
2421+
esp_err_t ret = _ring_buffer_pop(iface->ringbuf, data, size, (size_t *)bytes_read, timeout);
23932422

23942423
if (ESP_OK != ret) {
23952424
ESP_LOGD(TAG, "RX Ringbuffer read failed");

0 commit comments

Comments
 (0)