Skip to content

Commit a7c9db3

Browse files
committed
update tinyusb to commit 55951b71aea46c09f27afe1640454fe43c983eec
1 parent 446e0af commit a7c9db3

File tree

14 files changed

+660
-375
lines changed

14 files changed

+660
-375
lines changed

src/class/audio/audio_device.c

Lines changed: 356 additions & 207 deletions
Large diffs are not rendered by default.

src/class/audio/audio_device.h

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* Copyright (c) 2020 Ha Thach (tinyusb.org)
55
* Copyright (c) 2020 Reinhard Panhuber
6+
* Copyright (c) 2023 HiFiPhile
67
*
78
* Permission is hereby granted, free of charge, to any person obtaining a copy
89
* of this software and associated documentation files (the "Software"), to deal
@@ -192,6 +193,7 @@
192193
#endif
193194

194195
// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set().
196+
// Can be override by tud_audio_feedback_format_correction_cb()
195197
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION
196198
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1
197199
#endif
@@ -242,7 +244,8 @@
242244
// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size
243245
// The actual coding parameters of active AS alternate interface is parsed from the descriptors
244246

245-
// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)!
247+
// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple
248+
// of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sample_sz) * sample_sz)!
246249
// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!!
247250

248251
// For PCM encoding/decoding
@@ -446,63 +449,80 @@ static inline bool tud_audio_int_write (const audio_interru
446449
bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len);
447450

448451
//--------------------------------------------------------------------+
449-
// Application Callback API (weak is optional)
452+
// Application Callback API
450453
//--------------------------------------------------------------------+
451454

452455
#if CFG_TUD_AUDIO_ENABLE_EP_IN
453-
TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
454-
TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
456+
bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
457+
bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
455458
#endif
456459

457460
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
458-
TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
459-
TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
461+
bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
462+
bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
460463
#endif
461464

462465
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
463-
TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id);
466+
void tud_audio_fb_done_cb(uint8_t func_id);
464467

465468

466-
// determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced.
467-
468-
// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced).
469+
// Note about feedback calculation
470+
//
471+
// Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT
472+
// Feedback value is calculated within the audio driver by regulating the FIFO level to half fill.
473+
// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, well tested
474+
// (Windows, Linux, OSX) with a reliable result so far.
475+
// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is introduced.
476+
//
477+
// Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT
478+
// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from
479+
// which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter).
480+
// See tud_audio_set_fb_params() and tud_audio_feedback_update()
481+
// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a smaller delay is possible.
482+
// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point is the reading of the cycle counter value of f_m.
483+
// It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced).
484+
// Long-term drift could occur since error is accumulated.
485+
//
486+
// Option 3 - manual
487+
// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer.
488+
// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load.
489+
// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay is introduced.
469490

470-
// Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set().
471491

472492
// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed.
473493
//
474494
// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default,
475-
// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb
476-
// expects 16.16 format and handles the conversion to 10.14 on FS.
495+
// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set or tud_audio_feedback_format_correction_cb()
496+
// return true, then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS.
497+
//
498+
// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and it seems the
499+
// driver can work with either format.
477500
//
478-
// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the
479-
// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format.
480-
481501
// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value.
482-
502+
//
483503
// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec
484504
// Boiled down, the feedback value Ff = n_samples / (micro)frame.
485-
// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s)
505+
// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13
506+
// for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s)
486507
// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K)
487508
// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames
488-
489509
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
490-
static inline bool tud_audio_fb_set(uint32_t feedback);
491510

492-
// Update feedback value with passed cycles since last time this update function is called.
511+
// Update feedback value with passed MCLK cycles since last time this update function is called.
493512
// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented
494513
// This function will also call tud_audio_feedback_set()
495514
// return feedback value in 16.16 for reference (0 for error)
515+
// Example :
516+
// binterval=3 (4ms); FS = 48kHz; MCLK = 12.288MHz
517+
// In 4 SOF MCLK counted 49152 cycles
496518
uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles);
497519

498520
enum {
499521
AUDIO_FEEDBACK_METHOD_DISABLED,
500522
AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
501523
AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
502-
AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
503-
504-
// impelemnt later
505-
// AUDIO_FEEDBACK_METHOD_FIFO_COUNT
524+
AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only
525+
AUDIO_FEEDBACK_METHOD_FIFO_COUNT
506526
};
507527

508528
typedef struct {
@@ -514,52 +534,50 @@ typedef struct {
514534
uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on
515535
}frequency;
516536

517-
#if 0 // implement later
518-
struct {
519-
uint32_t threshold_bytes; // minimum number of bytes received to be considered as filled/ready
520-
}fifo_count;
521-
#endif
522537
};
523538
}audio_feedback_params_t;
524539

525540
// Invoked when needed to set feedback parameters
526-
TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
541+
void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
527542

528543
// Callback in ISR context, invoked periodically according to feedback endpoint bInterval.
529544
// Could be used to compute and update feedback value, should be placed in RAM if possible
530545
// frame_number : current SOF count
531546
// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor
532-
TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
547+
TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
533548

549+
// (Full-Speed only) Callback to set feedback format correction is applied or not,
550+
// default to CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION if not implemented.
551+
bool tud_audio_feedback_format_correction_cb(uint8_t func_id);
534552
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
535553

536554
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
537-
TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport);
555+
void tud_audio_int_done_cb(uint8_t rhport);
538556
#endif
539557

540558
// Invoked when audio set interface request received
541-
TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
559+
bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
542560

543561
// Invoked when audio set interface request received which closes an EP
544-
TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request);
562+
bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request);
545563

546564
// Invoked when audio class specific set request received for an EP
547-
TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
565+
bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
548566

549567
// Invoked when audio class specific set request received for an interface
550-
TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
568+
bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
551569

552570
// Invoked when audio class specific set request received for an entity
553-
TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
571+
bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
554572

555573
// Invoked when audio class specific get request received for an EP
556-
TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);
574+
bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);
557575

558576
// Invoked when audio class specific get request received for an interface
559-
TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
577+
bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
560578

561579
// Invoked when audio class specific get request received for an entity
562-
TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);
580+
bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);
563581

564582
//--------------------------------------------------------------------+
565583
// Inline Functions

src/class/bth/bth_device.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,14 @@ typedef struct
4848
uint8_t itf_num;
4949
uint8_t ep_ev;
5050
uint8_t ep_acl_in;
51+
uint16_t ep_acl_in_pkt_sz;
5152
uint8_t ep_acl_out;
5253
uint8_t ep_voice[2]; // Not used yet
5354
uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT];
5455

56+
// Previous amount of bytes sent when issuing ZLP
57+
uint32_t prev_xferred_bytes;
58+
5559
// Endpoint Transfer buffer
5660
CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd;
5761
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE];
@@ -133,11 +137,25 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_
133137
TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
134138
_btd_itf.ep_ev = desc_ep->bEndpointAddress;
135139

140+
desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep);
141+
136142
// Open endpoint pair
137-
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out,
138-
&_btd_itf.ep_acl_in), 0);
143+
TU_ASSERT(usbd_open_edpt_pair(rhport, (uint8_t const *)desc_ep, 2,
144+
TUSB_XFER_BULK, &_btd_itf.ep_acl_out,
145+
&_btd_itf.ep_acl_in),
146+
0);
147+
148+
// Save acl in endpoint max packet size
149+
tusb_desc_endpoint_t const *desc_ep_acl_in = desc_ep;
150+
for (size_t p = 0; p < 2; p++) {
151+
if (tu_edpt_dir(desc_ep_acl_in->bEndpointAddress) == TUSB_DIR_IN) {
152+
_btd_itf.ep_acl_in_pkt_sz = tu_edpt_packet_size(desc_ep_acl_in);
153+
break;
154+
}
155+
desc_ep_acl_in = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep_acl_in);
156+
}
139157

140-
itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep)));
158+
itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(desc_ep));
141159

142160
// Prepare for incoming data from host
143161
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0);
@@ -244,10 +262,8 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c
244262
return true;
245263
}
246264

247-
bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
248-
{
249-
(void)result;
250-
265+
bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
266+
uint32_t xferred_bytes) {
251267
// received new data from host
252268
if (ep_addr == _btd_itf.ep_acl_out)
253269
{
@@ -262,7 +278,20 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t
262278
}
263279
else if (ep_addr == _btd_itf.ep_acl_in)
264280
{
265-
if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes);
281+
if ((result == XFER_RESULT_SUCCESS) && (xferred_bytes > 0) &&
282+
((xferred_bytes & (_btd_itf.ep_acl_in_pkt_sz - 1)) == 0)) {
283+
// Save number of transferred bytes
284+
_btd_itf.prev_xferred_bytes = xferred_bytes;
285+
286+
// Send zero-length packet
287+
tud_bt_acl_data_send(NULL, 0);
288+
} else if (tud_bt_acl_data_sent_cb) {
289+
if (xferred_bytes == 0) {
290+
xferred_bytes = _btd_itf.prev_xferred_bytes;
291+
_btd_itf.prev_xferred_bytes = 0;
292+
}
293+
tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes);
294+
}
266295
}
267296

268297
return true;

src/class/hid/hid_device.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@
2424
* This file is part of the TinyUSB stack.
2525
*/
2626

27-
// ESP32 out-of-sync
28-
#ifdef ARDUINO_ARCH_ESP32
29-
#include "arduino/ports/esp32/tusb_config_esp32.h"
30-
#endif
31-
3227
#include "tusb_option.h"
3328

3429
#if (CFG_TUD_ENABLED && CFG_TUD_HID)
@@ -139,7 +134,7 @@ uint8_t tud_hid_n_get_protocol(uint8_t instance) {
139134
return _hidd_itf[instance].protocol_mode;
140135
}
141136

142-
bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) {
137+
bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]) {
143138
hid_keyboard_report_t report;
144139
report.modifier = modifier;
145140
report.reserved = 0;

0 commit comments

Comments
 (0)