30 enum audio_format_type_t {
33 AUDIO_FORMAT_TYPE_III,
36 enum audio_feedback_method_t {
37 AUDIO_FEEDBACK_METHOD_DISABLED,
38 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
39 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
40 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
41 AUDIO_FEEDBACK_METHOD_FIFO_COUNT
44 struct audiod_function_t {
46 uint8_t
const *p_desc;
64 uint8_t compute_method;
65 bool format_correction;
75 uint32_t fifo_lvl_avg;
76 uint16_t fifo_lvl_thr;
77 uint16_t rate_const[2];
81 uint32_t sample_rate_tx;
82 uint16_t packet_sz_tx[3];
85 audio_format_type_t format_type_tx;
86 uint8_t n_channels_tx;
87 uint8_t n_bytes_per_sample_tx;
92 std::vector<uint8_t> ctrl_buf;
93 std::vector<uint8_t> alt_setting;
94 std::vector<uint8_t> lin_buf_out;
95 std::vector<uint8_t> lin_buf_in;
96 std::vector<uint32_t> fb_buf;
97 std::vector<uint8_t> ep_in_sw_buf;
98 std::vector<uint8_t> ep_out_sw_buf;
101 struct audio_feedback_params_t {
103 uint32_t sample_freq;
117 bool getEnableEpIn()
const {
return config_.enable_ep_in;}
118 bool getEnableEpOut()
const {
return config_.enable_ep_out; }
119 bool getEnableFeedbackEp()
const {
return config_.enable_feedback_ep; }
120 bool getEnableEpInFlowControl()
const {
return config_.enable_ep_in_flow_control;}
121 bool getEnableInterruptEp()
const {
return config_.enable_interrupt_ep; }
122 bool getEnableFifoMutex()
const {
return config_.enable_fifo_mutex; }
125 uint8_t getAudioCount()
const {
return config_.audio_count; }
128 const uint8_t *getAudioDescriptors(uint8_t itf, uint8_t alt,
129 uint16_t *out_length) {
162 return descr_builder.buildDescriptor(itf, alt, out_length);
166 bool mounted()
const {
return tud_mounted(); }
169 bool handleControlRequest(
const tusb_control_request_t *request,
void *buffer,
172 if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
173 request->bRequest == TUSB_REQ_GET_DESCRIPTOR) {
176 uint8_t
const itf = tu_u16_low(request->wIndex);
177 uint8_t
const alt = tu_u16_low(request->wValue);
179 const uint8_t *desc = getAudioDescriptors(itf, alt, &desc_len);
180 if (desc && buffer && length >= desc_len) {
181 std::memcpy(buffer, desc, desc_len);
193 uint8_t audio_data[48] = {0};
194 uint16_t bytes_written = 48;
196 bytes_written = tx_callback_(audio_data,
sizeof(audio_data));
197 write(audio_data, bytes_written);
202 uint16_t n = read(buf,
sizeof(buf));
203 if (n > 0 && rx_callback_) rx_callback_(buf, n);
208 void setRxCallback(std::function<
void(
const uint8_t *, uint16_t)> cb) {
212 void setTxCallback(std::function<uint16_t(
const void *, uint16_t)> cb) {
216 void setGetReqItfCallback(std::function<
bool(
USBAudioDevice *, uint8_t,
217 tusb_control_request_t
const *)>
219 get_req_itf_cb_ = cb;
222 void setGetReqEntityCallback(
224 tusb_control_request_t
const *)>
226 get_req_entity_cb_ = cb;
229 void setGetReqEpCallback(std::function<
bool(
USBAudioDevice *, uint8_t,
230 tusb_control_request_t
const *)>
235 void setFbDoneCallback(std::function<
void(
USBAudioDevice *, uint8_t)> cb) {
239 void setIntDoneCallback(std::function<
void(
USBAudioDevice *, uint8_t)> cb) {
243 void setTxDoneCallback(
244 std::function<
bool(
USBAudioDevice *, uint8_t, audiod_function_t *)> cb) {
248 void setRxDoneCallback(std::function<
bool(
USBAudioDevice *, uint8_t,
249 audiod_function_t *, uint16_t)> cb) {
253 void setReqEntityCallback(std::function<
bool(
USBAudioDevice *, uint8_t)> cb) {
257 void setTudAudioSetItfCallback(
259 tusb_control_request_t
const *)>cb) {
260 tud_audio_set_itf_cb_ = cb;
263 void setReqEntityCallback(
265 tusb_control_request_t
const *, uint8_t *)>
267 tud_audio_set_req_entity_cb_ = cb;
270 void setReqItfCallback(
272 tusb_control_request_t
const *, uint8_t *)>
274 tud_audio_set_req_itf_cb_ = cb;
277 void setReqEpCallback(
279 tusb_control_request_t
const *, uint8_t *)>
281 tud_audio_set_req_ep_cb_ = cb;
284 void setItfCloseEpCallback(std::function<
bool(
USBAudioDevice *, uint8_t,
285 tusb_control_request_t
const *)>
287 tud_audio_set_itf_close_EP_cb_ = cb;
290 void setAudiodTxDoneCallback(
291 std::function<
bool(
USBAudioDevice *, uint8_t, audiod_function_t *)> cb) {
292 audiod_tx_done_cb_ = cb;
295 void setAudioFeedbackParamsCallback(
297 audio_feedback_params_t *)>
299 tud_audio_feedback_params_cb_ = cb;
302 void setAudioFeedbackFormatCorrectionCallback(
304 tud_audio_feedback_format_correction_cb_ = cb;
313 usbd_class_driver_t
const *usbd_app_driver_get(uint8_t *count) {
314 static usbd_class_driver_t driver;
315 driver.name =
"Audio";
316 driver.init = [](void) { USBAudioDevice::instance().audiod_init(); };
317 driver.deinit = [](void) {
318 return USBAudioDevice::instance().audiod_deinit();
320 driver.reset = [](uint8_t rhport) {
321 USBAudioDevice::instance().audiod_reset(rhport);
323 driver.open = [](uint8_t rhport, tusb_desc_interface_t
const *itf_desc,
325 return USBAudioDevice::instance().audiod_open(rhport, itf_desc, max_len);
327 driver.control_xfer_cb = [](uint8_t rhport, uint8_t stage,
328 tusb_control_request_t
const *request) {
329 return USBAudioDevice::instance().audiod_control_xfer_cb(rhport, stage,
332 driver.xfer_cb = [](uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
333 uint32_t xferred_bytes) {
334 return USBAudioDevice::instance().audiod_xfer_cb(rhport, ep_addr, result,
337 driver.sof = [](uint8_t rhport, uint32_t frame_count) {
338 USBAudioDevice::instance().audiod_sof_isr(rhport, frame_count);
348 std::function<void(
const uint8_t *, uint16_t)> rx_callback_;
349 std::function<uint16_t(
const void *, uint16_t)> tx_callback_;
350 std::function<void(
USBAudioDevice *, uint8_t rhport)> int_done_cb_;
351 std::function<bool(
USBAudioDevice *, uint8_t rhport, audiod_function_t *)>
353 std::function<bool(
USBAudioDevice *, uint8_t rhport, audiod_function_t *,
354 uint16_t xferred_bytes)>
358 tusb_control_request_t
const *)>
362 tusb_control_request_t
const *)>
366 tusb_control_request_t
const *)>
370 std::function<void(
USBAudioDevice *, uint8_t func_id)> fb_done_cb_;
371 std::function<bool(
USBAudioDevice *, uint8_t func_id)> req_entity_cb_;
373 tusb_control_request_t
const *p_request)>
374 tud_audio_set_itf_cb_;
376 tusb_control_request_t
const *p_request, uint8_t *pBuff)>
377 tud_audio_set_req_entity_cb_;
380 tusb_control_request_t
const *p_request, uint8_t *pBuff)>
381 tud_audio_set_req_itf_cb_;
384 tusb_control_request_t
const *p_request, uint8_t *pBuff)>
385 tud_audio_set_req_ep_cb_;
388 tusb_control_request_t
const *p_request)>
389 tud_audio_set_itf_close_EP_cb_;
392 audiod_function_t *audio)>
395 std::function<void(
USBAudioDevice *, uint8_t func_id, uint8_t alt_itf,
396 audio_feedback_params_t *feedback_param)>
397 tud_audio_feedback_params_cb_;
400 tud_audio_feedback_format_correction_cb_;
404 std::vector<uint16_t> ep_out_sw_buf_sz_;
407 std::vector<uint16_t> ep_in_sw_buf_sz_;
409 std::vector<uint16_t> desc_len_;
411 std::vector<uint16_t> ctrl_buf_sz_;
413 std::vector<audiod_function_t> audiod_fct_;
414 std::vector<osal_mutex_def_t> ep_in_ff_mutex_wr_;
415 std::vector<osal_mutex_def_t> ep_out_ff_mutex_rd_;
420 uint16_t getCtrlBufSz(uint8_t fn)
const {
421 return (fn < ctrl_buf_sz_.size()) ? ctrl_buf_sz_[fn] : 64;
425 uint16_t getEpOutSwBufSz(uint8_t fn)
const {
426 return (fn < ep_out_sw_buf_sz_.size()) ? ep_out_sw_buf_sz_[fn] : 0;
430 uint16_t getEpInSwBufSz(uint8_t fn)
const {
431 return (fn < ep_in_sw_buf_sz_.size()) ? ep_in_sw_buf_sz_[fn] : 0;
435 uint16_t getDescLen(uint8_t fn)
const {
436 return (fn < desc_len_.size()) ? desc_len_[fn] : 0;
440 bool getUseLinearBufferRx()
const {
return config_.use_linear_buffer_rx; }
442 bool getUseLinearBufferTx()
const {
return config_.use_linear_buffer_tx; }
446 static constexpr size_t getResetSize() {
447 return offsetof(audiod_function_t, ctrl_buf_sz) +
448 sizeof(((audiod_function_t *)0)->ctrl_buf_sz);
453 void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_count,
454 uint8_t frame_shift) {
459 uint16_t write(
const void *data, uint16_t len) {
460 uint16_t written = tud_audio_n_write(config_.ep_in, data, len);
466 uint16_t read(
void *buffer, uint16_t bufsize) {
467 return tud_audio_n_read(config_.ep_out, buffer, bufsize);
471 void audiod_init(
void) {
472 audiod_fct_.resize(getAudioCount());
476 for (uint8_t i = 0; i < getAudioCount(); i++) {
477 audiod_function_t *audio = &audiod_fct_[i];
479 int size = getCtrlBufSz(i);
480 audio->ctrl_buf.resize(size);
481 audio->ctrl_buf_sz = size;
483 audio->alt_setting.resize(config_.as_descr_count);
485 if (getEnableEpIn()) {
486 audio->ep_in_sw_buf.resize(getEpInSwBufSz(i));
488 tu_fifo_config(&audio->ep_in_ff,
489 audio->ep_in_sw_buf.data(),
490 getEpInSwBufSz(i), 1,
true);
491 if (getEnableFifoMutex()) {
492 tu_fifo_config_mutex(&audio->ep_in_ff,
493 osal_mutex_create(&ep_in_ff_mutex_wr_[i]), NULL);
497 if (getUseLinearBufferTx()) {
498 audio->lin_buf_in.resize(config_.lin_buf_in_size_per_func);
501 if (getEnableEpOut()) {
502 audio->ep_out_sw_buf.resize(getEpOutSwBufSz(i));
503 tu_fifo_config(&audio->ep_out_ff, audio->ep_out_sw_buf.data(),
504 getEpOutSwBufSz(i), 1,
true);
505 if (getEnableFifoMutex()) {
506 tu_fifo_config_mutex(&audio->ep_out_ff, NULL,
507 osal_mutex_create(&ep_out_ff_mutex_rd_[i]));
511 if (getUseLinearBufferRx()) {
512 audio->lin_buf_out.resize(config_.lin_buf_in_size_per_func);
514 if (getEnableFeedbackEp()) {
515 audio->fb_buf.resize(getEpOutSwBufSz(i));
521 if (getEnableFifoMutex()) {
522 if (getEnableEpIn()) {
523 ep_in_ff_mutex_wr_.resize(getAudioCount());
525 if (getEnableEpOut()) {
526 ep_out_ff_mutex_rd_.resize(getAudioCount());
531 bool audiod_deinit(
void) {
535 void audiod_reset(uint8_t rhport) {
537 for (uint8_t i = 0; i < getAudioCount(); i++) {
538 audiod_function_t *audio = &audiod_fct_[i];
539 memset(audio, 0, getResetSize());
540 if (getEnableEpIn()) {
541 tu_fifo_clear(&audio->ep_in_ff);
543 if (getEnableEpOut()) {
544 tu_fifo_clear(&audio->ep_out_ff);
549 uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t
const *itf_desc,
552 TU_VERIFY(TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass &&
553 AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass);
554 TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2);
555 TU_ASSERT(itf_desc->bNumEndpoints <= 1);
556 if (itf_desc->bNumEndpoints == 1) {
557 TU_ASSERT(getEnableInterruptEp());
559 TU_VERIFY(itf_desc->bAlternateSetting == 0);
561 for (i = 0; i < getAudioCount(); i++) {
562 if (!audiod_fct_[i].p_desc) {
563 audiod_fct_[i].p_desc = (uint8_t
const *)itf_desc;
564 audiod_fct_[i].rhport = rhport;
565 audiod_fct_[i].desc_length = getDescLen(i);
566 if (getEnableEpIn() || getEnableEpOut() || getEnableFeedbackEp()) {
567 uint8_t ep_in = 0, ep_out = 0, ep_fb = 0;
568 uint16_t ep_in_size = 0, ep_out_size = 0;
569 uint8_t
const *p_desc = audiod_fct_[i].p_desc;
570 uint8_t
const *p_desc_end =
571 p_desc + audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
572 while (p_desc_end - p_desc > 0) {
573 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
574 tusb_desc_endpoint_t
const *desc_ep =
575 (tusb_desc_endpoint_t
const *)p_desc;
576 if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
577 if (getEnableFeedbackEp() && desc_ep->bmAttributes.usage == 1) {
578 ep_fb = desc_ep->bEndpointAddress;
580 if (desc_ep->bmAttributes.usage == 0) {
581 if (getEnableEpIn() &&
582 tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
583 ep_in = desc_ep->bEndpointAddress;
585 TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
586 }
else if (getEnableEpOut() &&
587 tu_edpt_dir(desc_ep->bEndpointAddress) ==
589 ep_out = desc_ep->bEndpointAddress;
591 TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
596 p_desc = tu_desc_next(p_desc);
598 if (getEnableEpIn() && ep_in) {
599 usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
601 if (getEnableEpOut() && ep_out) {
602 usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
604 if (getEnableFeedbackEp() && ep_fb) {
605 usbd_edpt_iso_alloc(rhport, ep_fb, 4);
608 if (getEnableEpIn() && getEnableEpInFlowControl()) {
609 uint8_t
const *p_desc = audiod_fct_[i].p_desc;
610 uint8_t
const *p_desc_end =
611 p_desc + audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
612 while (p_desc_end - p_desc > 0) {
613 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
614 tusb_desc_endpoint_t
const *desc_ep =
615 (tusb_desc_endpoint_t
const *)p_desc;
616 if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS &&
617 desc_ep->bmAttributes.usage == 0 &&
618 tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
619 audiod_fct_[i].interval_tx = desc_ep->bInterval;
621 }
else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
622 tu_desc_subtype(p_desc) ==
623 AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
624 if (tu_unaligned_read16(p_desc + 4) ==
625 AUDIO_TERM_TYPE_USB_STREAMING) {
626 audiod_fct_[i].bclock_id_tx = p_desc[8];
629 p_desc = tu_desc_next(p_desc);
632 if (getEnableInterruptEp()) {
633 uint8_t
const *p_desc = audiod_fct_[i].p_desc;
634 uint8_t
const *p_desc_end =
635 p_desc + audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
636 while (p_desc_end - p_desc > 0) {
637 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
638 tusb_desc_endpoint_t
const *desc_ep =
639 (tusb_desc_endpoint_t
const *)p_desc;
640 uint8_t
const ep_addr = desc_ep->bEndpointAddress;
641 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
642 desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) {
643 audiod_fct_[i].ep_int = ep_addr;
644 TU_ASSERT(usbd_edpt_open(audiod_fct_[i].rhport, desc_ep));
647 p_desc = tu_desc_next(p_desc);
650 audiod_fct_[i].mounted =
true;
654 TU_ASSERT(i < getAudioCount());
655 uint16_t drv_len = audiod_fct_[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
659 bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage,
660 tusb_control_request_t
const *request) {
661 if (stage == CONTROL_STAGE_SETUP) {
662 return audiod_control_request(rhport, request);
663 }
else if (stage == CONTROL_STAGE_DATA) {
664 return audiod_control_complete(rhport, request);
670 bool audiod_control_complete(uint8_t rhport,
671 tusb_control_request_t
const *p_request) {
673 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
674 p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
677 switch (p_request->bmRequestType_bit.recipient) {
678 case TUSB_REQ_RCPT_INTERFACE: {
679 uint8_t itf = TU_U16_LOW(p_request->wIndex);
680 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
684 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
686 if (getEnableEpIn() && getEnableEpInFlowControl()) {
687 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
688 if (audiod_fct_[func_id].bclock_id_tx == entityID &&
689 ctrlSel == AUDIO_CS_CTRL_SAM_FREQ &&
690 p_request->bRequest == AUDIO_CS_REQ_CUR) {
691 audiod_fct_[func_id].sample_rate_tx =
692 tu_unaligned_read32(audiod_fct_[func_id].ctrl_buf.data());
697 if (tud_audio_set_req_entity_cb_) {
698 return tud_audio_set_req_entity_cb_(
699 this, rhport, p_request,
700 audiod_fct_[func_id].ctrl_buf.data());
705 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
708 if (tud_audio_set_req_itf_cb_) {
709 return tud_audio_set_req_itf_cb_(
710 this, rhport, p_request,
711 audiod_fct_[func_id].ctrl_buf.data());
716 case TUSB_REQ_RCPT_ENDPOINT: {
717 uint8_t ep = TU_U16_LOW(p_request->wIndex);
720 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
723 if (tud_audio_set_req_ep_cb_) {
724 return tud_audio_set_req_ep_cb_(
725 this, rhport, p_request, audiod_fct_[func_id].ctrl_buf.data());
737 bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
738 uint32_t xferred_bytes) {
741 for (uint8_t func_id = 0; func_id < getAudioCount(); func_id++) {
742 audiod_function_t *audio = &audiod_fct_[func_id];
743 if (getEnableInterruptEp() && audio->ep_int == ep_addr) {
744 if (int_done_cb_) int_done_cb_(
this, rhport);
747 if (getEnableEpIn() && audio->ep_in == ep_addr &&
748 audio->alt_setting.size() != 0) {
749 if (tx_done_cb_ && tx_done_cb_(
this, rhport, audio))
return true;
752 if (getEnableEpOut() && audio->ep_out == ep_addr) {
754 rx_done_cb_(
this, rhport, audio, (uint16_t)xferred_bytes))
758 if (getEnableFeedbackEp() && audio->ep_fb == ep_addr) {
760 fb_done_cb_(
this, func_id);
762 if (usbd_edpt_claim(rhport, audio->ep_fb)) {
763 return audiod_fb_send(audio);
770 TU_ATTR_FAST_FUNC
void audiod_sof_isr(uint8_t rhport, uint32_t frame_count) {
773 if (getEnableEpOut() && getEnableFeedbackEp()) {
774 for (uint8_t i = 0; i < getAudioCount(); i++) {
775 audiod_function_t *audio = &audiod_fct_[i];
776 if (audio->ep_fb != 0) {
777 uint8_t
const hs_adjust =
778 (TUSB_SPEED_HIGH == tud_speed_get()) ? 3 : 0;
779 uint32_t
const interval =
780 1UL << (audio->feedback.frame_shift - hs_adjust);
781 if (0 == (frame_count & (interval - 1))) {
782 tud_audio_feedback_interval_isr(i, frame_count,
783 audio->feedback.frame_shift);
790 bool audiod_control_request(uint8_t rhport,
791 tusb_control_request_t
const *p_request) {
796 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
797 switch (p_request->bRequest) {
798 case TUSB_REQ_GET_INTERFACE:
799 return audiod_get_interface(rhport, p_request);
801 case TUSB_REQ_SET_INTERFACE:
802 return audiod_set_interface(rhport, p_request);
804 case TUSB_REQ_CLEAR_FEATURE:
815 if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
816 uint8_t itf = TU_U16_LOW(p_request->wIndex);
820 switch (p_request->bmRequestType_bit.recipient) {
821 case TUSB_REQ_RCPT_INTERFACE: {
822 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
828 TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
832 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN &&
834 return req_entity_cb_(
this, func_id);
839 TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
843 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
845 if (get_req_itf_cb_) {
846 return get_req_itf_cb_(
this, rhport, p_request);
853 case TUSB_REQ_RCPT_ENDPOINT: {
854 uint8_t ep = TU_U16_LOW(p_request->wIndex);
857 TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
861 if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) {
863 if (get_req_ep_cb_) {
864 return get_req_ep_cb_(
this, rhport, p_request);
872 TU_LOG2(
" Unsupported recipient: %d\r\n",
873 p_request->bmRequestType_bit.recipient);
881 TU_VERIFY(tud_control_xfer(rhport, p_request,
882 audiod_fct_[func_id].ctrl_buf.data(),
883 audiod_fct_[func_id].ctrl_buf_sz));
893 bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID,
896 for (i = 0; i < getAudioCount(); i++) {
899 if (audiod_fct_[i].p_desc &&
900 ((tusb_desc_interface_t
const *)audiod_fct_[i].p_desc)
901 ->bInterfaceNumber == itf) {
904 uint8_t
const *p_desc =
905 tu_desc_next(audiod_fct_[i].p_desc);
906 uint8_t
const *p_desc_end =
907 ((audio_desc_cs_ac_interface_t
const *)p_desc)->wTotalLength +
909 p_desc = tu_desc_next(p_desc);
913 while (p_desc_end - p_desc > 0) {
914 if (p_desc[3] == entityID)
919 p_desc = tu_desc_next(p_desc);
926 bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) {
928 for (i = 0; i < getAudioCount(); i++) {
929 if (audiod_fct_[i].p_desc) {
931 uint8_t
const *p_desc_end =
932 audiod_fct_[i].p_desc + audiod_fct_[i].desc_length;
935 uint8_t
const *p_desc = tu_desc_next(audiod_fct_[i].p_desc);
936 p_desc += ((audio_desc_cs_ac_interface_t
const *)p_desc)->wTotalLength;
940 while (p_desc_end - p_desc > 0) {
941 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT &&
942 ((tusb_desc_endpoint_t
const *)p_desc)->bEndpointAddress == ep) {
946 p_desc = tu_desc_next(p_desc);
953 bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) {
955 for (i = 0; i < getAudioCount(); i++) {
956 if (audiod_fct_[i].p_desc) {
958 uint8_t
const *p_desc = audiod_fct_[i].p_desc;
959 uint8_t
const *p_desc_end = audiod_fct_[i].p_desc +
960 audiod_fct_[i].desc_length -
961 TUD_AUDIO_DESC_IAD_LEN;
964 while (p_desc_end - p_desc > 0) {
965 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
966 ((tusb_desc_interface_t
const *)audiod_fct_[i].p_desc)
967 ->bInterfaceNumber == itf) {
971 p_desc = tu_desc_next(p_desc);
978 void audiod_parse_flow_control_params(audiod_function_t *audio,
979 uint8_t
const *p_desc) {
980 p_desc = tu_desc_next(p_desc);
985 if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
986 tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) {
987 audio->n_channels_tx =
988 ((audio_desc_cs_as_interface_t
const *)p_desc)->bNrChannels;
989 audio->format_type_tx =
990 (audio_format_type_t)(((audio_desc_cs_as_interface_t
const *)p_desc)
993 p_desc = tu_desc_next(p_desc);
994 if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
995 tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE &&
996 ((audio_desc_type_I_format_t
const *)p_desc)->bFormatType ==
997 AUDIO_FORMAT_TYPE_I) {
998 audio->n_bytes_per_sample_tx =
999 ((audio_desc_type_I_format_t
const *)p_desc)->bSubslotSize;
1011 bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t *audio,
1013 uint8_t
const **pp_desc_int) {
1014 if (audio->p_desc) {
1016 uint8_t
const *p_desc_end =
1017 audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1020 uint8_t
const *p_desc = tu_desc_next(audio->p_desc);
1021 p_desc += ((audio_desc_cs_ac_interface_t
const *)p_desc)->wTotalLength;
1026 while (p_desc_end - p_desc > 0) {
1029 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1030 ((tusb_desc_interface_t
const *)p_desc)->bAlternateSetting == 0) {
1031 if (((tusb_desc_interface_t
const *)p_desc)->bInterfaceNumber ==
1034 *pp_desc_int = p_desc;
1040 p_desc = tu_desc_next(p_desc);
1052 bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id,
1054 uint8_t
const **pp_desc_int) {
1057 for (i = 0; i < getAudioCount(); i++) {
1058 if (audiod_get_AS_interface_index(itf, &audiod_fct_[i], idxItf,
1068 bool audiod_get_interface(uint8_t rhport,
1069 tusb_control_request_t
const *p_request) {
1070 uint8_t
const itf = tu_u16_low(p_request->wIndex);
1073 uint8_t func_id, idxItf;
1074 uint8_t
const *dummy;
1077 audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy));
1078 TU_VERIFY(tud_control_xfer(rhport, p_request,
1079 &audiod_fct_[func_id].alt_setting[idxItf], 1));
1081 TU_LOG2(
" Get itf: %u - current alt: %u\r\n", itf,
1082 audiod_fct_[func_id].alt_setting[idxItf]);
1087 bool audiod_fb_send(audiod_function_t *audio) {
1088 bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) &&
1089 audio->feedback.format_correction;
1091 if (apply_correction) {
1092 uint8_t *fb = (uint8_t *)audio->fb_buf.data();
1095 *(fb++) = (audio->feedback.value >> 2) & 0xFF;
1096 *(fb++) = (audio->feedback.value >> 10) & 0xFF;
1097 *(fb++) = (audio->feedback.value >> 18) & 0xFF;
1100 audio->fb_buf[0] = audio->feedback.value;
1117 return usbd_edpt_xfer(audio->rhport, audio->ep_fb,
1118 (uint8_t *)audio->fb_buf.data(),
1119 apply_correction ? 3 : 4);
1122 bool audiod_set_interface(uint8_t rhport,
1123 tusb_control_request_t
const *p_request) {
1143 uint8_t
const itf = tu_u16_low(p_request->wIndex);
1144 uint8_t
const alt = tu_u16_low(p_request->wValue);
1146 TU_LOG2(
" Set itf: %u - alt: %u\r\n", itf, alt);
1149 uint8_t func_id, idxItf;
1150 uint8_t
const *p_desc;
1152 audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc));
1154 audiod_function_t *audio = &audiod_fct_[func_id];
1159 if (getEnableEpIn()) {
1160 if (audio->ep_in_as_intf_num == itf) {
1161 audio->ep_in_as_intf_num = 0;
1162#ifndef TUP_DCD_EDPT_ISO_ALLOC
1163 usbd_edpt_close(rhport, audio->ep_in);
1167 tu_fifo_clear(&audio->ep_in_ff);
1170 if (tud_audio_set_itf_close_EP_cb_) {
1171 TU_VERIFY(tud_audio_set_itf_close_EP_cb_(
this, rhport, p_request));
1176 if (getEnableEpInFlowControl()) {
1177 audio->packet_sz_tx[0] = 0;
1178 audio->packet_sz_tx[1] = 0;
1179 audio->packet_sz_tx[2] = 0;
1184 if (getEnableEpOut()) {
1185 if (audio->ep_out_as_intf_num == itf) {
1186 audio->ep_out_as_intf_num = 0;
1187#ifndef TUP_DCD_EDPT_ISO_ALLOC
1188 usbd_edpt_close(rhport, audio->ep_out);
1192 tu_fifo_clear(&audio->ep_out_ff);
1195 if (tud_audio_set_itf_close_EP_cb_) {
1196 TU_VERIFY(tud_audio_set_itf_close_EP_cb_(
this, rhport, p_request));
1202 if (getEnableFeedbackEp()) {
1207 tu_memclr(&audio->feedback,
sizeof(audio->feedback));
1213 audio->alt_setting[idxItf] = alt;
1218 uint8_t
const *p_desc_end =
1219 audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
1224 while (p_desc_end - p_desc > 0) {
1226 if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE &&
1227 ((tusb_desc_interface_t
const *)p_desc)->bInterfaceNumber == itf &&
1228 ((tusb_desc_interface_t
const *)p_desc)->bAlternateSetting == alt) {
1229 uint8_t
const *p_desc_parse_for_params =
nullptr;
1230 if (getEnableEpIn() && getEnableEpInFlowControl()) {
1231 p_desc_parse_for_params = p_desc;
1235 uint8_t foundEPs = 0,
1236 nEps = ((tusb_desc_interface_t
const *)p_desc)->bNumEndpoints;
1239 while (foundEPs < nEps && (p_desc_end - p_desc > 0)) {
1240 if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
1241 tusb_desc_endpoint_t
const *desc_ep =
1242 (tusb_desc_endpoint_t
const *)p_desc;
1243#ifdef TUP_DCD_EDPT_ISO_ALLOC
1244 TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep));
1246 TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
1248 uint8_t
const ep_addr = desc_ep->bEndpointAddress;
1252 usbd_edpt_clear_stall(rhport, ep_addr);
1254 if (getEnableEpIn()) {
1255 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1256 desc_ep->bmAttributes.usage ==
1260 audio->ep_in = ep_addr;
1261 audio->ep_in_as_intf_num = itf;
1262 audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
1267 if (getEnableEpInFlowControl()) {
1268 audiod_parse_flow_control_params(audio,
1269 p_desc_parse_for_params);
1276 if (audiod_tx_done_cb_) {
1278 audiod_tx_done_cb_(
this, rhport, &audiod_fct_[func_id]));
1283 if (getEnableEpOut()) {
1284 if (tu_edpt_dir(ep_addr) ==
1288 audio->ep_out = ep_addr;
1289 audio->ep_out_as_intf_num = itf;
1290 audio->ep_out_sz = tu_edpt_packet_size(desc_ep);
1293 if (getUseLinearBufferRx()) {
1294 TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out,
1295 audio->lin_buf_out.data(),
1300 usbd_edpt_xfer_fifo(rhport, audio->ep_out,
1301 &audio->ep_out_ff, audio->ep_out_sz),
1306 if (getEnableFeedbackEp()) {
1307 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN &&
1308 desc_ep->bmAttributes.usage ==
1311 audio->ep_fb = ep_addr;
1312 audio->feedback.frame_shift = desc_ep->bInterval - 1;
1319 p_desc = tu_desc_next(p_desc);
1322 TU_VERIFY(foundEPs == nEps);
1325 if (tud_audio_set_itf_cb_) {
1326 TU_VERIFY(tud_audio_set_itf_cb_(
this, rhport, p_request));
1329 if (getEnableFeedbackEp()) {
1331 if (audio->ep_fb != 0) {
1332 audio_feedback_params_t fb_param;
1334 if (tud_audio_feedback_params_cb_) {
1335 tud_audio_feedback_params_cb_(
this, func_id, alt, &fb_param);
1337 audio->feedback.compute_method = fb_param.method;
1339 if (TUSB_SPEED_FULL == tud_speed_get())
1340 if (tud_audio_feedback_format_correction_cb_) {
1341 audio->feedback.format_correction =
1342 tud_audio_feedback_format_correction_cb_(
this, func_id);
1347 uint32_t
const frame_div =
1348 (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000;
1349 audio->feedback.min_value = ((fb_param.sample_freq - 1) / frame_div)
1351 audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1)
1354 switch (fb_param.method) {
1355 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
1356 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1357 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1358 audiod_set_fb_params_freq(audio, fb_param.sample_freq,
1359 fb_param.frequency.mclk_freq);
1362 case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: {
1364 uint16_t fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2;
1365 audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr;
1366 audio->feedback.compute.fifo_count.fifo_lvl_avg =
1367 ((uint32_t)fifo_lvl_thr) << 16;
1370 ((fb_param.sample_freq / 100) << 16) / (frame_div / 100);
1371 audio->feedback.compute.fifo_count.nom_value = nominal;
1372 audio->feedback.compute.fifo_count.rate_const[0] =
1373 (uint16_t)((audio->feedback.max_value - nominal) /
1375 audio->feedback.compute.fifo_count.rate_const[1] =
1376 (uint16_t)((nominal - audio->feedback.min_value) /
1380 if (tud_speed_get() == TUSB_SPEED_HIGH) {
1381 audio->feedback.compute.fifo_count.rate_const[0] /= 8;
1382 audio->feedback.compute.fifo_count.rate_const[1] /= 8;
1398 p_desc = tu_desc_next(p_desc);
1401 if (getEnableFeedbackEp()) {
1403 bool enable_sof =
false;
1404 for (uint8_t i = 0; i < getAudioCount(); i++) {
1405 if (audiod_fct_[i].ep_fb != 0 &&
1406 (audiod_fct_[i].feedback.compute_method ==
1407 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED ||
1408 audiod_fct_[i].feedback.compute_method ==
1409 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT ||
1410 audiod_fct_[i].feedback.compute_method ==
1411 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2)) {
1416 usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, enable_sof);
1419 if (getEnableEpIn() && getEnableEpInFlowControl()) {
1420 audiod_calc_tx_packet_sz(audio);
1423 tud_control_status(rhport, p_request);
1428 bool audiod_set_fb_params_freq(audiod_function_t *audio, uint32_t sample_freq,
1429 uint32_t mclk_freq) {
1436 uint32_t
const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13;
1437 uint32_t
const n_frame = (1UL << audio->feedback.frame_shift);
1439 if ((((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame) {
1440 TU_LOG1(
" UAC2 feedback interval too small\r\n");
1446 if ((mclk_freq % sample_freq) == 0 &&
1447 tu_is_power_of_two(mclk_freq / sample_freq)) {
1448 audio->feedback.compute_method =
1449 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2;
1450 audio->feedback.compute.power_of_2 =
1451 (uint8_t)(16 - (audio->feedback.frame_shift - 1) -
1452 tu_log2(mclk_freq / sample_freq));
1453 }
else if (audio->feedback.compute_method ==
1454 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) {
1455 audio->feedback.compute.float_const =
1456 (float)sample_freq / (
float)mclk_freq *
1457 (1UL << (16 - (audio->feedback.frame_shift - 1)));
1459 audio->feedback.compute.fixed.sample_freq = sample_freq;
1460 audio->feedback.compute.fixed.mclk_freq = mclk_freq;
1466 bool audiod_calc_tx_packet_sz(audiod_function_t *audio) {
1467 TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
1468 TU_VERIFY(audio->n_channels_tx);
1469 TU_VERIFY(audio->n_bytes_per_sample_tx);
1470 TU_VERIFY(audio->interval_tx);
1471 TU_VERIFY(audio->sample_rate_tx);
1473 const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL)
1474 ? audio->interval_tx
1475 : 1 << (audio->interval_tx - 1);
1477 const uint16_t sample_normimal =
1478 (uint16_t)(audio->sample_rate_tx * interval /
1479 ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1480 const uint16_t sample_reminder =
1481 (uint16_t)(audio->sample_rate_tx * interval %
1482 ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
1484 const uint16_t packet_sz_tx_min =
1485 (uint16_t)((sample_normimal - 1) * audio->n_channels_tx *
1486 audio->n_bytes_per_sample_tx);
1487 const uint16_t packet_sz_tx_norm =
1488 (uint16_t)(sample_normimal * audio->n_channels_tx *
1489 audio->n_bytes_per_sample_tx);
1490 const uint16_t packet_sz_tx_max =
1491 (uint16_t)((sample_normimal + 1) * audio->n_channels_tx *
1492 audio->n_bytes_per_sample_tx);
1495 TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
1498 if (sample_reminder) {
1501 audio->packet_sz_tx[0] = packet_sz_tx_norm;
1502 audio->packet_sz_tx[1] = packet_sz_tx_norm;
1503 audio->packet_sz_tx[2] = packet_sz_tx_max;
1507 audio->packet_sz_tx[0] = packet_sz_tx_min;
1508 audio->packet_sz_tx[1] = packet_sz_tx_norm;
1509 audio->packet_sz_tx[2] = packet_sz_tx_max;
1515 uint16_t tud_audio_n_write(uint8_t func_id,
const void *data, uint16_t len) {
1516 TU_VERIFY(func_id < getAudioCount() && audiod_fct_[func_id].p_desc != NULL);
1517 return tu_fifo_write_n(&audiod_fct_[func_id].ep_in_ff, data, len);
1520 uint16_t tud_audio_n_available(uint8_t func_id) {
1521 TU_VERIFY(func_id < getAudioCount() && audiod_fct_[func_id].p_desc != NULL);
1522 return tu_fifo_count(&audiod_fct_[func_id].ep_out_ff);
1525 uint16_t tud_audio_n_read(uint8_t func_id,
void *buffer, uint16_t bufsize) {
1526 TU_VERIFY(func_id < getAudioCount() && audiod_fct_[func_id].p_desc != NULL);
1527 return tu_fifo_read_n(&audiod_fct_[func_id].ep_out_ff, buffer, bufsize);