49 enum audio_format_type_t {
52 AUDIO_FORMAT_TYPE_III,
61 enum audio_feedback_method_t {
62 AUDIO_FEEDBACK_METHOD_DISABLED,
63 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
64 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
65 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
66 AUDIO_FEEDBACK_METHOD_FIFO_COUNT
75 struct audiod_function_t {
77 uint8_t
const* p_desc;
95 uint8_t compute_method;
96 bool format_correction;
101 uint32_t sample_freq;
106 uint32_t fifo_lvl_avg;
107 uint16_t fifo_lvl_thr;
108 uint16_t rate_const[2];
112 uint32_t sample_rate_tx;
113 uint16_t packet_sz_tx[3];
114 uint8_t bclock_id_tx;
116 audio_format_type_t format_type_tx;
117 uint8_t n_channels_tx;
118 uint8_t n_bytes_per_sample_tx;
123 std::vector<uint8_t> ctrl_buf;
124 std::vector<uint8_t> alt_setting;
125 std::vector<uint8_t> lin_buf_out;
126 std::vector<uint8_t> lin_buf_in;
127 std::vector<uint32_t> fb_buf;
128 std::vector<uint8_t> ep_in_sw_buf;
129 std::vector<uint8_t> ep_out_sw_buf;
138 struct audio_feedback_params_t {
140 uint32_t sample_freq;
156 cfg.enable_ep_out =
true;
157 cfg.enable_ep_in =
false;
160 cfg.enable_ep_out =
false;
161 cfg.enable_ep_in =
true;
164 cfg.enable_ep_out =
true;
165 cfg.enable_ep_in =
true;
195 return config_.enable_ep_in_flow_control;
214 uint16_t* out_length) {
247 return descr_builder.buildDescriptor(itf, alt, out_length);
251 bool mounted()
const {
return tud_mounted(); }
263 if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
264 request->bRequest == TUSB_REQ_GET_DESCRIPTOR) {
267 uint8_t
const itf = tu_u16_low(request->wIndex);
268 uint8_t
const alt = tu_u16_low(request->wValue);
271 if (desc && buffer && length >= desc_len) {
272 std::memcpy(buffer, desc, desc_len);
289 uint8_t audio_data[48] = {0};
290 uint16_t bytes_written = 48;
292 bytes_written = tx_callback_(audio_data,
sizeof(audio_data));
293 write(audio_data, bytes_written);
298 uint16_t n = read(buf,
sizeof(buf));
299 if (n > 0 && rx_callback_) rx_callback_(buf, n);
325 tusb_control_request_t
const*)>
327 get_req_itf_cb_ = cb;
336 tusb_control_request_t
const*)>
338 get_req_entity_cb_ = cb;
346 tusb_control_request_t
const*)>
372 std::function<
bool(
USBAudioDevice*, uint8_t, audiod_function_t*)> cb) {
381 audiod_function_t*, uint16_t)>
400 tusb_control_request_t
const*)>
402 tud_audio_set_itf_cb_ = cb;
411 tusb_control_request_t
const*, uint8_t*)>
413 tud_audio_set_req_entity_cb_ = cb;
422 tusb_control_request_t
const*, uint8_t*)>
424 tud_audio_set_req_itf_cb_ = cb;
433 tusb_control_request_t
const*, uint8_t*)>
435 tud_audio_set_req_ep_cb_ = cb;
443 tusb_control_request_t
const*)>
445 tud_audio_set_itf_close_EP_cb_ = cb;
453 std::function<
bool(
USBAudioDevice*, uint8_t, audiod_function_t*)> cb) {
454 audiod_tx_done_cb_ = cb;
463 audio_feedback_params_t*)>
465 tud_audio_feedback_params_cb_ = cb;
474 tud_audio_feedback_format_correction_cb_ = cb;
492 static usbd_class_driver_t driver;
493 driver.name =
"Audio";
495 driver.deinit = [](void) {
498 driver.reset = [](uint8_t rhport) {
501 driver.open = [](uint8_t rhport, tusb_desc_interface_t
const* itf_desc,
505 driver.control_xfer_cb = [](uint8_t rhport, uint8_t stage,
506 tusb_control_request_t
const* request) {
510 driver.xfer_cb = [](uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
511 uint32_t xferred_bytes) {
515 driver.sof = [](uint8_t rhport, uint32_t frame_count) {
526 std::function<void(
const uint8_t*, uint16_t)> rx_callback_;
527 std::function<uint16_t(
const uint8_t*, uint16_t)> tx_callback_;
528 std::function<void(USBAudioDevice*, uint8_t rhport)> int_done_cb_;
529 std::function<bool(USBAudioDevice*, uint8_t rhport, audiod_function_t*)>
531 std::function<bool(USBAudioDevice*, uint8_t rhport, audiod_function_t*,
532 uint16_t xferred_bytes)>
535 std::function<bool(USBAudioDevice*, uint8_t rhport,
536 tusb_control_request_t
const*)>
539 std::function<bool(USBAudioDevice*, uint8_t rhport,
540 tusb_control_request_t
const*)>
543 std::function<bool(USBAudioDevice*, uint8_t rhport,
544 tusb_control_request_t
const*)>
548 std::function<void(USBAudioDevice*, uint8_t func_id)> fb_done_cb_;
549 std::function<bool(USBAudioDevice*, uint8_t func_id)> req_entity_cb_;
550 std::function<bool(USBAudioDevice*, uint8_t rhport,
551 tusb_control_request_t
const* p_request)>
552 tud_audio_set_itf_cb_;
553 std::function<bool(USBAudioDevice*, uint8_t rhport,
554 tusb_control_request_t
const* p_request, uint8_t* pBuff)>
555 tud_audio_set_req_entity_cb_;
557 std::function<bool(USBAudioDevice*, uint8_t rhport,
558 tusb_control_request_t
const* p_request, uint8_t* pBuff)>
559 tud_audio_set_req_itf_cb_;
561 std::function<bool(USBAudioDevice*, uint8_t rhport,
562 tusb_control_request_t
const* p_request, uint8_t* pBuff)>
563 tud_audio_set_req_ep_cb_;
565 std::function<bool(USBAudioDevice*, uint8_t rhport,
566 tusb_control_request_t
const* p_request)>
567 tud_audio_set_itf_close_EP_cb_;
569 std::function<bool(USBAudioDevice*, uint8_t rhport, audiod_function_t* audio)>
572 std::function<void(USBAudioDevice*, uint8_t func_id, uint8_t alt_itf,
573 audio_feedback_params_t* feedback_param)>
574 tud_audio_feedback_params_cb_;
576 std::function<bool(USBAudioDevice*, uint8_t func_id)>
577 tud_audio_feedback_format_correction_cb_;
581 std::vector<uint16_t> ep_out_sw_buf_sz_;
584 std::vector<uint16_t> ep_in_sw_buf_sz_;
586 std::vector<uint16_t> desc_len_;
588 std::vector<uint16_t> ctrl_buf_sz_;
590 std::vector<audiod_function_t> audiod_fct_;
591 std::vector<osal_mutex_def_t> ep_in_ff_mutex_wr_;
592 std::vector<osal_mutex_def_t> ep_out_ff_mutex_rd_;
594 USBAudioDevice() =
default;
597 uint16_t getCtrlBufSz(uint8_t fn)
const {
598 return (fn < ctrl_buf_sz_.size()) ? ctrl_buf_sz_[fn] : 64;
602 uint16_t getEpOutSwBufSz(uint8_t fn)
const {
603 return (fn < ep_out_sw_buf_sz_.size()) ? ep_out_sw_buf_sz_[fn] : 0;
607 uint16_t getEpInSwBufSz(uint8_t fn)
const {
608 return (fn < ep_in_sw_buf_sz_.size()) ? ep_in_sw_buf_sz_[fn] : 0;
612 uint16_t getDescLen(uint8_t fn)
const {
613 return (fn < desc_len_.size()) ? desc_len_[fn] : 0;
617 bool getUseLinearBufferRx()
const {
return config_.use_linear_buffer_rx; }
619 bool getUseLinearBufferTx()
const {
return config_.use_linear_buffer_tx; }
623 static constexpr size_t getResetSize() {
624 return offsetof(audiod_function_t, ctrl_buf_sz) +
625 sizeof(((audiod_function_t*)0)->ctrl_buf_sz);
630 void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_count,
631 uint8_t frame_shift) {
636 uint16_t write(
const void* data, uint16_t len) {
637 uint16_t written = tud_audio_n_write(config_.ep_in, data, len);
643 uint16_t read(
void* buffer, uint16_t bufsize) {
644 return tud_audio_n_read(config_.ep_out, buffer, bufsize);
648 void audiod_init(
void) {
654 audiod_function_t* audio = &audiod_fct_[i];
656 int size = getCtrlBufSz(i);
657 audio->ctrl_buf.resize(size);
658 audio->ctrl_buf_sz = size;
660 audio->alt_setting.resize(config_.audio_functions_count());
663 audio->ep_in_sw_buf.resize(getEpInSwBufSz(i));
665 tu_fifo_config(&audio->ep_in_ff,
666 audio->ep_in_sw_buf.data(),
667 getEpInSwBufSz(i), 1,
true);
669 tu_fifo_config_mutex(&audio->ep_in_ff,
670 osal_mutex_create(&ep_in_ff_mutex_wr_[i]), NULL);
674 if (getUseLinearBufferTx()) {
675 audio->lin_buf_in.resize(config_.lin_buf_in_size_per_func);
679 audio->ep_out_sw_buf.resize(getEpOutSwBufSz(i));
680 tu_fifo_config(&audio->ep_out_ff, audio->ep_out_sw_buf.data(),
681 getEpOutSwBufSz(i), 1,
true);
683 tu_fifo_config_mutex(&audio->ep_out_ff, NULL,
684 osal_mutex_create(&ep_out_ff_mutex_rd_[i]));
688 if (getUseLinearBufferRx()) {
689 audio->lin_buf_out.resize(config_.lin_buf_in_size_per_func);
692 audio->fb_buf.resize(getEpOutSwBufSz(i));
708 bool audiod_deinit(
void) {
712 void audiod_reset(uint8_t rhport) {
715 audiod_function_t* audio = &audiod_fct_[i];
716 memset(audio, 0, getResetSize());
718 tu_fifo_clear(&audio->ep_in_ff);
721 tu_fifo_clear(&audio->ep_out_ff);
726 uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t
const* itf_desc,
729 TU_VERIFY(TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass &&
730 AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass);
731 TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2);
732 TU_ASSERT(itf_desc->bNumEndpoints <= 1);
733 if (itf_desc->bNumEndpoints == 1) {
736 TU_VERIFY(itf_desc->bAlternateSetting == 0);
739 if (!audiod_fct_[i].p_desc) {
740 audiod_fct_[i].p_desc = (uint8_t
const*)itf_desc;
741 audiod_fct_[i].rhport = rhport;
742 audiod_fct_[i].desc_length = getDescLen(i);
744 uint8_t ep_in = 0, ep_out = 0, ep_fb = 0;
745 uint16_t ep_in_size = 0, ep_out_size = 0;
746 uint8_t
const* p_desc = audiod_fct_[i].p_desc;
747 uint8_t
const* p_desc_end =
748 p_desc + audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
749 while (p_desc_end - p_desc > 0) {
750 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
751 tusb_desc_endpoint_t
const* desc_ep =
752 (tusb_desc_endpoint_t
const*)p_desc;
753 if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
755 ep_fb = desc_ep->bEndpointAddress;
757 if (desc_ep->bmAttributes.usage == 0) {
759 tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
760 ep_in = desc_ep->bEndpointAddress;
762 TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
764 tu_edpt_dir(desc_ep->bEndpointAddress) ==
766 ep_out = desc_ep->bEndpointAddress;
768 TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
773 p_desc = tu_desc_next(p_desc);
776 usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
779 usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
782 usbd_edpt_iso_alloc(rhport, ep_fb, 4);
786 uint8_t
const* p_desc = audiod_fct_[i].p_desc;
787 uint8_t
const* p_desc_end =
788 p_desc + audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
789 while (p_desc_end - p_desc > 0) {
790 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
791 tusb_desc_endpoint_t
const* desc_ep =
792 (tusb_desc_endpoint_t
const*)p_desc;
793 if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS &&
794 desc_ep->bmAttributes.usage == 0 &&
795 tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
796 audiod_fct_[i].interval_tx = desc_ep->bInterval;
798 }
else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
799 tu_desc_subtype(p_desc) ==
800 AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
801 if (tu_unaligned_read16(p_desc + 4) ==
802 AUDIO_TERM_TYPE_USB_STREAMING) {
803 audiod_fct_[i].bclock_id_tx = p_desc[8];
806 p_desc = tu_desc_next(p_desc);
810 uint8_t
const* p_desc = audiod_fct_[i].p_desc;
811 uint8_t
const* p_desc_end =
812 p_desc + audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
813 while (p_desc_end - p_desc > 0) {
814 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
815 tusb_desc_endpoint_t
const* desc_ep =
816 (tusb_desc_endpoint_t
const*)p_desc;
817 uint8_t
const ep_addr = desc_ep->bEndpointAddress;
818 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
819 desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) {
820 audiod_fct_[i].ep_int = ep_addr;
821 TU_ASSERT(usbd_edpt_open(audiod_fct_[i].rhport, desc_ep));
824 p_desc = tu_desc_next(p_desc);
827 audiod_fct_[i].mounted =
true;
832 uint16_t drv_len = audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
836 bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage,
837 tusb_control_request_t
const* request) {
838 if (stage == CONTROL_STAGE_SETUP) {
839 return audiod_control_request(rhport, request);
840 }
else if (stage == CONTROL_STAGE_DATA) {
841 return audiod_control_complete(rhport, request);
847 bool audiod_control_complete(uint8_t rhport,
848 tusb_control_request_t
const* p_request) {
850 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
851 p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
854 switch (p_request->bmRequestType_bit.recipient) {
855 case TUSB_REQ_RCPT_INTERFACE: {
856 uint8_t itf = TU_U16_LOW(p_request->wIndex);
857 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
861 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
864 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
865 if (audiod_fct_[func_id].bclock_id_tx == entityID &&
866 ctrlSel == AUDIO_CS_CTRL_SAM_FREQ &&
867 p_request->bRequest == AUDIO_CS_REQ_CUR) {
868 audiod_fct_[func_id].sample_rate_tx =
869 tu_unaligned_read32(audiod_fct_[func_id].ctrl_buf.data());
874 if (tud_audio_set_req_entity_cb_) {
875 return tud_audio_set_req_entity_cb_(
876 this, rhport, p_request,
877 audiod_fct_[func_id].ctrl_buf.data());
882 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
885 if (tud_audio_set_req_itf_cb_) {
886 return tud_audio_set_req_itf_cb_(
887 this, rhport, p_request,
888 audiod_fct_[func_id].ctrl_buf.data());
893 case TUSB_REQ_RCPT_ENDPOINT: {
894 uint8_t ep = TU_U16_LOW(p_request->wIndex);
897 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
900 if (tud_audio_set_req_ep_cb_) {
901 return tud_audio_set_req_ep_cb_(
902 this, rhport, p_request, audiod_fct_[func_id].ctrl_buf.data());
914 bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
915 uint32_t xferred_bytes) {
918 for (uint8_t func_id = 0; func_id <
getAudioCount(); func_id++) {
919 audiod_function_t* audio = &audiod_fct_[func_id];
921 if (int_done_cb_) int_done_cb_(
this, rhport);
925 audio->alt_setting.size() != 0) {
926 if (tx_done_cb_ && tx_done_cb_(
this, rhport, audio))
return true;
931 rx_done_cb_(
this, rhport, audio, (uint16_t)xferred_bytes))
937 fb_done_cb_(
this, func_id);
939 if (usbd_edpt_claim(rhport, audio->ep_fb)) {
940 return audiod_fb_send(audio);
947 TU_ATTR_FAST_FUNC
void audiod_sof_isr(uint8_t rhport, uint32_t frame_count) {
952 audiod_function_t* audio = &audiod_fct_[i];
953 if (audio->ep_fb != 0) {
954 uint8_t
const hs_adjust =
955 (TUSB_SPEED_HIGH == tud_speed_get()) ? 3 : 0;
956 uint32_t
const interval =
957 1UL << (audio->feedback.frame_shift - hs_adjust);
958 if (0 == (frame_count & (interval - 1))) {
959 tud_audio_feedback_interval_isr(i, frame_count,
960 audio->feedback.frame_shift);
967 bool audiod_control_request(uint8_t rhport,
968 tusb_control_request_t
const* p_request) {
973 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
974 switch (p_request->bRequest) {
975 case TUSB_REQ_GET_INTERFACE:
976 return audiod_get_interface(rhport, p_request);
978 case TUSB_REQ_SET_INTERFACE:
979 return audiod_set_interface(rhport, p_request);
981 case TUSB_REQ_CLEAR_FEATURE:
992 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
993 uint8_t itf = TU_U16_LOW(p_request->wIndex);
997 switch (p_request->bmRequestType_bit.recipient) {
998 case TUSB_REQ_RCPT_INTERFACE: {
999 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
1002 if (entityID != 0) {
1005 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
1009 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN &&
1011 return req_entity_cb_(
this, func_id);
1016 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
1020 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1022 if (get_req_itf_cb_) {
1023 return get_req_itf_cb_(
this, rhport, p_request);
1030 case TUSB_REQ_RCPT_ENDPOINT: {
1031 uint8_t ep = TU_U16_LOW(p_request->wIndex);
1034 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
1038 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
1040 if (get_req_ep_cb_) {
1041 return get_req_ep_cb_(
this, rhport, p_request);
1049 TU_LOG2(
" Unsupported recipient: %d\r\n",
1050 p_request->bmRequestType_bit.recipient);
1058 TU_VERIFY(tud_control_xfer(rhport, p_request,
1059 audiod_fct_[func_id].ctrl_buf.data(),
1060 audiod_fct_[func_id].ctrl_buf_sz));
1070 bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID,
1076 if (audiod_fct_[i].p_desc &&
1077 ((tusb_desc_interface_t
const*)audiod_fct_[i].p_desc)
1078 ->bInterfaceNumber == itf) {
1081 uint8_t
const* p_desc =
1082 tu_desc_next(audiod_fct_[i].p_desc);
1083 uint8_t
const* p_desc_end =
1084 ((audio_desc_cs_ac_interface_t
const*)p_desc)->wTotalLength +
1086 p_desc = tu_desc_next(p_desc);
1090 while (p_desc_end - p_desc > 0) {
1091 if (p_desc[3] == entityID)
1096 p_desc = tu_desc_next(p_desc);
1103 bool audiod_verify_ep_exists(uint8_t ep, uint8_t* func_id) {
1106 if (audiod_fct_[i].p_desc) {
1108 uint8_t
const* p_desc_end =
1109 audiod_fct_[i].p_desc + audiod_fct_[i].desc_length;
1112 uint8_t
const* p_desc = tu_desc_next(audiod_fct_[i].p_desc);
1113 p_desc += ((audio_desc_cs_ac_interface_t
const*)p_desc)->wTotalLength;
1117 while (p_desc_end - p_desc > 0) {
1118 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT &&
1119 ((tusb_desc_endpoint_t
const*)p_desc)->bEndpointAddress == ep) {
1123 p_desc = tu_desc_next(p_desc);
1130 bool audiod_verify_itf_exists(uint8_t itf, uint8_t* func_id) {
1133 if (audiod_fct_[i].p_desc) {
1135 uint8_t
const* p_desc = audiod_fct_[i].p_desc;
1136 uint8_t
const* p_desc_end = audiod_fct_[i].p_desc +
1137 audiod_fct_[i].desc_length -
1138 TUD_AUDIO_DESC_IAD_LEN;
1141 while (p_desc_end - p_desc > 0) {
1142 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1143 ((tusb_desc_interface_t
const*)audiod_fct_[i].p_desc)
1144 ->bInterfaceNumber == itf) {
1148 p_desc = tu_desc_next(p_desc);
1155 void audiod_parse_flow_control_params(audiod_function_t* audio,
1156 uint8_t
const* p_desc) {
1157 p_desc = tu_desc_next(p_desc);
1162 if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
1163 tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) {
1164 audio->n_channels_tx =
1165 ((audio_desc_cs_as_interface_t
const*)p_desc)->bNrChannels;
1166 audio->format_type_tx =
1167 (audio_format_type_t)(((audio_desc_cs_as_interface_t
const*)p_desc)
1170 p_desc = tu_desc_next(p_desc);
1171 if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
1172 tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE &&
1173 ((audio_desc_type_I_format_t
const*)p_desc)->bFormatType ==
1174 AUDIO_FORMAT_TYPE_I) {
1175 audio->n_bytes_per_sample_tx =
1176 ((audio_desc_type_I_format_t
const*)p_desc)->bSubslotSize;
1188 bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t* audio,
1190 uint8_t
const** pp_desc_int) {
1191 if (audio->p_desc) {
1193 uint8_t
const* p_desc_end =
1194 audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1197 uint8_t
const* p_desc = tu_desc_next(audio->p_desc);
1198 p_desc += ((audio_desc_cs_ac_interface_t
const*)p_desc)->wTotalLength;
1203 while (p_desc_end - p_desc > 0) {
1206 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1207 ((tusb_desc_interface_t
const*)p_desc)->bAlternateSetting == 0) {
1208 if (((tusb_desc_interface_t
const*)p_desc)->bInterfaceNumber == itf) {
1210 *pp_desc_int = p_desc;
1216 p_desc = tu_desc_next(p_desc);
1228 bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t* func_id,
1230 uint8_t
const** pp_desc_int) {
1234 if (audiod_get_AS_interface_index(itf, &audiod_fct_[i], idxItf,
1244 bool audiod_get_interface(uint8_t rhport,
1245 tusb_control_request_t
const* p_request) {
1246 uint8_t
const itf = tu_u16_low(p_request->wIndex);
1249 uint8_t func_id, idxItf;
1250 uint8_t
const* dummy;
1253 audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy));
1254 TU_VERIFY(tud_control_xfer(rhport, p_request,
1255 &audiod_fct_[func_id].alt_setting[idxItf], 1));
1257 TU_LOG2(
" Get itf: %u - current alt: %u\r\n", itf,
1258 audiod_fct_[func_id].alt_setting[idxItf]);
1263 bool audiod_fb_send(audiod_function_t* audio) {
1264 bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) &&
1265 audio->feedback.format_correction;
1267 if (apply_correction) {
1268 uint8_t* fb = (uint8_t*)audio->fb_buf.data();
1271 *(fb++) = (audio->feedback.value >> 2) & 0xFF;
1272 *(fb++) = (audio->feedback.value >> 10) & 0xFF;
1273 *(fb++) = (audio->feedback.value >> 18) & 0xFF;
1276 audio->fb_buf[0] = audio->feedback.value;
1293 return usbd_edpt_xfer(audio->rhport, audio->ep_fb,
1294 (uint8_t*)audio->fb_buf.data(),
1295 apply_correction ? 3 : 4);
1298 bool audiod_set_interface(uint8_t rhport,
1299 tusb_control_request_t
const* p_request) {
1319 uint8_t
const itf = tu_u16_low(p_request->wIndex);
1320 uint8_t
const alt = tu_u16_low(p_request->wValue);
1322 TU_LOG2(
" Set itf: %u - alt: %u\r\n", itf, alt);
1325 uint8_t func_id, idxItf;
1326 uint8_t
const* p_desc;
1328 audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc));
1330 audiod_function_t* audio = &audiod_fct_[func_id];
1336 if (audio->ep_in_as_intf_num == itf) {
1337 audio->ep_in_as_intf_num = 0;
1338#ifndef TUP_DCD_EDPT_ISO_ALLOC
1339 usbd_edpt_close(rhport, audio->ep_in);
1343 tu_fifo_clear(&audio->ep_in_ff);
1346 if (tud_audio_set_itf_close_EP_cb_) {
1347 TU_VERIFY(tud_audio_set_itf_close_EP_cb_(
this, rhport, p_request));
1353 audio->packet_sz_tx[0] = 0;
1354 audio->packet_sz_tx[1] = 0;
1355 audio->packet_sz_tx[2] = 0;
1361 if (audio->ep_out_as_intf_num == itf) {
1362 audio->ep_out_as_intf_num = 0;
1363#ifndef TUP_DCD_EDPT_ISO_ALLOC
1364 usbd_edpt_close(rhport, audio->ep_out);
1368 tu_fifo_clear(&audio->ep_out_ff);
1371 if (tud_audio_set_itf_close_EP_cb_) {
1372 TU_VERIFY(tud_audio_set_itf_close_EP_cb_(
this, rhport, p_request));
1383 tu_memclr(&audio->feedback,
sizeof(audio->feedback));
1389 audio->alt_setting[idxItf] = alt;
1394 uint8_t
const* p_desc_end =
1395 audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1400 while (p_desc_end - p_desc > 0) {
1402 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1403 ((tusb_desc_interface_t
const*)p_desc)->bInterfaceNumber == itf &&
1404 ((tusb_desc_interface_t
const*)p_desc)->bAlternateSetting == alt) {
1405 uint8_t
const* p_desc_parse_for_params =
nullptr;
1407 p_desc_parse_for_params = p_desc;
1411 uint8_t foundEPs = 0,
1412 nEps = ((tusb_desc_interface_t
const*)p_desc)->bNumEndpoints;
1415 while (foundEPs < nEps && (p_desc_end - p_desc > 0)) {
1416 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
1417 tusb_desc_endpoint_t
const* desc_ep =
1418 (tusb_desc_endpoint_t
const*)p_desc;
1419#ifdef TUP_DCD_EDPT_ISO_ALLOC
1420 TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep));
1422 TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
1424 uint8_t
const ep_addr = desc_ep->bEndpointAddress;
1428 usbd_edpt_clear_stall(rhport, ep_addr);
1431 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1432 desc_ep->bmAttributes.usage ==
1436 audio->ep_in = ep_addr;
1437 audio->ep_in_as_intf_num = itf;
1438 audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
1444 audiod_parse_flow_control_params(audio,
1445 p_desc_parse_for_params);
1452 if (audiod_tx_done_cb_) {
1454 audiod_tx_done_cb_(
this, rhport, &audiod_fct_[func_id]));
1460 if (tu_edpt_dir(ep_addr) ==
1464 audio->ep_out = ep_addr;
1465 audio->ep_out_as_intf_num = itf;
1466 audio->ep_out_sz = tu_edpt_packet_size(desc_ep);
1469 if (getUseLinearBufferRx()) {
1470 TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out,
1471 audio->lin_buf_out.data(),
1476 usbd_edpt_xfer_fifo(rhport, audio->ep_out,
1477 &audio->ep_out_ff, audio->ep_out_sz),
1483 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1484 desc_ep->bmAttributes.usage ==
1487 audio->ep_fb = ep_addr;
1488 audio->feedback.frame_shift = desc_ep->bInterval - 1;
1495 p_desc = tu_desc_next(p_desc);
1498 TU_VERIFY(foundEPs == nEps);
1501 if (tud_audio_set_itf_cb_) {
1502 TU_VERIFY(tud_audio_set_itf_cb_(
this, rhport, p_request));
1507 if (audio->ep_fb != 0) {
1508 audio_feedback_params_t fb_param;
1510 if (tud_audio_feedback_params_cb_) {
1511 tud_audio_feedback_params_cb_(
this, func_id, alt, &fb_param);
1513 audio->feedback.compute_method = fb_param.method;
1515 if (TUSB_SPEED_FULL == tud_speed_get())
1516 if (tud_audio_feedback_format_correction_cb_) {
1517 audio->feedback.format_correction =
1518 tud_audio_feedback_format_correction_cb_(
this, func_id);
1523 uint32_t
const frame_div =
1524 (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000;
1525 audio->feedback.min_value = ((fb_param.sample_freq - 1) / frame_div)
1527 audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1)
1530 switch (fb_param.method) {
1531 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
1532 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1533 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1534 audiod_set_fb_params_freq(audio, fb_param.sample_freq,
1535 fb_param.frequency.mclk_freq);
1538 case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: {
1540 uint16_t fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2;
1541 audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr;
1542 audio->feedback.compute.fifo_count.fifo_lvl_avg =
1543 ((uint32_t)fifo_lvl_thr) << 16;
1546 ((fb_param.sample_freq / 100) << 16) / (frame_div / 100);
1547 audio->feedback.compute.fifo_count.nom_value = nominal;
1548 audio->feedback.compute.fifo_count.rate_const[0] =
1549 (uint16_t)((audio->feedback.max_value - nominal) /
1551 audio->feedback.compute.fifo_count.rate_const[1] =
1552 (uint16_t)((nominal - audio->feedback.min_value) /
1556 if (tud_speed_get() == TUSB_SPEED_HIGH) {
1557 audio->feedback.compute.fifo_count.rate_const[0] /= 8;
1558 audio->feedback.compute.fifo_count.rate_const[1] /= 8;
1574 p_desc = tu_desc_next(p_desc);
1579 bool enable_sof =
false;
1581 if (audiod_fct_[i].ep_fb != 0 &&
1582 (audiod_fct_[i].feedback.compute_method ==
1583 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED ||
1584 audiod_fct_[i].feedback.compute_method ==
1585 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT ||
1586 audiod_fct_[i].feedback.compute_method ==
1587 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2)) {
1592 usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, enable_sof);
1596 audiod_calc_tx_packet_sz(audio);
1599 tud_control_status(rhport, p_request);
1604 bool audiod_set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq,
1605 uint32_t mclk_freq) {
1612 uint32_t
const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13;
1613 uint32_t
const n_frame = (1UL << audio->feedback.frame_shift);
1615 if ((((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame) {
1616 TU_LOG1(
" UAC2 feedback interval too small\r\n");
1622 if ((mclk_freq % sample_freq) == 0 &&
1623 tu_is_power_of_two(mclk_freq / sample_freq)) {
1624 audio->feedback.compute_method =
1625 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2;
1626 audio->feedback.compute.power_of_2 =
1627 (uint8_t)(16 - (audio->feedback.frame_shift - 1) -
1628 tu_log2(mclk_freq / sample_freq));
1629 }
else if (audio->feedback.compute_method ==
1630 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) {
1631 audio->feedback.compute.float_const =
1632 (float)sample_freq / (
float)mclk_freq *
1633 (1UL << (16 - (audio->feedback.frame_shift - 1)));
1635 audio->feedback.compute.fixed.sample_freq = sample_freq;
1636 audio->feedback.compute.fixed.mclk_freq = mclk_freq;
1642 bool audiod_calc_tx_packet_sz(audiod_function_t* audio) {
1643 TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
1644 TU_VERIFY(audio->n_channels_tx);
1645 TU_VERIFY(audio->n_bytes_per_sample_tx);
1646 TU_VERIFY(audio->interval_tx);
1647 TU_VERIFY(audio->sample_rate_tx);
1649 const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL)
1650 ? audio->interval_tx
1651 : 1 << (audio->interval_tx - 1);
1653 const uint16_t sample_normimal =
1654 (uint16_t)(audio->sample_rate_tx * interval /
1655 ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1656 const uint16_t sample_reminder =
1657 (uint16_t)(audio->sample_rate_tx * interval %
1658 ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1660 const uint16_t packet_sz_tx_min =
1661 (uint16_t)((sample_normimal - 1) * audio->n_channels_tx *
1662 audio->n_bytes_per_sample_tx);
1663 const uint16_t packet_sz_tx_norm =
1664 (uint16_t)(sample_normimal * audio->n_channels_tx *
1665 audio->n_bytes_per_sample_tx);
1666 const uint16_t packet_sz_tx_max =
1667 (uint16_t)((sample_normimal + 1) * audio->n_channels_tx *
1668 audio->n_bytes_per_sample_tx);
1671 TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
1674 if (sample_reminder) {
1677 audio->packet_sz_tx[0] = packet_sz_tx_norm;
1678 audio->packet_sz_tx[1] = packet_sz_tx_norm;
1679 audio->packet_sz_tx[2] = packet_sz_tx_max;
1683 audio->packet_sz_tx[0] = packet_sz_tx_min;
1684 audio->packet_sz_tx[1] = packet_sz_tx_norm;
1685 audio->packet_sz_tx[2] = packet_sz_tx_max;
1691 uint16_t tud_audio_n_write(uint8_t func_id,
const void* data, uint16_t len) {
1692 TU_VERIFY(func_id <
getAudioCount() && audiod_fct_[func_id].p_desc != NULL);
1693 return tu_fifo_write_n(&audiod_fct_[func_id].ep_in_ff, data, len);
1696 uint16_t tud_audio_n_available(uint8_t func_id) {
1697 TU_VERIFY(func_id <
getAudioCount() && audiod_fct_[func_id].p_desc != NULL);
1698 return tu_fifo_count(&audiod_fct_[func_id].ep_out_ff);
1701 uint16_t tud_audio_n_read(uint8_t func_id,
void* buffer, uint16_t bufsize) {
1702 TU_VERIFY(func_id <
getAudioCount() && audiod_fct_[func_id].p_desc != NULL);
1703 return tu_fifo_read_n(&audiod_fct_[func_id].ep_out_ff, buffer, bufsize);