3 #include "class/audio/audio.h"
4 #include "common/tusb_mcu.h"
5 #include "common/tusb_verify.h"
6 #include "device/usbd.h"
7 #include "device/usbd_pvt.h"
10 #include "tusb_option.h"
13 #undef OUT_SW_BUF_MEM_SECTION
14 #undef CFG_TUSB_MEM_ALIGN
15 #define OUT_SW_BUF_MEM_SECTION
16 #define CFG_TUSB_MEM_ALIGN
21 AUDIO_FEEDBACK_METHOD_DISABLED,
22 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
23 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
24 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
25 AUDIO_FEEDBACK_METHOD_FIFO_COUNT
47 uint32_t sample_rate = 48000;
48 uint8_t bits_per_sample = 16;
49 bool enable_feedback_ep =
true;
50 bool enable_interrupt_ep =
true;
51 bool enable_feedback_forward_correction =
false;
52 bool enable_feedback_interval_isr =
false;
53 bool enable_ep_in_flow_control =
true;
54 bool enable_linear_buffer_tx =
true;
55 bool enable_linear_buffer_rx =
true;
56 bool enable_fifo_mutex = CFG_FIFO_MUTEX;
57 int func_n_as_int = 1;
58 int func_ctl_buffer_size = 0;
59 int func_ep_in_sw_buffer_size = 0;
60 int func_ep_out_sw_buffer_size = 0;
61 int func_ep_in_size_max = 0;
62 int func_ep_out_size_max = 0;
63 size_t (*p_write_callback)(
const uint8_t *data,
size_t len,
65 size_t (*p_read_callback)(uint8_t *data,
size_t len,
68 bool is_ep_out() {
return p_write_callback !=
nullptr; }
69 bool is_ep_in() {
return p_read_callback !=
nullptr; };
73 if (func_ctl_buffer_size == 0) func_ctl_buffer_size = 64;
74 if (func_ep_in_size_max == 0)
76 TUD_AUDIO_EP_SIZE(sample_rate, bits_per_sample / 8, channels);
77 if (func_ep_out_size_max == 0)
78 func_ep_out_size_max =
79 TUD_AUDIO_EP_SIZE(sample_rate, bits_per_sample / 8, channels);
80 if (func_ep_out_size_max == 0)
81 func_ep_in_sw_buffer_size =
82 (TUD_OPT_HIGH_SPEED ? 32 : 4) *
85 if (func_ep_out_sw_buffer_size == 0)
86 func_ep_out_sw_buffer_size =
87 (TUD_OPT_HIGH_SPEED ? 32 : 4) *
92 func_ctl_buffer_size = 0;
93 func_ep_in_size_max = 0;
94 func_ep_out_size_max = 0;
95 func_ep_in_sw_buffer_size = 0;
96 func_ep_out_sw_buffer_size = 0;
106 virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
107 uint16_t bufsize) = 0;
109 virtual size_t getInterfaceDescriptorLength(uint8_t itfnum) = 0;
113 virtual bool set_itf_cb(uint8_t rhport,
114 tusb_control_request_t
const *p_request) = 0;
117 virtual bool set_req_ep_cb(uint8_t rhport,
118 tusb_control_request_t
const *p_request,
122 virtual bool set_req_itf_cb(uint8_t rhport,
123 tusb_control_request_t
const *p_request,
127 virtual bool set_req_entity_cb(uint8_t rhport,
128 tusb_control_request_t
const *p_request,
131 virtual bool get_req_ep_cb(uint8_t rhport,
132 tusb_control_request_t
const *p_request) = 0;
135 virtual bool get_req_itf_cb(uint8_t rhport,
136 tusb_control_request_t
const *p_request) = 0;
139 virtual bool get_req_entity_cb(uint8_t rhport,
140 tusb_control_request_t
const *p_request) = 0;
141 virtual bool tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in,
142 uint8_t cur_alt_setting) = 0;
144 virtual bool tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied,
145 uint8_t itf, uint8_t ep_in,
146 uint8_t cur_alt_setting) = 0;
148 virtual bool rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received,
149 uint8_t func_id, uint8_t ep_out,
150 uint8_t cur_alt_setting) = 0;
151 virtual bool rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received,
152 uint8_t func_id, uint8_t ep_out,
153 uint8_t cur_alt_setting) = 0;
155 virtual bool set_itf_close_EP_cb(uint8_t rhport,
156 tusb_control_request_t
const *p_request) = 0;
159 virtual void feedback_params_cb(uint8_t func_id, uint8_t alt_itf,
162 virtual void int_done_cb(uint8_t rhport) {};
163 virtual void fb_done_cb(uint8_t func_id) {};
164 virtual void feedback_interval_isr(uint8_t func_id, uint32_t frame_number,
165 uint8_t interval_shift) {}
167 virtual uint8_t allocInterface(uint8_t count = 1) = 0;
168 virtual uint8_t allocEndpoint(uint8_t in) = 0;
179 bool tud_audio_n_mounted(uint8_t func_id) {
180 TU_VERIFY(func_id < cfg.func_n_as_int);
183 return audio->mounted;
190 uint16_t tud_audio_n_available(uint8_t func_id) {
191 TU_VERIFY(func_id < cfg.func_n_as_int &&
192 _audiod_fct[func_id].p_desc != NULL);
193 return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff);
196 uint16_t tud_audio_n_read(uint8_t func_id,
void *buffer, uint16_t bufsize) {
197 TU_VERIFY(func_id < cfg.func_n_as_int &&
198 _audiod_fct[func_id].p_desc != NULL);
199 return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize);
202 bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) {
203 TU_VERIFY(func_id < cfg.func_n_as_int &&
204 _audiod_fct[func_id].p_desc != NULL);
205 return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff);
208 tu_fifo_t *tud_audio_n_get_ep_out_ff(uint8_t func_id) {
209 if (func_id < cfg.func_n_as_int && _audiod_fct[func_id].p_desc != NULL)
210 return &_audiod_fct[func_id].ep_out_ff;
232 TU_VERIFY(func_id < cfg.func_n_as_int &&
233 _audiod_fct[func_id].p_desc != NULL);
234 return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len);
237 bool tud_audio_n_clear_ep_in_ff(
240 TU_VERIFY(func_id < cfg.func_n_as_int &&
241 _audiod_fct[func_id].p_desc != NULL);
242 return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff);
245 tu_fifo_t *tud_audio_n_get_ep_in_ff(uint8_t func_id) {
246 if (func_id < cfg.func_n_as_int && _audiod_fct[func_id].p_desc != NULL)
247 return &_audiod_fct[func_id].ep_in_ff;
254 bool tud_audio_int_n_write(uint8_t func_id,
255 const audio_interrupt_data_t *data) {
256 TU_VERIFY(func_id < cfg.func_n_as_int &&
257 _audiod_fct[func_id].p_desc != NULL);
259 TU_VERIFY(_audiod_fct[func_id].ep_int != 0);
263 TU_VERIFY(usbd_edpt_claim(_audiod_fct[func_id].rhport,
264 _audiod_fct[func_id].ep_int));
267 if (tu_memcpy_s(_audiod_fct[func_id].ep_int_buf,
268 sizeof(_audiod_fct[func_id].ep_int_buf), data,
269 sizeof(audio_interrupt_data_t)) == 0) {
271 TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport,
272 _audiod_fct[func_id].ep_int,
273 _audiod_fct[func_id].ep_int_buf,
274 sizeof(_audiod_fct[func_id].ep_int_buf)),
278 usbd_edpt_release(_audiod_fct[func_id].rhport,
279 _audiod_fct[func_id].ep_int);
295 if (p_cb ==
nullptr)
return;
296 _audiod_fct.resize(cfg.func_n_as_int);
297 ctrl_buf_1.resize(cfg.func_ctl_buffer_size);
298 alt_setting_1.resize(cfg.func_n_as_int);
300 if (cfg.is_ep_in()) {
301 if (cfg.enable_linear_buffer_rx)
302 lin_buf_in_1.resize(cfg.func_ep_in_size_max);
303 audio_ep_in_sw_buf_1.resize(cfg.func_ep_in_sw_buffer_size);
306 if (cfg.is_ep_out()) {
307 if (cfg.enable_linear_buffer_tx)
308 audio_ep_out_sw_buf_1.resize(cfg.func_ep_out_sw_buffer_size);
309 lin_buf_out_1.resize(cfg.func_ep_out_sw_buffer_size);
312 audiod_function_t *audio = &_audiod_fct[0];
314 audio->ctrl_buf = ctrl_buf_1.data();
315 audio->ctrl_buf_sz = cfg.func_ctl_buffer_size;
316 audio->alt_setting = alt_setting_1.data();
319 if (cfg.is_ep_in()) {
320 tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1.data(),
321 cfg.func_ep_in_sw_buffer_size, 1,
true);
322 if (cfg.enable_fifo_mutex)
323 tu_fifo_config_mutex(&audio->ep_in_ff,
324 osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL);
329 if (cfg.enable_linear_buffer_tx) audio->lin_buf_in = lin_buf_in_1.data();
332 if (cfg.is_ep_out()) {
333 tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1.data(),
334 cfg.func_ep_in_sw_buffer_size, 1,
true);
335 if (cfg.enable_fifo_mutex)
336 tu_fifo_config_mutex(&audio->ep_out_ff, NULL,
337 osal_mutex_create(&ep_out_ff_mutex_rd_1));
341 if (cfg.enable_linear_buffer_rx) audio->lin_buf_out = lin_buf_out_1.data();
344 bool audiod_deinit(
void) {
return true; }
346 void audiod_reset(uint8_t rhport) {
349 for (uint8_t i = 0; i < cfg.func_n_as_int; i++) {
350 audiod_function_t *audio = &_audiod_fct[i];
351 tu_memclr(audio,
sizeof(audiod_function_t));
353 if (cfg.is_ep_in()) tu_fifo_clear(&audio->ep_in_ff);
355 if (cfg.is_ep_out()) tu_fifo_clear(&audio->ep_out_ff);
359 uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t
const *itf_desc,
362 if (p_cb ==
nullptr)
return 0;
364 int cls_tobe = TUSB_CLASS_AUDIO;
365 int cls_is = itf_desc->bInterfaceClass;
374 TU_ASSERT(itf_desc->bNumEndpoints <= 1);
375 if (itf_desc->bNumEndpoints == 1) {
376 TU_ASSERT(cfg.enable_interrupt_ep);
380 TU_VERIFY(itf_desc->bAlternateSetting == 0);
384 for (i = 0; i < cfg.func_n_as_int; i++) {
385 if (!_audiod_fct[i].p_desc) {
386 int len = p_cb->getInterfaceDescriptor(i,
nullptr, 0);
387 _audiod_fct[i].desc_length = len;
388 descriptor.resize(len);
389 _audiod_fct[i].p_desc = descriptor.data();
390 p_cb->getInterfaceDescriptor(i, descriptor.data(), len);
391 _audiod_fct[i].rhport = rhport;
393 #ifdef TUP_DCD_EDPT_ISO_ALLOC
396 uint16_t ep_in_size = 0;
399 uint16_t ep_out_size = 0;
402 uint8_t
const *p_desc = _audiod_fct[i].p_desc;
403 uint8_t
const *p_desc_end =
404 p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
407 while (p_desc_end - p_desc > 0) {
408 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
409 tusb_desc_endpoint_t
const *desc_ep =
410 (tusb_desc_endpoint_t
const *)p_desc;
411 if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
412 if (cfg.enable_feedback_ep) {
414 if (desc_ep->bmAttributes.usage == 1) {
415 ep_fb = desc_ep->bEndpointAddress;
419 if (desc_ep->bmAttributes.usage == 0) {
420 if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
421 if (cfg.is_ep_in()) {
422 ep_in = desc_ep->bEndpointAddress;
424 TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
427 if (cfg.is_ep_out()) {
428 ep_out = desc_ep->bEndpointAddress;
430 TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
437 p_desc = tu_desc_next(p_desc);
440 if (cfg.is_ep_in() && ep_in) {
441 usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
445 if (cfg.is_ep_out() && ep_out) {
446 usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
449 if (cfg.enable_feedback_ep) {
451 usbd_edpt_iso_alloc(rhport, ep_fb, 4);
458 if (cfg.is_ep_in() && cfg.enable_ep_in_flow_control) {
459 uint8_t
const *p_desc = _audiod_fct[i].p_desc;
460 uint8_t
const *p_desc_end =
461 p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
464 while (p_desc_end - p_desc > 0) {
465 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
466 tusb_desc_endpoint_t
const *desc_ep =
467 (tusb_desc_endpoint_t
const *)p_desc;
468 if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
469 if (desc_ep->bmAttributes.usage == 0) {
470 if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
471 _audiod_fct[i].interval_tx = desc_ep->bInterval;
475 }
else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
476 tu_desc_subtype(p_desc) ==
477 AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
478 if (tu_unaligned_read16(p_desc + 4) ==
479 AUDIO_TERM_TYPE_USB_STREAMING) {
480 _audiod_fct[i].bclock_id_tx = p_desc[8];
483 p_desc = tu_desc_next(p_desc);
487 if (cfg.enable_interrupt_ep) {
488 uint8_t
const *p_desc = _audiod_fct[i].p_desc;
489 uint8_t
const *p_desc_end =
490 p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
493 while (p_desc_end - p_desc > 0) {
495 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
496 tusb_desc_endpoint_t
const *desc_ep =
497 (tusb_desc_endpoint_t
const *)p_desc;
498 uint8_t
const ep_addr = desc_ep->bEndpointAddress;
500 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
501 desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) {
503 _audiod_fct[i].ep_int = ep_addr;
504 TU_ASSERT(usbd_edpt_open(_audiod_fct[i].rhport, desc_ep));
507 p_desc = tu_desc_next(p_desc);
511 _audiod_fct[i].mounted =
true;
517 TU_ASSERT(i < cfg.func_n_as_int);
522 _audiod_fct[i].desc_length -
523 TUD_AUDIO_DESC_IAD_LEN;
530 bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage,
531 tusb_control_request_t
const *request) {
532 if (stage == CONTROL_STAGE_SETUP) {
533 return audiod_control_request(rhport, request);
534 }
else if (stage == CONTROL_STAGE_DATA) {
535 return audiod_control_complete(rhport, request);
541 bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
542 uint32_t xferred_bytes) {
548 for (uint8_t func_id = 0; func_id < cfg.func_n_as_int; func_id++) {
549 audiod_function_t *audio = &_audiod_fct[func_id];
551 if (cfg.enable_interrupt_ep) {
553 if (audio->ep_int == ep_addr) {
567 if (p_cb) p_cb->int_done_cb(rhport);
571 if (cfg.is_ep_in()) {
573 if (audio->ep_in == ep_addr && audio->alt_setting != 0) {
596 TU_VERIFY(audiod_tx_done_cb(rhport, audio));
603 if (cfg.is_ep_out()) {
605 if (audio->ep_out == ep_addr) {
606 TU_VERIFY(audiod_rx_done_cb(rhport, audio, (uint16_t)xferred_bytes));
610 if (cfg.enable_feedback_ep) {
612 if (audio->ep_fb == ep_addr) {
613 if (p_cb) p_cb->fb_done_cb(func_id);
616 if (!usbd_edpt_busy(rhport, audio->ep_fb)) {
620 return audiod_fb_send(rhport, audio);
630 bool tud_audio_buffer_and_schedule_control_xfer(
631 uint8_t rhport, tusb_control_request_t
const *p_request,
void *data,
634 if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT)
return false;
638 uint8_t itf = TU_U16_LOW(p_request->wIndex);
641 switch (p_request->bmRequestType_bit.recipient) {
642 case TUSB_REQ_RCPT_INTERFACE: {
643 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
649 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
653 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
657 case TUSB_REQ_RCPT_ENDPOINT: {
658 uint8_t ep = TU_U16_LOW(p_request->wIndex);
661 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
666 TU_LOG2(
" Unsupported recipient: %d\r\n",
667 p_request->bmRequestType_bit.recipient);
673 if (len > _audiod_fct[func_id].ctrl_buf_sz)
674 len = _audiod_fct[func_id].ctrl_buf_sz;
677 TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf,
678 _audiod_fct[func_id].ctrl_buf_sz, data,
681 if (cfg.is_ep_in() && cfg.enable_ep_in_flow_control) {
683 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
684 p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) {
685 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
686 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
687 if (_audiod_fct[func_id].bclock_id_tx == entityID &&
688 ctrlSel == AUDIO_CS_CTRL_SAM_FREQ &&
689 p_request->bRequest == AUDIO_CS_REQ_CUR) {
690 _audiod_fct[func_id].sample_rate_tx =
691 tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf);
697 return tud_control_xfer(rhport, p_request,
698 (
void *)_audiod_fct[func_id].ctrl_buf, len);
701 bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) {
702 TU_VERIFY(func_id < cfg.func_n_as_int &&
703 _audiod_fct[func_id].p_desc != NULL);
706 if (cfg.enable_feedback_forward_correction) {
707 if (TUSB_SPEED_FULL == tud_speed_get()) {
708 uint8_t *fb = (uint8_t *)&_audiod_fct[func_id].feedback.value;
711 *(fb++) = (feedback >> 2) & 0xFF;
712 *(fb++) = (feedback >> 10) & 0xFF;
713 *(fb++) = (feedback >> 18) & 0xFF;
719 _audiod_fct[func_id].feedback.value = feedback;
723 if (!usbd_edpt_busy(_audiod_fct[func_id].rhport,
724 _audiod_fct[func_id].ep_fb)) {
725 return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]);
731 void audiod_sof_isr(uint8_t rhport, uint32_t frame_count) {
735 if (cfg.is_ep_out() && cfg.enable_feedback_ep) {
750 for (uint8_t i = 0; i < cfg.func_n_as_int; i++) {
751 audiod_function_t *audio = &_audiod_fct[i];
753 if (audio->ep_fb != 0) {
756 uint8_t
const hs_adjust =
757 (TUSB_SPEED_HIGH == tud_speed_get()) ? 3 : 0;
758 uint32_t
const interval =
759 1UL << (audio->feedback.frame_shift - hs_adjust);
760 if (0 == (frame_count & (interval - 1))) {
761 if (cfg.enable_feedback_interval_isr && p_cb)
762 p_cb->feedback_interval_isr(i, frame_count,
763 audio->feedback.frame_shift);
781 std::vector<CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
784 std::vector<OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
785 audio_ep_in_sw_buf_1;
787 std::vector<OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
788 audio_ep_out_sw_buf_1;
796 std::vector<CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
800 std::vector<CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t>
804 std::vector<uint8_t> alt_setting_1;
807 std::vector<uint8_t> descriptor;
811 osal_mutex_def_t ep_in_ff_mutex_wr_1;
814 osal_mutex_def_t ep_out_ff_mutex_rd_1;
821 uint8_t n_bytes_per_sample_tx;
822 uint8_t n_channels_tx;
823 uint8_t format_type_tx = AUDIO_FORMAT_TYPE_I;
857 uint16_t desc_length;
860 CFG_TUSB_MEM_ALIGN uint32_t
869 uint8_t compute_method;
876 uint32_t sample_freq;
887 uint32_t sample_rate_tx;
888 uint16_t packet_sz_tx[3];
889 uint8_t bclock_id_tx;
900 uint8_t *alt_setting;
910 CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6];
915 uint8_t *lin_buf_out;
922 std::vector<CFG_TUD_MEM_SECTION audiod_function_t> _audiod_fct;
927 for (uint8_t cnt = 0; cnt < cfg.func_n_as_int; cnt++) {
928 if (&_audiod_fct[cnt] == audio)
return cnt;
933 inline uint8_t tu_desc_subtype(
void const *desc) {
934 return ((uint8_t
const *)desc)[2];
937 bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio,
938 uint16_t n_bytes_received) {
940 uint8_t
const *dummy2;
941 uint8_t idx_audio_fct = 0;
944 idx_audio_fct = audiod_get_audio_fct_idx(audio);
945 TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio,
953 TU_VERIFY(p_cb->rx_done_pre_read_cb(rhport, n_bytes_received,
954 idx_audio_fct, audio->ep_out,
955 audio->alt_setting[idxItf]));
958 if (cfg.enable_linear_buffer_rx) {
960 TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out,
964 TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out,
969 TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff,
977 TU_VERIFY(p_cb->rx_done_post_read_cb(rhport, n_bytes_received,
978 idx_audio_fct, audio->ep_out,
979 audio->alt_setting[idxItf]));
995 bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) {
997 uint8_t
const *dummy2;
999 uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio);
1000 TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio,
1005 if (audio->alt_setting[idxItf] == 0)
return false;
1013 TU_VERIFY(p_cb->tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in,
1014 audio->alt_setting[idxItf]));
1017 uint16_t n_bytes_tx;
1022 if (cfg.enable_ep_in_flow_control) {
1025 n_bytes_tx = audiod_tx_packet_size(
1026 audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff),
1027 audio->ep_in_ff.depth, audio->ep_in_sz);
1029 n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff),
1033 if (cfg.enable_linear_buffer_tx) {
1034 tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx);
1036 usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx));
1039 TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff,
1047 TU_VERIFY(p_cb->tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct,
1049 audio->alt_setting[idxItf]));
1056 inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) {
1057 return usbd_edpt_xfer(rhport, audio->ep_fb,
1058 (uint8_t *)&audio->feedback.value, 4);
1061 bool audiod_set_interface(uint8_t rhport,
1062 tusb_control_request_t
const *p_request) {
1082 uint8_t
const itf = tu_u16_low(p_request->wIndex);
1083 uint8_t
const alt = tu_u16_low(p_request->wValue);
1085 TU_LOG2(
" Set itf: %u - alt: %u\r\n", itf, alt);
1088 uint8_t func_id, idxItf;
1089 uint8_t
const *p_desc;
1091 audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc));
1093 audiod_function_t *audio = &_audiod_fct[func_id];
1098 if (cfg.is_ep_in()) {
1099 if (audio->ep_in_as_intf_num == itf) {
1100 audio->ep_in_as_intf_num = 0;
1101 #ifndef TUP_DCD_EDPT_ISO_ALLOC
1102 usbd_edpt_close(rhport, audio->ep_in);
1106 tu_fifo_clear(&audio->ep_in_ff);
1109 if (p_cb) TU_VERIFY(p_cb->set_itf_close_EP_cb(rhport, p_request));
1113 if (cfg.enable_ep_in_flow_control) {
1114 audio->packet_sz_tx[0] = 0;
1115 audio->packet_sz_tx[1] = 0;
1116 audio->packet_sz_tx[2] = 0;
1121 if (cfg.is_ep_out()) {
1122 if (audio->ep_out_as_intf_num == itf) {
1123 audio->ep_out_as_intf_num = 0;
1124 #ifndef TUP_DCD_EDPT_ISO_ALLOC
1125 usbd_edpt_close(rhport, audio->ep_out);
1129 tu_fifo_clear(&audio->ep_out_ff);
1131 if (p_cb) TU_VERIFY(p_cb->set_itf_close_EP_cb(rhport, p_request));
1136 if (cfg.enable_feedback_ep) {
1137 #ifndef TUP_DCD_EDPT_ISO_ALLOC
1138 usbd_edpt_close(rhport, audio->ep_fb);
1141 tu_memclr(&audio->feedback,
sizeof(audio->feedback));
1147 audio->alt_setting[idxItf] = alt;
1152 uint8_t
const *p_desc_end =
1153 audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1158 while (p_desc_end - p_desc > 0) {
1160 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1161 ((tusb_desc_interface_t
const *)p_desc)->bInterfaceNumber == itf &&
1162 ((tusb_desc_interface_t
const *)p_desc)->bAlternateSetting == alt) {
1163 uint8_t
const *p_desc_parse_for_params = p_desc;
1166 uint8_t foundEPs = 0,
1167 nEps = ((tusb_desc_interface_t
const *)p_desc)->bNumEndpoints;
1170 while (foundEPs < nEps && (p_desc_end - p_desc > 0)) {
1171 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
1172 tusb_desc_endpoint_t
const *desc_ep =
1173 (tusb_desc_endpoint_t
const *)p_desc;
1174 #ifdef TUP_DCD_EDPT_ISO_ALLOC
1175 TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep));
1177 TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
1179 uint8_t
const ep_addr = desc_ep->bEndpointAddress;
1183 usbd_edpt_clear_stall(rhport, ep_addr);
1185 if (cfg.is_ep_in()) {
1186 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1187 desc_ep->bmAttributes.usage ==
1191 audio->ep_in = ep_addr;
1192 audio->ep_in_as_intf_num = itf;
1193 audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
1198 if (cfg.enable_ep_in_flow_control)
1199 audiod_parse_for_AS_params(audio, p_desc_parse_for_params,
1210 TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id]));
1214 if (cfg.is_ep_out()) {
1215 if (tu_edpt_dir(ep_addr) ==
1219 audio->ep_out = ep_addr;
1220 audio->ep_out_as_intf_num = itf;
1221 audio->ep_out_sz = tu_edpt_packet_size(desc_ep);
1224 if (cfg.enable_linear_buffer_rx) {
1226 usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out,
1231 usbd_edpt_xfer_fifo(rhport, audio->ep_out,
1232 &audio->ep_out_ff, audio->ep_out_sz),
1237 if (cfg.enable_feedback_ep) {
1238 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1239 desc_ep->bmAttributes.usage ==
1242 audio->ep_fb = ep_addr;
1243 audio->feedback.frame_shift = desc_ep->bInterval - 1;
1246 if (cfg.enable_feedback_interval_isr)
1247 usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO,
true);
1254 p_desc = tu_desc_next(p_desc);
1257 TU_VERIFY(foundEPs == nEps);
1260 if (p_cb) TU_VERIFY(p_cb->set_itf_cb(rhport, p_request));
1262 if (cfg.enable_feedback_ep) {
1267 p_cb->feedback_params_cb(func_id, alt, &fb_param);
1268 audio->feedback.compute_method = fb_param.method;
1272 uint32_t
const frame_div =
1273 (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000;
1274 audio->feedback.min_value = (fb_param.sample_freq / frame_div - 1)
1276 audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1)
1279 switch (fb_param.method) {
1280 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
1281 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1282 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1283 set_fb_params_freq(audio, fb_param.sample_freq,
1284 fb_param.frequency.mclk_freq);
1299 p_desc = tu_desc_next(p_desc);
1302 if (cfg.enable_feedback_ep) {
1304 bool disable =
true;
1305 for (uint8_t i = 0; i < cfg.func_n_as_int; i++) {
1306 if (_audiod_fct[i].ep_fb != 0) {
1311 if (disable) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO,
false);
1314 if (cfg.is_ep_in() && cfg.enable_ep_in_flow_control)
1315 audiod_calc_tx_packet_sz(audio);
1317 tud_control_status(rhport, p_request);
1324 bool audiod_control_complete(uint8_t rhport,
1325 tusb_control_request_t
const *p_request) {
1327 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
1328 p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
1331 switch (p_request->bmRequestType_bit.recipient) {
1332 case TUSB_REQ_RCPT_INTERFACE: {
1333 uint8_t itf = TU_U16_LOW(p_request->wIndex);
1334 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1336 if (entityID != 0) {
1339 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1342 return p_cb->set_req_entity_cb(rhport, p_request,
1343 _audiod_fct[func_id].ctrl_buf);
1345 TU_LOG2(
" No entity set request callback available!\r\n");
1353 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1356 return p_cb->set_req_itf_cb(rhport, p_request,
1357 _audiod_fct[func_id].ctrl_buf);
1359 TU_LOG2(
" No interface set request callback available!\r\n");
1366 case TUSB_REQ_RCPT_ENDPOINT: {
1367 uint8_t ep = TU_U16_LOW(p_request->wIndex);
1371 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1374 return p_cb->set_req_ep_cb(rhport, p_request,
1375 _audiod_fct[func_id].ctrl_buf);
1377 TU_LOG2(
" No EP set request callback available!\r\n");
1392 bool audiod_control_request(uint8_t rhport,
1393 tusb_control_request_t
const *p_request) {
1398 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
1399 switch (p_request->bRequest) {
1400 case TUSB_REQ_GET_INTERFACE:
1401 return audiod_get_interface(rhport, p_request);
1403 case TUSB_REQ_SET_INTERFACE:
1404 return audiod_set_interface(rhport, p_request);
1406 case TUSB_REQ_CLEAR_FEATURE:
1417 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
1418 uint8_t itf = TU_U16_LOW(p_request->wIndex);
1422 switch (p_request->bmRequestType_bit.recipient) {
1423 case TUSB_REQ_RCPT_INTERFACE: {
1424 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1427 if (entityID != 0) {
1430 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1435 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1437 return p_cb->get_req_entity_cb(rhport, p_request);
1439 TU_LOG2(
" No entity get request callback available!\r\n");
1446 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1451 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1453 return p_cb->set_itf_cb(rhport, p_request);
1455 TU_LOG2(
" No interface get request callback available!\r\n");
1462 case TUSB_REQ_RCPT_ENDPOINT: {
1463 uint8_t ep = TU_U16_LOW(p_request->wIndex);
1466 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1470 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1472 return p_cb->get_req_ep_cb(rhport, p_request);
1474 TU_LOG2(
" No EP get request callback available!\r\n");
1482 TU_LOG2(
" Unsupported recipient: %d\r\n",
1483 p_request->bmRequestType_bit.recipient);
1491 TU_VERIFY(tud_control_xfer(rhport, p_request,
1492 _audiod_fct[func_id].ctrl_buf,
1493 _audiod_fct[func_id].ctrl_buf_sz));
1502 bool audiod_get_interface(uint8_t rhport,
1503 tusb_control_request_t
const *p_request) {
1504 uint8_t
const itf = tu_u16_low(p_request->wIndex);
1507 uint8_t func_id, idxItf;
1508 uint8_t
const *dummy;
1511 audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy));
1512 TU_VERIFY(tud_control_xfer(rhport, p_request,
1513 &_audiod_fct[func_id].alt_setting[idxItf], 1));
1515 TU_LOG2(
" Get itf: %u - current alt: %u\r\n", itf,
1516 _audiod_fct[func_id].alt_setting[idxItf]);
1523 bool audiod_control_completeX(uint8_t rhport,
1524 tusb_control_request_t
const *p_request) {
1526 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
1527 p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
1530 switch (p_request->bmRequestType_bit.recipient) {
1531 case TUSB_REQ_RCPT_INTERFACE: {
1532 uint8_t itf = TU_U16_LOW(p_request->wIndex);
1533 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1535 if (entityID != 0) {
1538 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1541 return p_cb->set_req_entity_cb(rhport, p_request,
1542 _audiod_fct[func_id].ctrl_buf);
1544 TU_LOG2(
" No entity set request callback available!\r\n");
1552 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1555 return p_cb->set_req_itf_cb(rhport, p_request,
1556 _audiod_fct[func_id].ctrl_buf);
1558 TU_LOG2(
" No interface set request callback available!\r\n");
1565 case TUSB_REQ_RCPT_ENDPOINT: {
1566 uint8_t ep = TU_U16_LOW(p_request->wIndex);
1570 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1573 return p_cb->set_req_ep_cb(rhport, p_request,
1574 _audiod_fct[func_id].ctrl_buf);
1576 TU_LOG2(
" No EP set request callback available!\r\n");
1590 bool set_fb_params_freq(audiod_function_t *audio, uint32_t sample_freq,
1591 uint32_t mclk_freq) {
1599 uint32_t
const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13;
1600 uint32_t
const n_frame = (1UL << audio->feedback.frame_shift);
1602 if ((((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame) {
1603 TU_LOG1(
" UAC2 feedback interval too small\r\n");
1609 if ((mclk_freq % sample_freq) == 0 &&
1610 tu_is_power_of_two(mclk_freq / sample_freq)) {
1611 audio->feedback.compute_method =
1612 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2;
1613 audio->feedback.compute.power_of_2 =
1614 16 - audio->feedback.frame_shift - tu_log2(mclk_freq / sample_freq);
1615 }
else if (audio->feedback.compute_method ==
1616 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) {
1617 audio->feedback.compute.float_const =
1618 (float)sample_freq / mclk_freq *
1619 (1UL << (16 - audio->feedback.frame_shift));
1621 audio->feedback.compute.fixed.sample_freq = sample_freq;
1622 audio->feedback.compute.fixed.mclk_freq = mclk_freq;
1628 uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) {
1629 audiod_function_t *audio = &_audiod_fct[func_id];
1632 switch (audio->feedback.compute_method) {
1633 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1634 feedback = (cycles << audio->feedback.compute.power_of_2);
1637 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1639 (uint32_t)((
float)cycles * audio->feedback.compute.float_const);
1642 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: {
1644 (((uint64_t)cycles) * audio->feedback.compute.fixed.sample_freq)
1645 << (16 - audio->feedback.frame_shift);
1646 feedback = (uint32_t)(fb64 / audio->feedback.compute.fixed.mclk_freq);
1659 if (feedback > audio->feedback.max_value)
1660 feedback = audio->feedback.max_value;
1661 if (feedback < audio->feedback.min_value)
1662 feedback = audio->feedback.min_value;
1664 tud_audio_n_fb_set(func_id, feedback);
1676 bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t *audio,
1678 uint8_t
const **pp_desc_int) {
1679 if (audio->p_desc) {
1681 uint8_t
const *p_desc_end =
1682 audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1685 uint8_t
const *p_desc = tu_desc_next(audio->p_desc);
1686 p_desc += ((audio_desc_cs_ac_interface_t
const *)p_desc)->wTotalLength;
1691 while (p_desc_end - p_desc > 0) {
1694 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1695 ((tusb_desc_interface_t
const *)p_desc)->bAlternateSetting == 0) {
1696 if (((tusb_desc_interface_t
const *)p_desc)->bInterfaceNumber ==
1699 *pp_desc_int = p_desc;
1705 p_desc = tu_desc_next(p_desc);
1718 bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id,
1720 uint8_t
const **pp_desc_int) {
1723 for (i = 0; i < cfg.func_n_as_int; i++) {
1724 if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf,
1736 bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID,
1739 for (i = 0; i < cfg.func_n_as_int; i++) {
1742 if (_audiod_fct[i].p_desc &&
1743 ((tusb_desc_interface_t
const *)_audiod_fct[i].p_desc)
1744 ->bInterfaceNumber == itf) {
1747 uint8_t
const *p_desc =
1748 tu_desc_next(_audiod_fct[i].p_desc);
1749 uint8_t
const *p_desc_end =
1750 ((audio_desc_cs_ac_interface_t
const *)p_desc)->wTotalLength +
1752 p_desc = tu_desc_next(p_desc);
1756 while (p_desc_end - p_desc > 0) {
1757 if (p_desc[3] == entityID)
1762 p_desc = tu_desc_next(p_desc);
1769 bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) {
1771 for (i = 0; i < cfg.func_n_as_int; i++) {
1772 if (_audiod_fct[i].p_desc) {
1774 uint8_t
const *p_desc = _audiod_fct[i].p_desc;
1775 uint8_t
const *p_desc_end = _audiod_fct[i].p_desc +
1776 _audiod_fct[i].desc_length -
1777 TUD_AUDIO_DESC_IAD_LEN;
1780 while (p_desc_end - p_desc > 0) {
1781 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1782 ((tusb_desc_interface_t
const *)_audiod_fct[i].p_desc)
1783 ->bInterfaceNumber == itf) {
1787 p_desc = tu_desc_next(p_desc);
1794 bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) {
1796 for (i = 0; i < cfg.func_n_as_int; i++) {
1797 if (_audiod_fct[i].p_desc) {
1799 uint8_t
const *p_desc_end =
1800 _audiod_fct[i].p_desc + _audiod_fct[i].desc_length;
1803 uint8_t
const *p_desc = tu_desc_next(_audiod_fct[i].p_desc);
1804 p_desc += ((audio_desc_cs_ac_interface_t
const *)p_desc)->wTotalLength;
1808 while (p_desc_end - p_desc > 0) {
1809 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT &&
1810 ((tusb_desc_endpoint_t
const *)p_desc)->bEndpointAddress == ep) {
1814 p_desc = tu_desc_next(p_desc);
1826 void audiod_parse_for_AS_params(audiod_function_t *audio,
1827 uint8_t
const *p_desc,
1828 uint8_t
const *p_desc_end,
1829 uint8_t
const as_itf) {
1830 if (cfg.is_ep_in() && cfg.is_ep_out()) {
1831 if (as_itf != audio->ep_in_as_intf_num &&
1832 as_itf != audio->ep_out_as_intf_num)
1836 if (cfg.is_ep_in() && !cfg.is_ep_out()) {
1837 if (as_itf != audio->ep_in_as_intf_num)
return;
1839 if (!cfg.is_ep_in() && cfg.is_ep_out()) {
1840 if (as_itf != audio->ep_out_as_intf_num)
return;
1843 p_desc = tu_desc_next(p_desc);
1847 while (p_desc_end - p_desc > 0) {
1850 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE)
break;
1854 if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
1855 tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) {
1856 if (cfg.is_ep_in()) {
1857 if (as_itf == audio->ep_in_as_intf_num) {
1858 audio->n_channels_tx =
1859 ((audio_desc_cs_as_interface_t
const *)p_desc)->bNrChannels;
1860 audio->format_type_tx =
1861 (audio_format_type_t)(((audio_desc_cs_as_interface_t
const *)
1868 if (cfg.enable_ep_in_flow_control) {
1869 if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
1870 tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE &&
1871 ((audio_desc_type_I_format_t
const *)p_desc)->bFormatType ==
1872 AUDIO_FORMAT_TYPE_I) {
1873 if (cfg.is_ep_in() && cfg.is_ep_out()) {
1874 if (as_itf != audio->ep_in_as_intf_num &&
1875 as_itf != audio->ep_out_as_intf_num)
1879 if (cfg.is_ep_in() && !cfg.is_ep_out()) {
1880 if (as_itf != audio->ep_in_as_intf_num)
break;
1882 if (!cfg.is_ep_in() && cfg.is_ep_out()) {
1883 if (as_itf != audio->ep_out_as_intf_num)
break;
1886 if (cfg.is_ep_in()) {
1887 if (as_itf == audio->ep_in_as_intf_num) {
1888 audio->n_bytes_per_sample_tx =
1889 ((audio_desc_type_I_format_t
const *)p_desc)->bSubslotSize;
1897 p_desc = tu_desc_next(p_desc);
1901 bool audiod_calc_tx_packet_sz(audiod_function_t *audio) {
1902 TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
1903 TU_VERIFY(audio->n_channels_tx);
1904 TU_VERIFY(audio->n_bytes_per_sample_tx);
1905 TU_VERIFY(audio->interval_tx);
1906 TU_VERIFY(audio->sample_rate_tx);
1908 const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL)
1909 ? audio->interval_tx
1910 : 1 << (audio->interval_tx - 1);
1912 const uint16_t sample_normimal =
1913 (uint16_t)(audio->sample_rate_tx * interval /
1914 ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1915 const uint16_t sample_reminder =
1916 (uint16_t)(audio->sample_rate_tx * interval %
1917 ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1919 const uint16_t packet_sz_tx_min =
1920 (uint16_t)((sample_normimal - 1) * audio->n_channels_tx *
1921 audio->n_bytes_per_sample_tx);
1922 const uint16_t packet_sz_tx_norm =
1923 (uint16_t)(sample_normimal * audio->n_channels_tx *
1924 audio->n_bytes_per_sample_tx);
1925 const uint16_t packet_sz_tx_max =
1926 (uint16_t)((sample_normimal + 1) * audio->n_channels_tx *
1927 audio->n_bytes_per_sample_tx);
1930 TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
1933 if (sample_reminder) {
1936 audio->packet_sz_tx[0] = packet_sz_tx_norm;
1937 audio->packet_sz_tx[1] = packet_sz_tx_norm;
1938 audio->packet_sz_tx[2] = packet_sz_tx_max;
1942 audio->packet_sz_tx[0] = packet_sz_tx_min;
1943 audio->packet_sz_tx[1] = packet_sz_tx_norm;
1944 audio->packet_sz_tx[2] = packet_sz_tx_max;
1950 uint16_t audiod_tx_packet_size(
const uint16_t *norminal_size,
1951 uint16_t data_count, uint16_t fifo_depth,
1952 uint16_t max_depth) {
1954 if (norminal_size[1] && norminal_size[1] <= fifo_depth * 4) {
1956 int ctrl_blackout = 0;
1957 uint16_t packet_size;
1958 uint16_t slot_size = norminal_size[2] - norminal_size[1];
1959 if (data_count < norminal_size[0]) {
1963 }
else if (data_count < fifo_depth / 2 - slot_size && !ctrl_blackout) {
1964 packet_size = norminal_size[0];
1966 }
else if (data_count > fifo_depth / 2 + slot_size && !ctrl_blackout) {
1967 packet_size = norminal_size[2];
1968 if (norminal_size[0] == norminal_size[1]) {
1976 packet_size = norminal_size[1];
1977 if (ctrl_blackout) {
1982 return tu_min16(packet_size, max_depth);
1984 return tu_min16(data_count, max_depth);
Definition: USBDeviceAudioAPI.h:103
Configuration for TinyUSB Audio.
Definition: USBDeviceAudioAPI.h:43
Definition: USBDeviceAudioAPI.h:177
uint16_t tud_audio_n_write(uint8_t func_id, const void *data, uint16_t len)
Write data to EP in buffer.
Definition: USBDeviceAudioAPI.h:231
Definition: USBDeviceAudio.h:104
Definition: USBDeviceAudioAPI.h:859
Definition: USBDeviceAudioAPI.h:817
Definition: USBDeviceAudioAPI.h:28