From 9d0251f7a6751a0d998da4fad81a35a043608275 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 19 Sep 2023 15:42:52 +0200 Subject: Fix UAC interleaved copy. --- src/class/audio/audio_device.c | 113 +++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 62 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1a7ce7870..0e4220f4f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -631,68 +631,59 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t // Decoding according to 2.3.1.5 Audio Streams // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, uint8_t * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) { - // This function is an optimized version of - // while((uint8_t *)dst < dst_end) - // { - // memcpy(dst, src, nBytesToCopy); - // dst = (uint8_t *)dst + nBytesToCopy; - // src += nBytesToCopy * n_ff_used; - // } - - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; + // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) switch (nBytesToCopy) { case 1: while((uint8_t *)dst < dst_end) { - *(uint8_t *)dst++ = *src; - src += n_ff_used; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + src += 2 * (n_ff_used - 1); } break; case 2: while((uint8_t *)dst < dst_end) { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - dst += 2; - src += 2 * n_ff_used; + *(uint32_t*)dst = *(uint32_t*)src; + src += 4; + dst += 4; + src += 4 * (n_ff_used - 1); } break; case 3: while((uint8_t *)dst < dst_end) { - // memcpy(dst, src, 3); - // dst = (uint8_t *)dst + 3; - // src += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - - src += 3 * (n_ff_used - 1); + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + src += 6 * (n_ff_used - 1); } break; case 4: while((uint8_t *)dst < dst_end) { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + *(uint32_t*)dst++ = *(uint32_t*)src++; + src += 4; + dst += 4; + *(uint32_t*)dst++ = *(uint32_t*)src++; + src += 4; dst += 4; - src += 4 * n_ff_used; + src += 8 * (n_ff_used - 1); } break; } @@ -946,57 +937,55 @@ range [-1, +1) // Helper function static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) { - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - + // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) switch (nBytesToCopy) { case 1: while(src < src_end) { - *dst = *src++; - dst += n_ff_used; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + dst += 2 * (n_ff_used - 1); } break; case 2: while(src < src_end) { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - src += 2; - dst += 2 * n_ff_used; + *(uint32_t*)dst = *(uint32_t*)src; + src += 4; + dst += 4; + dst += 4 * (n_ff_used - 1); } break; case 3: while(src < src_end) { - // memcpy(dst, src, 3); - // src = (uint8_t *)src + 3; - // dst += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - - dst += 3 * (n_ff_used - 1); + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + dst += 6 * (n_ff_used - 1); } break; case 4: while(src < src_end) { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + *(uint32_t*)dst++ = *(uint32_t*)src++; + src += 4; + dst += 4; + *(uint32_t*)dst++ = *(uint32_t*)src++; src += 4; - dst += 4 * n_ff_used; + dst += 4; + dst += 8 * (n_ff_used - 1); } break; } -- cgit v1.3.1 From 6be7f354c26e09a87d1b856b0e237ff82be5963f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 19 Sep 2023 16:32:49 +0200 Subject: Fix cast-align. --- src/class/audio/audio_device.c | 196 +++++++++++++++++++---------------------- 1 file changed, 90 insertions(+), 106 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0e4220f4f..46fd6dfa9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -631,64 +631,55 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t // Decoding according to 2.3.1.5 Audio Streams // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, uint8_t * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) - - switch (nBytesToCopy) + uint16_t * dst16 = dst; + uint16_t * src16 = src; + const uint16_t * dst_end16 = dst_end; + uint32_t * dst32 = dst; + uint32_t * src32 = src; + const uint32_t * dst_end32 = dst_end; + + if (nBytesToCopy == 1) { - case 1: - while((uint8_t *)dst < dst_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - src += 2 * (n_ff_used - 1); - } - break; - - case 2: - while((uint8_t *)dst < dst_end) - { - *(uint32_t*)dst = *(uint32_t*)src; - src += 4; - dst += 4; - src += 4 * (n_ff_used - 1); - } - break; - - case 3: - while((uint8_t *)dst < dst_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - src += 6 * (n_ff_used - 1); - } - break; - - case 4: - while((uint8_t *)dst < dst_end) - { - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - src += 8 * (n_ff_used - 1); - } - break; + while(dst16 < dst_end16) + { + *dst16++ = *src16++; + src16 += n_ff_used - 1; + } + return src16; + } + else if (nBytesToCopy == 2) + { + while(dst32 < dst_end32) + { + *dst32++ = *src32++; + src32 += n_ff_used - 1; + } + return src32; + } + else if (nBytesToCopy == 3) + { + while(dst16 < dst_end16) + { + *dst16++ = *src16++; + *dst16++ = *src16++; + *dst16++ = *src16++; + src16 += 3 * (n_ff_used - 1); + } + return src16; + } + else // nBytesToCopy == 4 + { + while(dst32 < dst_end32) + { + *dst32++ = *src32++; + *dst32++ = *src32++; + src32 += 2 * (n_ff_used - 1); + } + return src32; } - - return src; } static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) @@ -935,62 +926,55 @@ range [-1, +1) * */ // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, const void * src_end, void * dst, uint8_t const n_ff_used) { // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) - switch (nBytesToCopy) + uint16_t * dst16 = dst; + uint16_t * src16 = src; + const uint16_t * src_end16 = src_end; + uint32_t * dst32 = dst; + uint32_t * src32 = src; + const uint32_t * src_end32 = src_end; + + if (nBytesToCopy == 1) { - case 1: - while(src < src_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - dst += 2 * (n_ff_used - 1); - } - break; - - case 2: - while(src < src_end) - { - *(uint32_t*)dst = *(uint32_t*)src; - src += 4; - dst += 4; - dst += 4 * (n_ff_used - 1); - } - break; - - case 3: - while(src < src_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - dst += 6 * (n_ff_used - 1); - } - break; - - case 4: - while(src < src_end) - { - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - dst += 8 * (n_ff_used - 1); - } - break; + while(src16 < src_end16) + { + *dst16++ = *src16++; + dst16 += n_ff_used - 1; + } + return dst16; + } + else if (nBytesToCopy == 2) + { + while(src32 < src_end32) + { + *dst32++ = *src32++; + dst32 += n_ff_used - 1; + } + return dst32; + } + else if (nBytesToCopy == 3) + { + while(src16 < src_end16) + { + *dst16++ = *src16++; + *dst16++ = *src16++; + *dst16++ = *src16++; + dst16 += 3 * (n_ff_used - 1); + } + return dst16; + } + else // nBytesToCopy == 4 + { + while(src32 < src_end32) + { + *dst32++ = *src32++; + *dst32++ = *src32++; + dst32 += 2 * (n_ff_used - 1); + } + return dst32; } - - return dst; } static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) -- cgit v1.3.1 From 277852afc1798f2acdb61917984e76b4bafa699e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Sep 2023 10:56:38 +0700 Subject: fix esp32 msc example --- examples/host/cdc_msc_hid_freertos/src/cdc_app.c | 8 +- examples/host/cdc_msc_hid_freertos/src/hid_app.c | 4 + examples/host/cdc_msc_hid_freertos/src/main.c | 12 +- examples/host/cdc_msc_hid_freertos/src/msc_app.c | 8 +- src/class/msc/msc_host.c | 265 ++++++++++------------- src/class/msc/msc_host.h | 8 +- src/host/usbh.c | 22 +- 7 files changed, 151 insertions(+), 176 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 943e534d8..91dcc2e1a 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -31,9 +31,7 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ - -//------------- IMPLEMENTATION -------------// - +// helper size_t get_console_inputs(uint8_t *buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { @@ -47,6 +45,10 @@ size_t get_console_inputs(uint8_t *buf, size_t bufsize) { return count; } +void cdc_app_init(void) { + // nothing to do +} + void cdc_app_task(void* param) { (void) param; diff --git a/examples/host/cdc_msc_hid_freertos/src/hid_app.c b/examples/host/cdc_msc_hid_freertos/src/hid_app.c index a2df3b909..9ea5c1be0 100644 --- a/examples/host/cdc_msc_hid_freertos/src/hid_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/hid_app.c @@ -48,6 +48,10 @@ static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const *report); static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); +void hid_app_init(void) { + // nothing to do +} + //--------------------------------------------------------------------+ // TinyUSB Callbacks //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index 88e742ee2..b60be015b 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -82,10 +82,15 @@ StaticTask_t cdc_taskdef; TimerHandle_t blinky_tm; static void led_blinky_cb(TimerHandle_t xTimer); -static void usb_host_task(void* param); +extern void cdc_app_init(void); +extern void hid_app_init(void); +extern void msc_app_init(void); +static void usb_host_task(void* param); extern void cdc_app_task(void* param); + + /*------------- MAIN -------------*/ int main(void) { board_init(); @@ -131,6 +136,10 @@ static void usb_host_task(void *param) { board_init_after_tusb(); } + cdc_app_init(); + hid_app_init(); + msc_app_init(); + // RTOS forever loop while (1) { // put this thread to waiting state until there is new events @@ -154,7 +163,6 @@ void tuh_umount_cb(uint8_t dev_addr) { printf("A device with address %d is unmounted \r\n", dev_addr); } - //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c index a8d6fbfaa..ee02ba917 100644 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -25,10 +25,12 @@ #include "tusb.h" -#if CFG_TUH_MSC - static scsi_inquiry_resp_t inquiry_resp; +void msc_app_init(void) { + // nothing to do +} + bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { msc_cbw_t const *cbw = cb_data->cbw; msc_csw_t const *csw = cb_data->csw; @@ -63,5 +65,3 @@ void tuh_msc_umount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); } - -#endif diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index da264142c..39f2d9f1c 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -43,16 +43,14 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -enum -{ +enum { MSC_STAGE_IDLE = 0, MSC_STAGE_CMD, MSC_STAGE_DATA, MSC_STAGE_STATUS, }; -typedef struct -{ +typedef struct { uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; @@ -69,13 +67,13 @@ typedef struct //------------- SCSI -------------// uint8_t stage; - void* buffer; + void* buffer; tuh_msc_complete_cb_t complete_cb; uintptr_t complete_arg; CFG_TUH_MEM_ALIGN msc_cbw_t cbw; CFG_TUH_MEM_ALIGN msc_csw_t csw; -}msch_interface_t; +} msch_interface_t; CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; @@ -86,40 +84,34 @@ static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; // FIXME potential nul reference TU_ATTR_ALWAYS_INLINE -static inline msch_interface_t* get_itf(uint8_t dev_addr) -{ - return &_msch_itf[dev_addr-1]; +static inline msch_interface_t* get_itf(uint8_t dev_addr) { + return &_msch_itf[dev_addr - 1]; } //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) -{ +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->max_lun; } -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) -{ +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->capacity[lun].block_count; } -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) -{ +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->capacity[lun].block_size; } -bool tuh_msc_mounted(uint8_t dev_addr) -{ +bool tuh_msc_mounted(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->mounted; } -bool tuh_msc_ready(uint8_t dev_addr) -{ +bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out); } @@ -127,20 +119,20 @@ bool tuh_msc_ready(uint8_t dev_addr) //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ -static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) -{ +static inline void cbw_init(msc_cbw_t* cbw, uint8_t lun) { tu_memclr(cbw, sizeof(msc_cbw_t)); cbw->signature = MSC_CBW_SIGNATURE; cbw->tag = 0x54555342; // TUSB cbw->lun = lun; } -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); +bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { + msch_interface_t* p_msc = get_itf(daddr); TU_VERIFY(p_msc->configured); - // TODO claim endpoint + // claim endpoint + TU_VERIFY(usbh_edpt_claim(daddr, p_msc->ep_out)); p_msc->cbw = *cbw; p_msc->stage = MSC_STAGE_CMD; @@ -148,15 +140,18 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu p_msc->complete_cb = complete_cb; p_msc->complete_arg = arg; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); + if (!usbh_edpt_xfer(daddr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))) { + usbh_edpt_release(daddr, p_msc->ep_out); + return false; + } return true; } -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -169,8 +164,8 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->mounted); @@ -181,18 +176,16 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_inquiry_t); - scsi_inquiry_t const cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) + scsi_inquiry_t const cmd_inquiry = { + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_resp_t) }; memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->configured); @@ -200,16 +193,16 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ cbw_init(&cbw, lun); cbw.total_bytes = 0; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg); } -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void* response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -217,73 +210,64 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_ms cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_request_sense_t); - scsi_request_sense_t const cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 + scsi_request_sense_t const cmd_request_sense = { + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 }; - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void* buffer, uint32_t lba, uint16_t block_count, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->mounted); msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); + cbw.total_bytes = block_count * p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); - scsi_read10_t const cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + scsi_read10_t const cmd_read10 = { + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg); } -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const* buffer, uint32_t lba, uint16_t block_count, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->mounted); msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.total_bytes = block_count * p_msc->capacity[lun].block_size; cbw.dir = TUSB_DIR_OUT; cbw.cmd_len = sizeof(scsi_write10_t); - scsi_write10_t const cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + scsi_write10_t const cmd_write10 = { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb, arg); + return tuh_msc_scsi_command(dev_addr, &cbw, (void*) (uintptr_t) buffer, complete_cb, arg); } #if 0 // MSC interface Reset (not used now) -bool tuh_msc_reset(uint8_t dev_addr) -{ - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { +bool tuh_msc_reset(uint8_t dev_addr) { + tusb_control_request_t const new_request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT @@ -300,79 +284,71 @@ bool tuh_msc_reset(uint8_t dev_addr) //--------------------------------------------------------------------+ // CLASS-USBH API //--------------------------------------------------------------------+ -void msch_init(void) -{ +void msch_init(void) { tu_memclr(_msch_itf, sizeof(_msch_itf)); } -void msch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); +void msch_close(uint8_t dev_addr) { + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX,); msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured, ); + TU_VERIFY(p_msc->configured,); TU_LOG_DRV(" MSCh close addr = %d\r\n", dev_addr); // invoke Application Callback if (p_msc->mounted) { - if(tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); } tu_memclr(p_msc, sizeof(msch_interface_t)); } -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = get_itf(dev_addr); msc_cbw_t const * cbw = &p_msc->cbw; msc_csw_t * csw = &p_msc->csw; - switch (p_msc->stage) - { + switch (p_msc->stage) { case MSC_STAGE_CMD: // Must be Command Block - TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); + TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); - if ( cbw->total_bytes && p_msc->buffer ) - { + if (cbw->total_bytes && p_msc->buffer) { // Data stage if any p_msc->stage = MSC_STAGE_DATA; - uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes)); - }else - { + } else { // Status stage p_msc->stage = MSC_STAGE_STATUS; TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); } - break; + break; case MSC_STAGE_DATA: // Status stage p_msc->stage = MSC_STAGE_STATUS; TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); - break; + break; case MSC_STAGE_STATUS: // SCSI op is complete p_msc->stage = MSC_STAGE_IDLE; - if (p_msc->complete_cb) - { - tuh_msc_complete_data_t const cb_data = - { - .cbw = cbw, - .csw = csw, - .scsi_data = p_msc->buffer, - .user_arg = p_msc->complete_arg + if (p_msc->complete_cb) { + tuh_msc_complete_data_t const cb_data = { + .cbw = cbw, + .csw = csw, + .scsi_data = p_msc->buffer, + .user_arg = p_msc->complete_arg }; p_msc->complete_cb(dev_addr, &cb_data); } - break; + break; - // unknown state - default: break; + // unknown state + default: + break; } return true; @@ -381,39 +357,35 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 //--------------------------------------------------------------------+ // MSC Enumeration //--------------------------------------------------------------------+ - -static void config_get_maxlun_complete (tuh_xfer_t* xfer); -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data); +static void config_get_maxlun_complete(tuh_xfer_t* xfer); +static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) { (void) rhport; TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_ASSERT(drv_len <= max_len); msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); + tusb_desc_endpoint_t const* ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(desc_itf); - for(uint32_t i=0; i<2; i++) - { + for (uint32_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc)); - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) - { + if (TUSB_DIR_IN == tu_edpt_dir(ep_desc->bEndpointAddress)) { p_msc->ep_in = ep_desc->bEndpointAddress; - }else - { + } else { p_msc->ep_out = ep_desc->bEndpointAddress; } - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); + ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(ep_desc); } p_msc->itf_num = desc_itf->bInterfaceNumber; @@ -430,32 +402,31 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) { //------------- Get Max Lun -------------// TU_LOG_DRV("MSC Get Max Lun\r\n"); tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = itf_num, + .wLength = 1 }; tuh_xfer_t xfer = { - .daddr = dev_addr, - .ep_addr = 0, - .setup = &request, - .buffer = _msch_buffer, - .complete_cb = config_get_maxlun_complete, - .user_data = 0 + .daddr = dev_addr, + .ep_addr = 0, + .setup = &request, + .buffer = _msch_buffer, + .complete_cb = config_get_maxlun_complete, + .user_data = 0 }; TU_ASSERT(tuh_control_xfer(&xfer)); return true; } -static void config_get_maxlun_complete (tuh_xfer_t* xfer) -{ +static void config_get_maxlun_complete(tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; msch_interface_t* p_msc = get_itf(daddr); @@ -471,18 +442,16 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer) tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0); } -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; - if (csw->status == 0) - { + if (csw->status == 0) { // Unit is ready, read its capacity TU_LOG_DRV("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0); - }else - { + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), + config_read_capacity_complete, 0); + } else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries @@ -493,8 +462,7 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_d return true; } -static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; @@ -503,8 +471,7 @@ static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_dat return true; } -static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 6c0e5c9dd..9ca1b4703 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MSC_HOST_H_ -#define _TUSB_MSC_HOST_H_ +#ifndef TUSB_MSC_HOST_H_ +#define TUSB_MSC_HOST_H_ #include "msc.h" @@ -73,7 +73,7 @@ uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); // Perform a full SCSI command (cbw, data, csw) in non-blocking manner. // Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); // Perform SCSI Inquiry command // Complete callback is invoked when SCSI op is complete. @@ -123,4 +123,4 @@ bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, ui } #endif -#endif /* _TUSB_MSC_HOST_H_ */ +#endif diff --git a/src/host/usbh.c b/src/host/usbh.c index e332f35cc..8d75c9726 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -817,6 +817,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) } // Submit an transfer +// TODO call usbh_edpt_release if failed bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1713,19 +1714,16 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur return true; } -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) -{ +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { usbh_device_t* dev = get_device(dev_addr); - for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) - { + for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) { // continue with next valid interface // IAD binding interface such as CDCs should return itf_num + 1 when complete // with usbh_driver_set_config_complete() uint8_t const drv_id = dev->itf2drv[itf_num]; usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver) - { + if (driver) { TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; @@ -1733,23 +1731,19 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) } // all interface are configured - if (itf_num == CFG_TUH_INTERFACE_MAX) - { + if (itf_num == CFG_TUH_INTERFACE_MAX) { enum_full_complete(); - if (is_hub_addr(dev_addr)) - { + if (is_hub_addr(dev_addr)) { TU_LOG(CFG_TUH_LOG_LEVEL, "HUB address = %u is mounted\r\n", dev_addr); - }else - { + }else { // Invoke callback if available if (tuh_mount_cb) tuh_mount_cb(dev_addr); } } } -static void enum_full_complete(void) -{ +static void enum_full_complete(void) { // mark enumeration as complete _dev0.enumerating = 0; -- cgit v1.3.1 From 8b2cb63da88c0f790fee8d514971153569993b05 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 18:22:20 +0200 Subject: Fix naming nBytesPerSample. --- src/class/audio/audio_device.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 46fd6dfa9..5d3772a9d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -631,9 +631,9 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t // Decoding according to 2.3.1.5 Audio Streams // Helper function -static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesPerSample, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) + // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2) uint16_t * dst16 = dst; uint16_t * src16 = src; const uint16_t * dst_end16 = dst_end; @@ -641,7 +641,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB uint32_t * src32 = src; const uint32_t * dst_end32 = dst_end; - if (nBytesToCopy == 1) + if (nBytesPerSample == 1) { while(dst16 < dst_end16) { @@ -650,7 +650,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB } return src16; } - else if (nBytesToCopy == 2) + else if (nBytesPerSample == 2) { while(dst32 < dst_end32) { @@ -659,7 +659,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB } return src32; } - else if (nBytesToCopy == 3) + else if (nBytesPerSample == 3) { while(dst16 < dst_end16) { @@ -670,7 +670,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB } return src16; } - else // nBytesToCopy == 4 + else // nBytesPerSample == 4 { while(dst32 < dst_end32) { @@ -926,9 +926,9 @@ range [-1, +1) * */ // Helper function -static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, const void * src_end, void * dst, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesPerSample, void * src, const void * src_end, void * dst, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) + // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2) uint16_t * dst16 = dst; uint16_t * src16 = src; const uint16_t * src_end16 = src_end; @@ -936,7 +936,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB uint32_t * src32 = src; const uint32_t * src_end32 = src_end; - if (nBytesToCopy == 1) + if (nBytesPerSample == 1) { while(src16 < src_end16) { @@ -945,7 +945,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB } return dst16; } - else if (nBytesToCopy == 2) + else if (nBytesPerSample == 2) { while(src32 < src_end32) { @@ -954,7 +954,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB } return dst32; } - else if (nBytesToCopy == 3) + else if (nBytesPerSample == 3) { while(src16 < src_end16) { @@ -965,7 +965,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB } return dst16; } - else // nBytesToCopy == 4 + else // nBytesPerSample == 4 { while(src32 < src_end32) { -- cgit v1.3.1 From 656e1e416aa9dbd7ba4c18e777f7294a101f0667 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 17 Oct 2023 09:46:01 +0200 Subject: Add flow control for IN transfer. --- examples/device/audio_4_channel_mic/src/main.c | 30 ++++- .../audio_4_channel_mic/src/plot_audio_samples.py | 7 +- .../device/audio_4_channel_mic/src/tusb_config.h | 15 ++- src/class/audio/audio_device.c | 140 ++++++++++++++++++--- src/class/audio/audio_device.h | 16 +++ 5 files changed, 187 insertions(+), 21 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 4bcbdb692..52e6d71f7 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -69,8 +69,13 @@ uint8_t clkValid; audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +#if CFG_TUD_AUDIO_ENABLE_ENCODING // Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ/2]; // Ensure half word aligned +#else +// Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_EP_SZ_IN]; // Ensure half word aligned +#endif void led_blinking_task(void); void audio_task(void); @@ -97,6 +102,7 @@ int main(void) sampleFreqRng.subrange[0].bRes = 0; // Generate dummy data +#if CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t * p_buff = i2s_dummy_buffer[0]; uint16_t dataVal = 1; for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) @@ -116,6 +122,23 @@ int main(void) float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); *p_buff++ = (uint16_t)(sinf(t) * 25) + 200; } +#else + uint16_t * p_buff = i2s_dummy_buffer; + uint16_t dataVal = 1; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal++; + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)(sinf(t) * 25) + 200; + } +#endif while (1) { @@ -384,6 +407,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); + // Set sample rate for flow control + tud_audio_set_tx_flow_control(sampFreq); return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: @@ -429,12 +454,15 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); // } +#if CFG_TUD_AUDIO_ENABLE_ENCODING // Write I2S buffer into FIFO for (uint8_t cnt=0; cnt < 2; cnt++) { tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); } - +#else + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); +#endif return true; } diff --git a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py index a3a2b2fd4..d17a908b6 100644 --- a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py +++ b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py @@ -10,11 +10,11 @@ if __name__ == '__main__': # print(sd.query_devices()) fs = 48000 # Sample rate - duration = 20e-3 # Duration of recording + duration = 1 # Duration of recording if platform.system() == 'Windows': # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows) - device = 'Microphone (MicNode_4_Ch), Windows WDM-KS' + device = 'Microphone (MicNode_4_Ch), Windows WASAPI' elif platform.system() == 'Darwin': device = 'MicNode_4_Ch' else: @@ -28,8 +28,7 @@ if __name__ == '__main__': time = np.arange(0, duration, 1 / fs) # time vector # strip starting zero - myrecording = myrecording[100:] - time = time[100:] + plt.plot(time, myrecording) plt.xlabel('Time [s]') plt.ylabel('Amplitude') diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index 291ac4f79..d1e19c5a1 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -114,14 +114,25 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) + +#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 + +#if CFG_TUD_AUDIO_ENABLE_ENCODING + #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 #define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 #define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value #define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 4 * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) + +#else + +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX 4 * CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 4 * CFG_TUD_AUDIO_EP_SZ_IN + +#endif #ifdef __cplusplus } diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 5d3772a9d..9299440c9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -364,14 +364,21 @@ typedef struct #endif #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + uint32_t sample_rate_tx; + uint16_t packet_sz_tx[3]; + uint8_t bclock_id_tx; + uint8_t interval_tx; +#endif + // Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL) audio_format_type_t format_type_tx; uint8_t n_channels_tx; + uint8_t n_bytes_per_sampe_tx; #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING audio_data_format_type_I_t format_type_I_tx; - uint8_t n_bytes_per_sampe_tx; uint8_t n_channels_per_ff_tx; uint8_t n_ff_used_tx; #endif @@ -444,7 +451,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); static inline uint8_t tu_desc_subtype(void const* desc) @@ -453,6 +460,10 @@ static inline uint8_t tu_desc_subtype(void const* desc) } #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +static bool audiod_tx_calc_packet_size(const uint16_t* norminal_size, uint16_t data_size, uint16_t fifo_size, uint16_t* packet_size); +#endif + #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); #endif @@ -821,6 +832,57 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1 #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + +bool tud_audio_n_set_tx_flow_control(uint8_t func_id, uint32_t sample_rate) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[func_id]; + + TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I); + TU_VERIFY(audio->n_channels_tx); + TU_VERIFY(audio->n_bytes_per_sampe_tx); + TU_VERIFY(audio->interval_tx); + + if (sample_rate == 0) + { + audio->packet_sz_tx[0] = 0; + audio->packet_sz_tx[1] = 0; + audio->packet_sz_tx[2] = 0; + return false; + } + + const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL) ? audio->interval_tx : 1 << (audio->interval_tx - 1); + + const uint32_t sample_normimal = sample_rate * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); + const uint32_t sample_reminder = sample_rate * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); + + const uint16_t packet_sz_tx_min = (sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + const uint16_t packet_sz_tx_norm = sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + const uint16_t packet_sz_tx_max = (sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + + TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz); + + // Frmt20.pdf 2.3.1.1 USB Packets + if (sample_reminder) + { + // All virtual frame packets must either contain INT(nav) audio slots (small VFP) or INT(nav)+1 (large VFP) audio slots + audio->packet_sz_tx[0] = packet_sz_tx_norm; + audio->packet_sz_tx[1] = packet_sz_tx_norm; + audio->packet_sz_tx[2] = packet_sz_tx_max; + } else + { + // In the case where nav = INT(nav), ni may vary between INT(nav)-1 (small VFP), INT(nav) + // (medium VFP) and INT(nav)+1 (large VFP). + audio->packet_sz_tx[0] = packet_sz_tx_min; + audio->packet_sz_tx[1] = packet_sz_tx_norm; + audio->packet_sz_tx[2] = packet_sz_tx_max; + } + + return true; +} + +#endif // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. // If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. @@ -886,9 +948,16 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) #else // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - +#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + uint16_t tgt_packet_sz; + // packet_sz_tx is based on total packet size, here we want size for each support buffer. + if (audiod_tx_calc_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, &tgt_packet_sz)) + n_bytes_tx = tgt_packet_sz; + else + n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); +#else n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - +#endif #if USE_LINEAR_BUFFER_TX tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); @@ -987,7 +1056,6 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // Determine amount of samples uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); uint8_t cnt_ff; @@ -1001,14 +1069,24 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi } } - // Check if there is enough +#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + uint16_t tgt_packet_sz; + // packet_sz_tx is based on total packet size, here we want size for each support buffer. + if (audiod_tx_calc_packet_size(audio->packet_sz_tx, nBytesPerFFToSend * n_ff_used, audio->tx_supp_ff[0].depth * n_ff_used, &tgt_packet_sz)) + nBytesPerFFToSend = tgt_packet_sz / n_ff_used; +#endif + + // Check if there is enough data if (nBytesPerFFToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); +#if !CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; + uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; + nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize; +#endif // Encode uint8_t * dst; @@ -1489,6 +1567,9 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin #if CFG_TUD_AUDIO_ENABLE_EP_IN ep_in = desc_ep->bEndpointAddress; ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); + #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + _audiod_fct[i].interval_tx = desc_ep->bInterval; + #endif #endif } else { @@ -1607,6 +1688,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in = 0; // Necessary? + #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + audio->packet_sz_tx[0] = 0; + audio->packet_sz_tx[1] = 0; + audio->packet_sz_tx[2] = 0; + #endif } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1657,7 +1743,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) { -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL uint8_t const * p_desc_parse_for_params = p_desc; #endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary @@ -1686,12 +1772,13 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_sz = tu_edpt_packet_size(desc_ep); // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters - #if CFG_TUD_AUDIO_ENABLE_ENCODING + #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx); + #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx)) + * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx)); for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); @@ -2404,7 +2491,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) return false; } -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) // p_desc points to the AS interface of alternate setting zero // itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter // Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! @@ -2455,7 +2542,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * } // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -2491,6 +2578,31 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * } #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +static bool audiod_tx_calc_packet_size(const uint16_t* norminal_size, uint16_t data_size, uint16_t fifo_size, uint16_t* packet_size) +{ + TU_VERIFY(norminal_size[1]); + + // This flow control method need a FIFO size of 4*Navg + TU_VERIFY(norminal_size[1] <= fifo_size * 4); + + if (data_size < norminal_size[0]) + *packet_size = 0; + else + { + uint16_t slot_size = norminal_size[2] - norminal_size[1]; + if (data_size < fifo_size / 2 - slot_size) + *packet_size = norminal_size[0]; + else if (data_size > fifo_size / 2 + slot_size) + *packet_size = norminal_size[2]; + else + *packet_size = norminal_size[1]; + } + + return true; +} +#endif + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 7c88b99fc..4cb3ca84c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -181,6 +181,11 @@ #endif #endif +// (For TYPE-I format only) Flow control is necessary to allow IN ep send correct amount of data, unless it's a virtual device where data is perfectly synchronized to USB clock. +#ifndef CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 +#endif + // Enable/disable feedback EP (required for asynchronous RX applications) #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 @@ -392,6 +397,10 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_i uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +bool tud_audio_n_set_tx_flow_control (uint8_t func_id, uint32_t sample_rate); +#endif + //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ @@ -670,6 +679,13 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l } #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +static inline bool tud_audio_set_tx_flow_control(uint32_t sample_rate) +{ + return tud_audio_n_set_tx_flow_control(0, sample_rate); +} +#endif + #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) -- cgit v1.3.1 From 0a1d6cf4d028bce2248da01b8cc13aa4673e61b5 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 17 Oct 2023 13:06:55 +0200 Subject: Read sample rate directly from control transfer to eliminate callback. --- examples/device/audio_4_channel_mic/src/main.c | 5 +- src/class/audio/audio_device.c | 301 ++++++++++++++----------- src/class/audio/audio_device.h | 10 - 3 files changed, 173 insertions(+), 143 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 52e6d71f7..9c37315c8 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -407,9 +407,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); - // Set sample rate for flow control - tud_audio_set_tx_flow_control(sampFreq); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + // Buffered control transfer is needed for IN flow control to work + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: TU_LOG2(" Get Sample Freq. range\r\n"); diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 9299440c9..e246281be 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -461,7 +461,8 @@ static inline uint8_t tu_desc_subtype(void const* desc) #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL -static bool audiod_tx_calc_packet_size(const uint16_t* norminal_size, uint16_t data_size, uint16_t fifo_size, uint16_t* packet_size); +static bool audiod_calc_tx_packet_sz(audiod_function_t* audio); +static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_size); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -832,58 +833,6 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1 #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - -bool tud_audio_n_set_tx_flow_control(uint8_t func_id, uint32_t sample_rate) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[func_id]; - - TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I); - TU_VERIFY(audio->n_channels_tx); - TU_VERIFY(audio->n_bytes_per_sampe_tx); - TU_VERIFY(audio->interval_tx); - - if (sample_rate == 0) - { - audio->packet_sz_tx[0] = 0; - audio->packet_sz_tx[1] = 0; - audio->packet_sz_tx[2] = 0; - return false; - } - - const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL) ? audio->interval_tx : 1 << (audio->interval_tx - 1); - - const uint32_t sample_normimal = sample_rate * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); - const uint32_t sample_reminder = sample_rate * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); - - const uint16_t packet_sz_tx_min = (sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; - const uint16_t packet_sz_tx_norm = sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; - const uint16_t packet_sz_tx_max = (sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; - - TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz); - - // Frmt20.pdf 2.3.1.1 USB Packets - if (sample_reminder) - { - // All virtual frame packets must either contain INT(nav) audio slots (small VFP) or INT(nav)+1 (large VFP) audio slots - audio->packet_sz_tx[0] = packet_sz_tx_norm; - audio->packet_sz_tx[1] = packet_sz_tx_norm; - audio->packet_sz_tx[2] = packet_sz_tx_max; - } else - { - // In the case where nav = INT(nav), ni may vary between INT(nav)-1 (small VFP), INT(nav) - // (medium VFP) and INT(nav)+1 (large VFP). - audio->packet_sz_tx[0] = packet_sz_tx_min; - audio->packet_sz_tx[1] = packet_sz_tx_norm; - audio->packet_sz_tx[2] = packet_sz_tx_max; - } - - return true; -} - -#endif - // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. // If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. @@ -949,12 +898,8 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) #else // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - uint16_t tgt_packet_sz; // packet_sz_tx is based on total packet size, here we want size for each support buffer. - if (audiod_tx_calc_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, &tgt_packet_sz)) - n_bytes_tx = tgt_packet_sz; - else - n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); + n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz); #else n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO #endif @@ -1056,7 +1001,6 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // Determine amount of samples uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); uint8_t cnt_ff; @@ -1070,19 +1014,18 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi } #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - uint16_t tgt_packet_sz; + const uint16_t norm_packet_sz_tx[3] = {audio->packet_sz_tx[0] / n_ff_used, + audio->packet_sz_tx[1] / n_ff_used, + audio->packet_sz_tx[2] / n_ff_used}; // packet_sz_tx is based on total packet size, here we want size for each support buffer. - if (audiod_tx_calc_packet_size(audio->packet_sz_tx, nBytesPerFFToSend * n_ff_used, audio->tx_supp_ff[0].depth * n_ff_used, &tgt_packet_sz)) - nBytesPerFFToSend = tgt_packet_sz / n_ff_used; -#endif - + nBytesPerFFToSend = audiod_tx_packet_size(norm_packet_sz_tx, nBytesPerFFToSend, audio->tx_supp_ff[0].depth, audio->ep_in_sz / n_ff_used); + // Check if there is enough data + if (nBytesPerFFToSend == 0) return 0; +#else // Check if there is enough data if (nBytesPerFFToSend == 0) return 0; - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); - -#if !CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, audio->ep_in_sz / n_ff_used); // Round to full number of samples (flooring) uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize; @@ -1349,7 +1292,7 @@ void audiod_init(void) #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING switch (i) { #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 @@ -1529,85 +1472,115 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } #if USE_ISO_EP_ALLOCATION + { #if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in = 0; - uint16_t ep_in_size = 0; + uint8_t ep_in = 0; + uint16_t ep_in_size = 0; #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out = 0; - uint16_t ep_out_size = 0; + uint8_t ep_out = 0; + uint16_t ep_out_size = 0; #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb = 0; + uint8_t ep_fb = 0; #endif - - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + uint8_t const *p_desc = _audiod_fct[i].p_desc; + uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + while (p_desc < p_desc_end) { - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Explicit feedback EP - if (desc_ep->bmAttributes.usage == 1) + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; + if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { - ep_fb = desc_ep->bEndpointAddress; - } + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // Explicit feedback EP + if (desc_ep->bmAttributes.usage == 1) + { + ep_fb = desc_ep->bEndpointAddress; + } #endif - // Data EP - if (desc_ep->bmAttributes.usage == 0) - { - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) + // Data EP + if (desc_ep->bmAttributes.usage == 0) { + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) + { #if CFG_TUD_AUDIO_ENABLE_EP_IN - ep_in = desc_ep->bEndpointAddress; - ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); - #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - _audiod_fct[i].interval_tx = desc_ep->bInterval; - #endif + ep_in = desc_ep->bEndpointAddress; + ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); #endif - } else - { + } else + { #if CFG_TUD_AUDIO_ENABLE_EP_OUT - ep_out = desc_ep->bEndpointAddress; - ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); + ep_out = desc_ep->bEndpointAddress; + ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); #endif + } } - } + } } + + p_desc = tu_desc_next(p_desc); } - p_desc = tu_desc_next(p_desc); - } #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (ep_in) - { - usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size); - } + if (ep_in) + { + usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size); + } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (ep_out) - { - usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size); - } + if (ep_out) + { + usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size); + } #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (ep_fb) - { - usbd_edpt_iso_alloc(rhport, ep_fb, 4); - } + if (ep_fb) + { + usbd_edpt_iso_alloc(rhport, ep_fb, 4); + } #endif - + } #endif // USE_ISO_EP_ALLOCATION +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + { + uint8_t const *p_desc = _audiod_fct[i].p_desc; + uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; + if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + { + if (desc_ep->bmAttributes.usage == 0) + { + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) + { + _audiod_fct[i].interval_tx = desc_ep->bInterval; + } + } + } + } else + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) + { + if(tu_unaligned_read16(p_desc + 4) == AUDIO_TERM_TYPE_USB_STREAMING) + { + _audiod_fct[i].bclock_id_tx = p_desc[8]; + } + } + p_desc = tu_desc_next(p_desc); + } + } +#endif // CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + break; } } @@ -1910,6 +1883,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (disable) usbd_sof_enable(rhport, false); #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + audiod_calc_tx_packet_sz(audio); +#endif + tud_control_status(rhport, p_request); return true; @@ -2352,6 +2329,19 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Copy into buffer TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t)len)); +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + // Find data for sampling_frequency_control + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + { + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO_CS_REQ_CUR) + { + _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf); + } + } +#endif + // Schedule transmit return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); } @@ -2579,28 +2569,79 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL -static bool audiod_tx_calc_packet_size(const uint16_t* norminal_size, uint16_t data_size, uint16_t fifo_size, uint16_t* packet_size) + +static bool audiod_calc_tx_packet_sz(audiod_function_t* audio) { - TU_VERIFY(norminal_size[1]); + TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I); + TU_VERIFY(audio->n_channels_tx); + TU_VERIFY(audio->n_bytes_per_sampe_tx); + TU_VERIFY(audio->interval_tx); + TU_VERIFY(audio->sample_rate_tx); - // This flow control method need a FIFO size of 4*Navg - TU_VERIFY(norminal_size[1] <= fifo_size * 4); + const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL) ? audio->interval_tx : 1 << (audio->interval_tx - 1); - if (data_size < norminal_size[0]) - *packet_size = 0; - else + const uint32_t sample_normimal = audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); + const uint32_t sample_reminder = audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); + + const uint16_t packet_sz_tx_min = (sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + const uint16_t packet_sz_tx_norm = sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + const uint16_t packet_sz_tx_max = (sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + + // Endpoint size must larger than packet size + TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz); + + // Frmt20.pdf 2.3.1.1 USB Packets + if (sample_reminder) { - uint16_t slot_size = norminal_size[2] - norminal_size[1]; - if (data_size < fifo_size / 2 - slot_size) - *packet_size = norminal_size[0]; - else if (data_size > fifo_size / 2 + slot_size) - *packet_size = norminal_size[2]; - else - *packet_size = norminal_size[1]; + // All virtual frame packets must either contain INT(nav) audio slots (small VFP) or INT(nav)+1 (large VFP) audio slots + audio->packet_sz_tx[0] = packet_sz_tx_norm; + audio->packet_sz_tx[1] = packet_sz_tx_norm; + audio->packet_sz_tx[2] = packet_sz_tx_max; + } else + { + // In the case where nav = INT(nav), ni may vary between INT(nav)-1 (small VFP), INT(nav) + // (medium VFP) and INT(nav)+1 (large VFP). + audio->packet_sz_tx[0] = packet_sz_tx_min; + audio->packet_sz_tx[1] = packet_sz_tx_norm; + audio->packet_sz_tx[2] = packet_sz_tx_max; } return true; } + +static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_depth) +{ + // Flow control need a FIFO size of at least 4*Navg + if(norminal_size[1] && norminal_size[1] <= fifo_depth * 4) + { + uint16_t packet_size; + uint16_t slot_size = norminal_size[2] - norminal_size[1]; + if (data_count < fifo_depth / 2 - slot_size) + { + if (data_count < norminal_size[0]) + { + // If you get here frequently, then your I2S clock deviation is too big ! + packet_size = 0; + } else + { + packet_size = norminal_size[0]; + } + } + else if (data_count > fifo_depth / 2 + slot_size) + { + packet_size = norminal_size[2]; + } else + { + packet_size = norminal_size[1]; + } + // Normally this cap is not necessary + return tu_min16(packet_size, max_depth); + } else + { + return tu_min16(data_count, max_depth); + } +} + #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 4cb3ca84c..ef3e12a06 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -397,9 +397,6 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_i uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL -bool tud_audio_n_set_tx_flow_control (uint8_t func_id, uint32_t sample_rate); -#endif //--------------------------------------------------------------------+ // Application API (Interface0) @@ -679,13 +676,6 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l } #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL -static inline bool tud_audio_set_tx_flow_control(uint32_t sample_rate) -{ - return tud_audio_n_set_tx_flow_control(0, sample_rate); -} -#endif - #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) -- cgit v1.3.1 From d83a2107883c8a6224ab99f248a59b216a8d2a82 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 17 Oct 2023 15:18:05 +0200 Subject: Add blackout time. --- src/class/audio/audio_device.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index e246281be..d32ed56b2 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2614,25 +2614,39 @@ static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t da // Flow control need a FIFO size of at least 4*Navg if(norminal_size[1] && norminal_size[1] <= fifo_depth * 4) { + // Use blackout to prioritize normal size packet + static int ctrl_blackout = 0; uint16_t packet_size; uint16_t slot_size = norminal_size[2] - norminal_size[1]; - if (data_count < fifo_depth / 2 - slot_size) + if (data_count < norminal_size[0]) { - if (data_count < norminal_size[0]) - { // If you get here frequently, then your I2S clock deviation is too big ! packet_size = 0; + } else + if (data_count < fifo_depth / 2 - slot_size && !ctrl_blackout) + { + packet_size = norminal_size[0]; + ctrl_blackout = 10; + } else + if (data_count > fifo_depth / 2 + slot_size && !ctrl_blackout) + { + packet_size = norminal_size[2]; + if(norminal_size[0] == norminal_size[1]) + { + // nav = INT(nav) + 1 + ctrl_blackout = 2; } else { - packet_size = norminal_size[0]; + // nav = INT(nav) + ctrl_blackout = 10; } - } - else if (data_count > fifo_depth / 2 + slot_size) - { - packet_size = norminal_size[2]; } else { packet_size = norminal_size[1]; + if (ctrl_blackout) + { + ctrl_blackout--; + } } // Normally this cap is not necessary return tu_min16(packet_size, max_depth); -- cgit v1.3.1 From e9d894fe6620d623bc393698a971d08d43516e01 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 17 Oct 2023 15:23:05 +0200 Subject: Fix compile. --- .../device/audio_4_channel_mic/src/tusb_config.h | 5 +++-- src/class/audio/audio_device.c | 26 +++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index d1e19c5a1..f86b63528 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -115,7 +115,8 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 +#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 +#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 #if CFG_TUD_AUDIO_ENABLE_ENCODING @@ -129,7 +130,7 @@ extern "C" { #else -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX 4 * CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 4 * CFG_TUD_AUDIO_EP_SZ_IN #endif diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d32ed56b2..220771aec 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -217,7 +217,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; // Software encoding/decoding support FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO @@ -225,7 +225,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO @@ -233,7 +233,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO @@ -243,7 +243,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO @@ -251,7 +251,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO @@ -259,7 +259,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO @@ -2519,7 +2519,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * } #endif -#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING if (as_itf == audio->ep_out_as_intf_num) { audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; @@ -2552,7 +2552,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * } #endif -#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING if (as_itf == audio->ep_out_as_intf_num) { audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; @@ -2580,12 +2580,12 @@ static bool audiod_calc_tx_packet_sz(audiod_function_t* audio) const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL) ? audio->interval_tx : 1 << (audio->interval_tx - 1); - const uint32_t sample_normimal = audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); - const uint32_t sample_reminder = audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000); + const uint16_t sample_normimal = (uint16_t)(audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000)); + const uint16_t sample_reminder = (uint16_t)(audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000)); - const uint16_t packet_sz_tx_min = (sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; - const uint16_t packet_sz_tx_norm = sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; - const uint16_t packet_sz_tx_max = (sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx; + const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx); + const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx); + const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx); // Endpoint size must larger than packet size TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz); -- cgit v1.3.1 From ade8a19aefa91e4aba0bbb0ddeafbcd041c6a4c3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 17 Oct 2023 21:21:52 +0200 Subject: Put sw_buf in USB section only if necessary. --- src/class/audio/audio_device.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 220771aec..9712afde9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -110,24 +110,36 @@ #error Maximum number of audio functions restricted to three! #endif +// Put sw_buf in USB section only if necessary +#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING +#define IN_SW_BUF_MEM_SECTION +#else +#define IN_SW_BUF_MEM_SECTION CFG_TUD_MEM_SECTION +#endif +#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING +#define OUT_SW_BUF_MEM_SECTION +#else +#define OUT_SW_BUF_MEM_SECTION CFG_TUD_MEM_SECTION +#endif + // EP IN software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; + IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; + IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; + IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO #endif @@ -154,21 +166,21 @@ // EP OUT software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; + OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; + OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; + OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO #endif -- cgit v1.3.1 From d3fa3cdf487be5929240bc23f9d109c5e3e947bc Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 18 Oct 2023 17:05:35 +0200 Subject: Adjsut blackout time. --- examples/device/audio_4_channel_mic/src/tusb_config.h | 4 ++-- src/class/audio/audio_device.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index f86b63528..cf44918e2 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -126,12 +126,12 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 #define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value #define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 4 * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 4 * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Minimum 4*EP size is needed for flow control #else #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 4 * CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 4 * CFG_TUD_AUDIO_EP_SZ_IN // Minimum 4*EP size is needed for flow control #endif diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 9712afde9..9af999992 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2645,11 +2645,11 @@ static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t da packet_size = norminal_size[2]; if(norminal_size[0] == norminal_size[1]) { - // nav = INT(nav) + 1 - ctrl_blackout = 2; + // nav > INT(nav), eg. 44.1k, 88.2k + ctrl_blackout = 0; } else { - // nav = INT(nav) + // nav = INT(nav), eg. 48k, 96k ctrl_blackout = 10; } } else -- cgit v1.3.1 From 8bac68db84ccbf4f9fbd0d6075b6a1b0253c081a Mon Sep 17 00:00:00 2001 From: Antonio Vázquez Blanco Date: Wed, 11 Oct 2023 10:15:52 +0200 Subject: Add historical EP compatibility to bth class --- src/class/bth/bth_device.c | 2 +- src/class/bth/bth_device.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index c5c74d26a..be36e8c11 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -204,7 +204,7 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) { // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); + TU_VERIFY((CFG_TUD_BTH_HISTORICAL_COMPAT && request->bRequest == 0xe0) || (request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0)); } else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 921bd7a1a..c23e74bfb 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -39,6 +39,13 @@ #ifndef CFG_TUD_BTH_DATA_EPSIZE #define CFG_TUD_BTH_DATA_EPSIZE 64 #endif +#ifndef CFG_TUD_BTH_HISTORICAL_COMPAT +#define CFG_TUD_BTH_HISTORICAL_COMPAT 0 +#endif +#ifndef CFG_TUD_BTH_ISO_ALT_COUNT +// See Bluetooth Core v5.3, Vol. 4, Part B, Section 2.1 +#error You must tell the driver the number of ISO endpoints to use +#endif typedef struct TU_ATTR_PACKED { -- cgit v1.3.1 From aedc92f2d31af6209b00e8a5d7abbfec02ed979b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Nov 2023 11:25:55 +0700 Subject: fix typo in cdc line coding enum --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- examples/host/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- src/class/cdc/cdc.h | 20 +++++++++++--------- src/class/cdc/cdc_host.h | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/class') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index c8e9138e3..a53000a11 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -118,7 +118,7 @@ // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t // bit rate = 115200, 1 stop bit, no parity, 8 bit data width -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } #ifdef __cplusplus diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 1bed9a9b3..ba23301ed 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -123,7 +123,7 @@ // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t // bit rate = 115200, 1 stop bit, no parity, 8 bit data width -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } #ifdef __cplusplus diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 4658e43af..deec32ae4 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -182,21 +182,23 @@ typedef enum CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, }cdc_management_request_t; -enum -{ +enum { CDC_CONTROL_LINE_STATE_DTR = 0x01, CDC_CONTROL_LINE_STATE_RTS = 0x02, }; -enum -{ - CDC_LINE_CONDING_STOP_BITS_1 = 0, // 1 bit - CDC_LINE_CONDING_STOP_BITS_1_5 = 1, // 1.5 bits - CDC_LINE_CONDING_STOP_BITS_2 = 2, // 2 bits +enum { + CDC_LINE_CODING_STOP_BITS_1 = 0, // 1 bit + CDC_LINE_CODING_STOP_BITS_1_5 = 1, // 1.5 bits + CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits }; -enum -{ +// TODO Backward compatible for typos. Maybe removed in the future release +#define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1 +#define CDC_LINE_CONDING_STOP_BITS_1_5 CDC_LINE_CODING_STOP_BITS_1_5 +#define CDC_LINE_CONDING_STOP_BITS_2 CDC_LINE_CODING_STOP_BITS_2 + +enum { CDC_LINE_CODING_PARITY_NONE = 0, CDC_LINE_CODING_PARITY_ODD = 1, CDC_LINE_CODING_PARITY_EVEN = 2, diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 19552f1ee..9e5edd94e 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -44,7 +44,7 @@ // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t //#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM -//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } +//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } //#endif // RX FIFO size -- cgit v1.3.1 From 6e5c7f43906bac8ab47642e56c153297b83f3679 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Nov 2023 16:08:06 +0700 Subject: rename to CFG_TUD_BTH_HISTORICAL_COMPATIBLE, move CFG_TUD_BTH_ISO_ALT_COUNT to tusb_option.h and mandatory for BTH driver --- src/class/bth/bth_device.c | 4 +++- src/class/bth/bth_device.h | 12 ++++++------ src/device/usbd.h | 4 ---- src/tusb_option.h | 13 +++++++++---- 4 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src/class') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index be36e8c11..f145e2ead 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -204,7 +204,9 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) { // HCI command packet addressing for single function Primary Controllers - TU_VERIFY((CFG_TUD_BTH_HISTORICAL_COMPAT && request->bRequest == 0xe0) || (request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0)); + // also compatible with historical mode if enabled + TU_VERIFY((request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0) || + (CFG_TUD_BTH_HISTORICAL_COMPATIBLE && request->bRequest == 0xe0)); } else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index c23e74bfb..e782c532b 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -36,15 +36,15 @@ #ifndef CFG_TUD_BTH_EVENT_EPSIZE #define CFG_TUD_BTH_EVENT_EPSIZE 16 #endif + #ifndef CFG_TUD_BTH_DATA_EPSIZE #define CFG_TUD_BTH_DATA_EPSIZE 64 #endif -#ifndef CFG_TUD_BTH_HISTORICAL_COMPAT -#define CFG_TUD_BTH_HISTORICAL_COMPAT 0 -#endif -#ifndef CFG_TUD_BTH_ISO_ALT_COUNT -// See Bluetooth Core v5.3, Vol. 4, Part B, Section 2.1 -#error You must tell the driver the number of ISO endpoints to use + +// Allow BTH class to work in historically compatibility mode where the bRequest is always 0xe0. +// See Bluetooth Core v5.3, Vol. 4, Part B, Section 2.2 +#ifndef CFG_TUD_BTH_HISTORICAL_COMPATIBLE +#define CFG_TUD_BTH_HISTORICAL_COMPATIBLE 0 #endif typedef struct TU_ATTR_PACKED diff --git a/src/device/usbd.h b/src/device/usbd.h index 93a2033c4..e14e3d6de 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -771,10 +771,6 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 #define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 -#ifndef CFG_TUD_BTH_ISO_ALT_COUNT -#define CFG_TUD_BTH_ISO_ALT_COUNT 0 -#endif - // Length of template descriptor: 38 bytes + number of ISO alternatives * 23 #define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) diff --git a/src/tusb_option.h b/src/tusb_option.h index b8509a069..7920fbf35 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -342,6 +342,15 @@ #define CFG_TUD_INTERFACE_MAX 16 #endif +//------------- Device Class Driver -------------// +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + +#if CFG_TUD_BTH && !defined(CFG_TUD_BTH_ISO_ALT_COUNT) +#error CFG_TUD_BTH_ISO_ALT_COUNT must be defined to tell Bluetooth driver the number of ISO endpoints to use +#endif + #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif @@ -382,10 +391,6 @@ #define CFG_TUD_DFU 0 #endif -#ifndef CFG_TUD_BTH - #define CFG_TUD_BTH 0 -#endif - #ifndef CFG_TUD_ECM_RNDIS #ifdef CFG_TUD_NET #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" -- cgit v1.3.1 From 2fed722b0004e64667df526043f3bfcb131d3ee3 Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Sun, 27 Aug 2023 15:21:15 -0400 Subject: add tuh_hid_set_default_protocol() to set default USB host HID protocol --- src/class/hid/hid_host.c | 11 +++++++++-- src/class/hid/hid_host.h | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a3551c85a..80312676a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -211,6 +211,13 @@ static void set_protocol_complete(tuh_xfer_t* xfer) } } +CFG_TUH_MEM_SECTION +tu_static uint8_t _hidh_default_protocol = HID_PROTOCOL_BOOT; + +void tuh_hid_set_default_protocol(uint8_t protocol) { + _hidh_default_protocol = protocol; +} + static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("HID Set Protocol = %d\r\n", protocol); @@ -521,7 +528,7 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_ p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config - p_hid->protocol_mode = HID_PROTOCOL_BOOT; + p_hid->protocol_mode = _hidh_default_protocol; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { p_hid->itf_protocol = desc_itf->bInterfaceProtocol; @@ -591,7 +598,7 @@ static void process_set_config(tuh_xfer_t* xfer) break; case CONFIG_SET_PROTOCOL: - _hidh_set_protocol(daddr, p_hid->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC); + _hidh_set_protocol(daddr, p_hid->itf_num, _hidh_default_protocol, process_set_config, CONFIG_GET_REPORT_DESC); break; case CONFIG_GET_REPORT_DESC: diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 08ad421d2..3c59e301d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -97,6 +97,11 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Application can use set_protocol() to switch back to Report protocol. uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t idx); +// Device by default is initialized in Boot protocol for simplicity. Application +// can use this to modify the default protocol before calling tuh_init(), or use +// set_protocol() to change the protocol after initialization. +void tuh_hid_set_default_protocol(uint8_t protocol); + // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t idx, uint8_t protocol); -- cgit v1.3.1 From f469250fa34929b1890500b1d7abfb2a7bb7dcc5 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Nov 2023 18:35:00 +0700 Subject: minor update --- src/class/hid/hid_host.c | 5 ++--- src/class/hid/hid_host.h | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src/class') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 80312676a..db52b503f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -67,6 +67,8 @@ typedef struct CFG_TUH_MEM_SECTION tu_static hidh_interface_t _hidh_itf[CFG_TUH_HID]; +tu_static uint8_t _hidh_default_protocol = HID_PROTOCOL_BOOT; + //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ @@ -211,9 +213,6 @@ static void set_protocol_complete(tuh_xfer_t* xfer) } } -CFG_TUH_MEM_SECTION -tu_static uint8_t _hidh_default_protocol = HID_PROTOCOL_BOOT; - void tuh_hid_set_default_protocol(uint8_t protocol) { _hidh_default_protocol = protocol; } diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3c59e301d..238b7c627 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -97,9 +97,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Application can use set_protocol() to switch back to Report protocol. uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t idx); -// Device by default is initialized in Boot protocol for simplicity. Application -// can use this to modify the default protocol before calling tuh_init(), or use -// set_protocol() to change the protocol after initialization. +// Device by default is enumerated in Boot protocol for simplicity. Application +// can use this to modify the default protocol for next enumeration. void tuh_hid_set_default_protocol(uint8_t protocol); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -- cgit v1.3.1 From c4e04d3db4f8f33e906afbae4739d64e53fa9987 Mon Sep 17 00:00:00 2001 From: Oliver Larsson Date: Sun, 29 Oct 2023 16:53:10 +0100 Subject: Add configuration option CFG_TUH_CDC_CP210X_PID_LIST to tusb_option.h --- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/serial/cp210x.h | 2 -- src/tusb_option.h | 6 ++++++ 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 53e15710e..a6af9b84d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -109,7 +109,7 @@ static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tu #if CFG_TUH_CDC_CP210X #include "serial/cp210x.h" -static uint16_t const cp210x_pids[] = { TU_CP210X_PID_LIST }; +static uint16_t const cp210x_pids[] = { CFG_TUH_CDC_CP210X_PID_LIST }; enum { CP210X_PID_COUNT = sizeof(cp210x_pids) / sizeof(cp210x_pids[0]) }; diff --git a/src/class/cdc/serial/cp210x.h b/src/class/cdc/serial/cp210x.h index b01417092..2c749f522 100644 --- a/src/class/cdc/serial/cp210x.h +++ b/src/class/cdc/serial/cp210x.h @@ -29,8 +29,6 @@ // https://www.silabs.com/documents/public/application-notes/AN571.pdf #define TU_CP210X_VID 0x10C4 -#define TU_CP210X_PID_LIST \ - 0xEA60, 0xEA70 /* Config request codes */ #define CP210X_IFC_ENABLE 0x00 diff --git a/src/tusb_option.h b/src/tusb_option.h index a41f5a07e..3d290ae66 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -441,6 +441,12 @@ #define CFG_TUH_CDC_CP210X 0 #endif +#ifndef CFG_TUH_CDC_CP210X_PID_LIST + // List of product IDs that can use the CP210X CDC driver + #define CFG_TUH_CDC_CP210X_PID_LIST \ + 0xEA60, 0xEA70 +#endif + #ifndef CFG_TUH_HID #define CFG_TUH_HID 0 #endif -- cgit v1.3.1 From ac418f4d25400c12864b242f94215664dc5d9229 Mon Sep 17 00:00:00 2001 From: Angel Molina Date: Sat, 9 Dec 2023 23:13:53 +0100 Subject: Fix strict-overflow warning when compiling with gcc >= 12 --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 9af999992..731c39b54 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1565,7 +1565,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { uint8_t const *p_desc = _audiod_fct[i].p_desc; uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - while (p_desc < p_desc_end) + while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { -- cgit v1.3.1 From 506617d4b39ba9118a24477a4be6db9733e2e2f1 Mon Sep 17 00:00:00 2001 From: Ángel Molina Núñez Date: Sun, 10 Dec 2023 17:04:46 +0100 Subject: Add comment to explain why the condition changes --- src/class/audio/audio_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/class') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 731c39b54..d438d0715 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1565,6 +1565,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { uint8_t const *p_desc = _audiod_fct[i].p_desc; uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) -- cgit v1.3.1 From 9a7e23379ccd4fe572af824c09d6113401412522 Mon Sep 17 00:00:00 2001 From: Oliver Larsson Date: Mon, 11 Dec 2023 09:36:10 +0100 Subject: Add configuration option CFG_TUH_CDC_FTDI_PID_LIST to tusb_option.h --- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/serial/ftdi_sio.h | 5 +---- src/tusb_option.h | 6 ++++++ 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a6af9b84d..a6dfb45ae 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -90,7 +90,7 @@ static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfe #if CFG_TUH_CDC_FTDI #include "serial/ftdi_sio.h" -static uint16_t const ftdi_pids[] = { TU_FTDI_PID_LIST }; +static uint16_t const ftdi_pids[] = { CFG_TUH_CDC_FTDI_PID_LIST }; enum { FTDI_PID_COUNT = sizeof(ftdi_pids) / sizeof(ftdi_pids[0]) }; diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index 6916e4031..0825f0719 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -25,11 +25,8 @@ #ifndef TUSB_FTDI_SIO_H #define TUSB_FTDI_SIO_H -// VID/PID for matching FTDI devices +// VID for matching FTDI devices #define TU_FTDI_VID 0x0403 -#define TU_FTDI_PID_LIST \ - 0x6001, 0x6006, 0x6010, 0x6011, 0x6014, 0x6015, 0x8372, 0xFBFA, \ - 0xcd18 // Commands #define FTDI_SIO_RESET 0 /* Reset the port */ diff --git a/src/tusb_option.h b/src/tusb_option.h index 900784388..7597392d6 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -442,6 +442,12 @@ #define CFG_TUH_CDC_FTDI 0 #endif +#ifndef CFG_TUH_CDC_FTDI_PID_LIST + // List of product IDs that can use the FTDI CDC driver + #define CFG_TUH_CDC_FTDI_PID_LIST \ + 0x6001, 0x6006, 0x6010, 0x6011, 0x6014, 0x6015, 0x8372, 0xFBFA, 0xCD18 +#endif + #ifndef CFG_TUH_CDC_CP210X // CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 0 -- cgit v1.3.1 From 91f65a36bfb1d4516c39306e77fb15d4e1c2fc0b Mon Sep 17 00:00:00 2001 From: IngHK Date: Tue, 9 Jan 2024 09:53:54 +0100 Subject: [CDC] host: moved acm_open to other acm prototypes --- src/class/cdc/cdc_host.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a6dfb45ae..b20da3723 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -80,6 +80,7 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC]; //--------------------------------------------------------------------+ //------------- ACM prototypes -------------// +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void acm_process_config(tuh_xfer_t* xfer); static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -605,8 +606,6 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // Enumeration //--------------------------------------------------------------------+ -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); - static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const *desc_ep) { for(size_t i=0; i<2; i++) -- cgit v1.3.1 From c619a861414d2edeb34c5f59b74ed0fe28b39172 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 11 Jan 2024 08:53:47 +0100 Subject: bInterfaceClass number replaced by define --- src/class/cdc/cdc_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index b20da3723..79477ef53 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -641,7 +641,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d return acm_open(daddr, itf_desc, max_len); } #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X - else if ( 0xff == itf_desc->bInterfaceClass ) + else if ( TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass ) { uint16_t vid, pid; TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); -- cgit v1.3.1