6 #include "USBDeviceAudioAPI.h"
7 #include "common/tusb_types.h"
12 #define AUDIO_LOG(...) \
15 snprintf(msg, 160, __VA_ARGS__); \
16 LOG_AUDIO_OUTPUT.println(msg); \
17 LOG_AUDIO_OUTPUT.flush(); \
19 #define AUDIO_NO_LOG(...)
21 #define LOG_AUDIO_OUTPUT Serial
22 #define AUDIO_DEBUG false
23 #define LOG_AUDIO_ERROR AUDIO_LOG
24 #define LOG_AUDIO_DEBUG AUDIO_LOG
36 #define UAC2_ENTITY_CLOCK 0x10
39 #define UAC2_ENTITY_SPK_INPUT_TERMINAL 0x15
40 #define UAC2_ENTITY_SPK_FEATURE_UNIT 0x16
41 #define UAC2_ENTITY_SPK_OUTPUT_TERMINAL 0x17
44 #define UAC2_ENTITY_MIC_INPUT_TERMINAL 0x11
45 #define UAC2_ENTITY_MIC_FEATURE_UNIT 0x12
46 #define UAC2_ENTITY_MIC_OUTPUT_TERMINAL 0x13
50 #define debugWrite(pin, active) digitalWrite(pin, active);
52 #define debugWrite(pin, active)
56 enum class AudioProcessingStatus {
67 void resize(
int size) { vector.resize(size); }
69 uint8_t *data() {
return vector.data(); }
74 memmove(data(), data() + n, pos);
78 int available() {
return pos; }
80 int size() {
return vector.size(); }
82 void reset() {
int pos = 0; }
84 void clear() { memset(data(), 0, size()); }
86 void setAvailable(
int av) { pos = av; }
89 std::vector<uint8_t> vector;
113 cfg.p_write_callback = write_cb;
120 cfg.p_read_callback = read_cb;
142 _itf_number_total = 0;
147 _api.begin(
this, cfg);
148 _mute.resize(cfg.channels + 1);
149 _volume.resize(cfg.channels + 1);
152 if (!isMicrophone() && !isSpeaker()) {
153 LOG_AUDIO_ERROR(
"No callback has been defined");
159 if (interfaceDescriptor(
nullptr, 1024) == 0) {
161 LOG_AUDIO_ERROR(
"Interface Descriptor length was 0");
166 setStatus(AudioProcessingStatus::ACTIVE);
172 tud_deinit(cfg.rh_port);
173 setStatus(AudioProcessingStatus::INACTIVE);
174 if (_out_buffer.size() > 0) _out_buffer.resize(0);
175 if (_in_buffer.size() > 0) _out_buffer.resize(0);
180 return status() == AudioProcessingStatus::ACTIVE ||
181 status() == AudioProcessingStatus::PLAYING;
184 operator bool() {
return active(); }
187 uint32_t rate() {
return cfg.sample_rate; }
190 int channels() {
return cfg.channels; }
193 uint16_t volume(
int channel) {
return _volume[channel]; }
196 bool isMute(
int channel) {
return _mute[channel]; }
201 pinMode(pin, OUTPUT);
202 _is_led_setup =
false;
206 if (_processing_status != AudioProcessingStatus::INACTIVE &&
207 millis() > _led_timeout) {
208 _led_timeout = millis() + (uint16_t)_processing_status;
209 _led_active = !_led_active;
210 digitalWrite(pin, _led_active);
215 if (_processing_status == AudioProcessingStatus::INACTIVE) {
218 digitalWrite(pin, _led_active);
225 AudioProcessingStatus
status() {
return _processing_status; }
227 bool isMicrophone() {
228 return (cfg.p_read_callback !=
nullptr && cfg.p_read_callback != defaultReadCB) ||
229 (cfg.p_read_callback == defaultReadCB && p_stream !=
nullptr);
233 return (cfg.p_write_callback !=
nullptr &&
234 cfg.p_write_callback != defaultWriteCB) ||
235 (cfg.p_write_callback == defaultWriteCB && p_print !=
nullptr);
238 bool isHeadset() {
return isSpeaker() && isMicrophone(); }
247 virtual uint16_t getMaxEPSize() {
248 return TUD_AUDIO_EP_SIZE(cfg.sample_rate, cfg.bits_per_sample / 8,
252 virtual uint16_t getIOSize() {
253 return TUD_AUDIO_EP_SIZE(cfg.sample_rate, cfg.bits_per_sample / 8,
257 virtual uint8_t getFeatureUnitLength() {
return (6 + (channels() + 1) * 4); }
261 bool set_itf_cb(uint8_t rhport,
262 tusb_control_request_t
const *p_request)
override {
263 uint8_t
const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
264 uint8_t
const alt = tu_u16_low(tu_le16toh(p_request->wValue));
266 if (alt != 0)
setStatus(AudioProcessingStatus::PLAYING);
272 bool set_req_ep_cb(uint8_t rhport, tusb_control_request_t
const *p_request,
273 uint8_t *pBuff)
override {
279 TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
282 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
283 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
284 uint8_t ep = TU_U16_LOW(p_request->wIndex);
294 bool set_req_itf_cb(uint8_t rhport, tusb_control_request_t
const *p_request,
295 uint8_t *pBuff)
override {
301 TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR);
304 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
305 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
306 uint8_t itf = TU_U16_LOW(p_request->wIndex);
316 bool set_req_entity_cb(uint8_t rhport,
317 tusb_control_request_t
const *p_request,
318 uint8_t *buf)
override {
320 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
321 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
322 uint8_t itf = TU_U16_LOW(p_request->wIndex);
323 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
324 audio_control_request_t
const *request =
325 (audio_control_request_t
const *)p_request;
330 if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) {
331 bool rc = feature_unit_set_request(rhport, p_request, buf);
335 if (request->bEntityID == UAC2_ENTITY_CLOCK) {
336 bool rc = clock_set_request(rhport, p_request, buf);
343 "Set request not handled, entity = %d, selector = %d, request = %d",
344 request->bEntityID, request->bControlSelector, request->bRequest);
349 bool get_req_ep_cb(uint8_t rhport,
350 tusb_control_request_t
const *p_request)
override {
354 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
355 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
356 uint8_t ep = TU_U16_LOW(p_request->wIndex);
368 bool get_req_itf_cb(uint8_t rhport,
369 tusb_control_request_t
const *p_request)
override {
373 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
374 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
375 uint8_t itf = TU_U16_LOW(p_request->wIndex);
385 bool get_req_entity_cb(uint8_t rhport,
386 tusb_control_request_t
const *p_request)
override {
387 cfg.rh_port = rhport;
389 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
390 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
393 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
394 audio_control_request_t
const *request =
395 (audio_control_request_t
const *)p_request;
400 if (request->bEntityID == UAC2_ENTITY_CLOCK) {
401 bool rc = clock_get_request(rhport, p_request);
402 if (rc) debugWrite(6, LOW);
407 if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) {
408 bool rc = feature_unit_get_request(rhport, p_request);
409 if (rc) debugWrite(6, LOW);
414 if (entityID == UAC2_ENTITY_MIC_FEATURE_UNIT) {
415 bool rc = feature_unit_get_request(rhport, p_request);
416 if (rc) debugWrite(6, LOW);
421 if (entityID == UAC2_ENTITY_MIC_INPUT_TERMINAL ||
422 entityID == UAC2_ENTITY_SPK_INPUT_TERMINAL) {
424 case AUDIO_TE_CTRL_CONNECTOR: {
427 audio_desc_channel_cluster_t ret;
428 ret.bNrChannels = cfg.channels;
429 ret.bmChannelConfig = (audio_channel_config_t)0;
430 ret.iChannelNames = 0;
432 LOG_AUDIO_DEBUG(
" Get terminal connector");
434 bool rc = _api.tud_audio_buffer_and_schedule_control_xfer(
435 rhport, p_request, (
void *)&ret,
sizeof(ret));
436 if (rc) debugWrite(6, LOW);
442 LOG_AUDIO_DEBUG(
" Unsupported selector: %d", entityID);
448 LOG_AUDIO_DEBUG(
" Unsupported entity: %d", entityID);
453 bool tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in,
454 uint8_t cur_alt_setting)
override {
461 if (isMicrophone()) {
464 uint16_t len = getIOSize() - 2;
465 if (_out_buffer.size() < len) _out_buffer.resize(len);
468 if (_out_buffer.available() != 0) {
473 uint8_t *adr = _out_buffer.data();
475 int len_eff = (*cfg.p_read_callback)(adr, len, *
this);
476 _out_buffer.setAvailable(len_eff);
483 bool tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied,
484 uint8_t itf, uint8_t ep_in,
485 uint8_t cur_alt_setting)
override {
489 (void)cur_alt_setting;
492 if (isMicrophone()) {
494 uint8_t *adr = _out_buffer.data();
503 bool rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received,
504 uint8_t func_id, uint8_t ep_out,
505 uint8_t cur_alt_setting)
override {
507 if (isSpeaker() && _in_buffer.available() == 0) {
509 uint16_t len = _api.tud_audio_n_available(func_id);
511 if (_in_buffer.size() < len) _in_buffer.resize(len);
512 uint8_t *adr = _in_buffer.data();
513 int len_eff = _api.tud_audio_n_read(func_id, adr, len);
514 _in_buffer.setAvailable(len_eff);
522 bool rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received,
523 uint8_t func_id, uint8_t ep_out,
524 uint8_t cur_alt_setting)
override {
526 if (isSpeaker() && _in_buffer.available() > 0) {
528 uint8_t *adr = _in_buffer.data();
529 size_t rc = cfg.p_write_callback(adr, _in_buffer.available(), *
this);
530 _in_buffer.consume(rc);
536 bool set_itf_close_EP_cb(uint8_t rhport,
537 tusb_control_request_t
const *p_request)
override {
539 uint8_t
const itf = tu_u16_low(tu_le16toh(p_request->wIndex));
540 uint8_t
const alt = tu_u16_low(tu_le16toh(p_request->wValue));
541 if (alt == 0)
setStatus(AudioProcessingStatus::ACTIVE);
546 void feedback_params_cb(uint8_t func_id, uint8_t alt_itf,
551 feedback_param->method = AUDIO_FEEDBACK_METHOD_FIFO_COUNT;
552 feedback_param->sample_freq = cfg.sample_rate;
557 return getInterfaceDescriptor(
nullptr, 0);
561 uint16_t getInterfaceDescriptor(uint8_t *buf,
564 if (!isMicrophone() && !isSpeaker()) {
569 if (buf ==
nullptr && _desc_len > 0) {
574 if (_desc_len > 0 && bufsize < _desc_len) {
578 return interfaceDescriptor(buf, bufsize);
584 bool _is_led_setup =
true;
585 AudioProcessingStatus _processing_status = AudioProcessingStatus::INACTIVE;
586 std::vector<bool> _mute;
587 std::vector<uint16_t> _volume;
588 uint8_t _clk_is_valid =
true;
591 bool _led_active =
false;
592 uint64_t _led_timeout = 0;
595 uint8_t _itfnum_spk = 0;
596 uint8_t _itfnum_mic = 0;
597 uint8_t _itf_number_total = 0;
598 uint8_t _itfnum_ctl = 0;
605 int _desc_append_pos = 0;
609 Stream *p_stream =
nullptr;
610 Print *p_print =
nullptr;
613 std::vector<uint8_t> interface_descriptor;
622 for (
int j = 0; j < 8; j++) {
628 void append(uint8_t *to, uint8_t *str,
int len) {
629 if (to !=
nullptr) memcpy(to + _desc_append_pos, str, len);
630 _desc_append_pos += len;
633 static size_t defaultWriteCB(
const uint8_t *data,
size_t len,
635 Print *p_print = ref.p_print;
636 if (p_print)
return p_print->write((
const uint8_t *)data, len);
640 static size_t defaultReadCB(uint8_t *data,
size_t len,
USBDeviceAudio &ref) {
641 Stream *p_stream = ref.p_stream;
642 if (p_stream)
return p_stream->readBytes((uint8_t *)data, len);
647 virtual bool feature_unit_get_request(
648 uint8_t rhport, tusb_control_request_t
const *p_request) {
650 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
651 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
654 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
656 case AUDIO_FU_CTRL_MUTE: {
660 LOG_AUDIO_DEBUG(
" Get Mute of channel: %u", channelNum);
661 bool current_mute = _mute[channelNum];
662 bool rc = tud_control_xfer(rhport, p_request, ¤t_mute, 1);
663 _mute[channelNum] = current_mute;
667 case AUDIO_FU_CTRL_VOLUME:
668 switch (p_request->bRequest) {
669 case AUDIO_CS_REQ_CUR:
670 LOG_AUDIO_DEBUG(
" Get Volume of channel: %u", channelNum);
671 return tud_control_xfer(rhport, p_request, &_volume[channelNum],
672 sizeof(_volume[channelNum]));
674 case AUDIO_CS_REQ_RANGE:
675 LOG_AUDIO_DEBUG(
" Get Volume range of channel: %u", channelNum);
678 audio_control_range_2_n_t(1) ret;
680 ret.wNumSubRanges = 1;
681 ret.subrange[0].bMin = 0;
682 ret.subrange[0].bMax = 100;
683 ret.subrange[0].bRes = 1;
685 return _api.tud_audio_buffer_and_schedule_control_xfer(
686 rhport, p_request, (
void *)&ret, sizeof(ret));
703 virtual
bool feature_unit_set_request(uint8_t rhport,
704 tusb_control_request_t const *p_request,
705 uint8_t const *buf) {
707 audio_control_request_t
const *request =
708 (audio_control_request_t
const *)p_request;
711 TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR);
713 if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) {
714 TU_VERIFY(request->wLength ==
sizeof(audio_control_cur_1_t));
716 _mute[request->bChannelNumber] =
717 ((audio_control_cur_1_t
const *)buf)->bCur;
719 LOG_AUDIO_DEBUG(
"Set channel %d Mute: %d", request->bChannelNumber,
720 _mute[request->bChannelNumber]);
723 }
else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) {
724 TU_VERIFY(request->wLength ==
sizeof(audio_control_cur_2_t));
726 _volume[request->bChannelNumber] =
727 ((audio_control_cur_2_t
const *)buf)->bCur;
729 LOG_AUDIO_DEBUG(
"Set channel %d volume: %d dB", request->bChannelNumber,
730 _volume[request->bChannelNumber] / 256);
735 "Feature unit set request not supported, entity = %u, selector = %u, "
737 request->bEntityID, request->bControlSelector, request->bRequest);
742 virtual bool clock_get_request(uint8_t rhport,
743 tusb_control_request_t
const *p_request) {
744 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
745 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
748 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
750 case AUDIO_CS_CTRL_SAM_FREQ:
752 switch (p_request->bRequest) {
753 case AUDIO_CS_REQ_CUR:
754 LOG_AUDIO_DEBUG(
" Get Sample Freq. -> %d", cfg.sample_rate);
756 return _api.tud_audio_buffer_and_schedule_control_xfer(
757 rhport, p_request, &cfg.sample_rate,
sizeof(cfg.sample_rate));
759 case AUDIO_CS_REQ_RANGE:
760 LOG_AUDIO_DEBUG(
" Get Sample Freq. range -> %d - %d",
761 cfg.sample_rate, cfg.sample_rate);
762 audio_control_range_4_n_t(2) sampleFreqRng;
763 sampleFreqRng.wNumSubRanges = 1;
764 sampleFreqRng.subrange[0].bMin = cfg.sample_rate;
765 sampleFreqRng.subrange[0].bMax = cfg.sample_rate;
766 sampleFreqRng.subrange[0].bRes = 0;
770 return tud_control_xfer(rhport, p_request, &sampleFreqRng,
771 sizeof(sampleFreqRng));
780 case AUDIO_CS_CTRL_CLK_VALID:
782 LOG_AUDIO_DEBUG(" Get Sample Freq. valid");
783 return tud_control_xfer(rhport, p_request, &_clk_is_valid,
784 sizeof(_clk_is_valid));
793 virtual
bool clock_set_request(uint8_t rhport,
794 tusb_control_request_t const *p_request,
795 uint8_t const *buf) {
797 uint8_t channelNum = TU_U16_LOW(p_request->wValue);
798 uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
801 uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
806 if (ctrlSel == AUDIO_CS_CTRL_SAM_FREQ) {
807 TU_VERIFY(p_request->wLength ==
sizeof(audio_control_cur_4_t));
808 cfg.sample_rate = (uint32_t)((audio_control_cur_4_t
const *)buf)->bCur;
809 LOG_AUDIO_DEBUG(
"Clock set current freq: %ld", cfg.sample_rate);
813 "Clock set request not supported, entity = %u, selector = %u, "
816 entityID, ctrlSel, p_request->bRequest);
821 uint16_t interfaceDescriptor(uint8_t *buf, uint16_t bufsize) {
823 uint8_t feature_unit_len = getFeatureUnitLength();
824 _desc_append_pos = 0;
827 if (_desc_len == 0) {
828 _itf_number_total = 1;
829 _itfnum_ctl = allocInterface();
830 _ep_ctl = allocEndpoint(TUSB_DIR_IN);
834 if (isHeadset() && _desc_len == 0) {
835 _itfnum_mic = allocInterface();
836 _itfnum_spk = allocInterface();
837 _ep_mic = allocEndpoint(TUSB_DIR_IN);
838 _ep_int = allocEndpoint(TUSB_DIR_IN);
839 _ep_spk = allocEndpoint(TUSB_DIR_OUT);
840 _itf_number_total += 2;
841 }
else if (isMicrophone() && _desc_len == 0) {
842 _itfnum_mic = allocInterface();
843 _ep_mic = allocEndpoint(TUSB_DIR_IN);
845 }
else if (isSpeaker() && _desc_len == 0) {
846 _itfnum_spk = allocInterface();
847 _ep_spk = allocEndpoint(TUSB_DIR_OUT);
848 _ep_fb = allocEndpoint(TUSB_DIR_IN);
854 uint8_t total_len = TUD_AUDIO_DESC_CLK_SRC_LEN + feature_unit_len +
855 (2 * (TUD_AUDIO_DESC_INPUT_TERM_LEN +
856 TUD_AUDIO_DESC_OUTPUT_TERM_LEN));
857 interfaceDescriptorHeadset(buf, total_len);
858 }
else if (isMicrophone()) {
859 uint8_t total_len = TUD_AUDIO_DESC_CLK_SRC_LEN + feature_unit_len +
860 TUD_AUDIO_DESC_INPUT_TERM_LEN +
861 TUD_AUDIO_DESC_OUTPUT_TERM_LEN;
862 interfaceDescriptorMicrophone(buf, total_len);
863 }
else if (isSpeaker()) {
864 uint8_t total_len = TUD_AUDIO_DESC_CLK_SRC_LEN + feature_unit_len +
865 TUD_AUDIO_DESC_INPUT_TERM_LEN +
866 TUD_AUDIO_DESC_OUTPUT_TERM_LEN;
867 interfaceDescriptorSpeaker(buf, total_len);
871 if (_desc_len == 0) {
872 _desc_len = _desc_append_pos;
878 void interfaceDescriptorHeader(uint8_t *buf, uint8_t total_len,
881 uint8_t d1[] = {TUD_AUDIO_DESC_IAD( _itfnum_ctl,
884 append(buf, d1,
sizeof(d1));
887 uint8_t d2[] = {TUD_AUDIO_DESC_STD_AC( _itfnum_ctl,
889 append(buf, d2,
sizeof(d2));
892 uint8_t d3[] = {TUD_AUDIO_DESC_CS_AC(
893 0x0200, category, total_len,
894 AUDIO_CTRL_NONE << AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS)};
895 append(buf, d3,
sizeof(d3));
897 void interfaceDescriptorMicrophone(uint8_t *buf, uint8_t total_len) {
898 interfaceDescriptorHeader(buf, total_len, AUDIO_FUNC_MICROPHONE);
904 uint8_t d4[] = {TUD_AUDIO_DESC_CLK_SRC(
906 AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK,
907 (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS),
908 UAC2_ENTITY_MIC_INPUT_TERMINAL, 0x00)};
909 append(buf, d4,
sizeof(d4));
917 uint8_t d7[] = {TUD_AUDIO_DESC_INPUT_TERM(
918 UAC2_ENTITY_MIC_INPUT_TERMINAL,
919 UAC2_ENTITY_SPK_OUTPUT_TERMINAL,
920 UAC2_ENTITY_MIC_OUTPUT_TERMINAL,
921 UAC2_ENTITY_CLOCK, cfg.channels,
922 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED,
924 AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS,
926 append(buf, d7,
sizeof(d7));
931 uint8_t d8[] = {TUD_AUDIO_DESC_OUTPUT_TERM(
932 UAC2_ENTITY_MIC_OUTPUT_TERMINAL,
933 AUDIO_TERM_TYPE_USB_STREAMING,
934 UAC2_ENTITY_SPK_INPUT_TERMINAL,
935 UAC2_ENTITY_MIC_FEATURE_UNIT, UAC2_ENTITY_CLOCK,
937 append(buf, d8,
sizeof(d8));
955 uint8_t feature_unit_len = getFeatureUnitLength();
956 uint8_t df1[] = {feature_unit_len, TUSB_DESC_CS_INTERFACE,
957 AUDIO_CS_AC_INTERFACE_FEATURE_UNIT,
958 UAC2_ENTITY_MIC_FEATURE_UNIT,
959 UAC2_ENTITY_MIC_INPUT_TERMINAL};
960 append(buf, df1,
sizeof(df1));
961 for (
int j = 0; j < cfg.channels + 1; j++) {
963 U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS |
964 AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS)};
965 append(buf, df2,
sizeof(df2));
968 uint8_t df3[1] = {0x00};
969 append(buf, df3,
sizeof(df3));
977 uint8_t d15[] = {TUD_AUDIO_DESC_STD_AS_INT(
978 (uint8_t)(_itfnum_mic), 0x00, 0x00,
980 append(buf, d15,
sizeof(d15));
986 uint8_t d16[] = {TUD_AUDIO_DESC_STD_AS_INT(
987 (uint8_t)(_itfnum_mic), 0x01, 0x01,
989 append(buf, d16,
sizeof(d16));
996 uint8_t d17[] = {TUD_AUDIO_DESC_CS_AS_INT(
997 UAC2_ENTITY_MIC_OUTPUT_TERMINAL, AUDIO_CTRL_NONE,
999 AUDIO_DATA_FORMAT_TYPE_I_PCM,
1001 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, 0x00)};
1002 append(buf, d17,
sizeof(d17));
1006 uint8_t d18[] = {TUD_AUDIO_DESC_TYPE_I_FORMAT(
1007 (uint8_t)(cfg.bits_per_sample / 8), (uint8_t)cfg.bits_per_sample)};
1008 append(buf, d18,
sizeof(d18));
1015 uint8_t attr =
static_cast<uint8_t
>(TUSB_XFER_ISOCHRONOUS) |
1016 static_cast<uint8_t
>(TUSB_ISO_EP_ATT_ASYNCHRONOUS) |
1017 static_cast<uint8_t
>(TUSB_ISO_EP_ATT_DATA);
1018 uint8_t d19[] = {TUD_AUDIO_DESC_STD_AS_ISO_EP(
1019 _ep_mic, attr, getMaxEPSize(),
1021 append(buf, d19,
sizeof(d19));
1028 uint8_t d20[] = {TUD_AUDIO_DESC_CS_AS_ISO_EP(
1029 AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK,
1031 AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED,
1033 append(buf, d20,
sizeof(d20));
1036 void interfaceDescriptorSpeaker(uint8_t *buf, uint8_t total_len) {
1037 interfaceDescriptorHeader(buf, total_len, AUDIO_FUNC_DESKTOP_SPEAKER);
1043 uint8_t d4[] = {TUD_AUDIO_DESC_CLK_SRC(
1045 AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK,
1046 (AUDIO_CTRL_RW << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS),
1047 UAC2_ENTITY_SPK_INPUT_TERMINAL, 0x00)};
1048 append(buf, d4,
sizeof(d4));
1056 uint8_t d7[] = {TUD_AUDIO_DESC_INPUT_TERM(
1057 UAC2_ENTITY_SPK_INPUT_TERMINAL,
1058 AUDIO_TERM_TYPE_USB_STREAMING, 0x00,
1059 UAC2_ENTITY_CLOCK, cfg.channels,
1060 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED,
1062 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS),
1064 append(buf, d7,
sizeof(d7));
1070 uint8_t d8[] = {TUD_AUDIO_DESC_OUTPUT_TERM(
1071 UAC2_ENTITY_SPK_OUTPUT_TERMINAL,
1072 AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER,
1073 UAC2_ENTITY_SPK_INPUT_TERMINAL,
1074 UAC2_ENTITY_SPK_FEATURE_UNIT, UAC2_ENTITY_CLOCK,
1076 append(buf, d8,
sizeof(d8));
1103 uint8_t feature_unit_len = getFeatureUnitLength();
1104 uint8_t df1[] = {feature_unit_len, TUSB_DESC_CS_INTERFACE,
1105 AUDIO_CS_AC_INTERFACE_FEATURE_UNIT,
1106 UAC2_ENTITY_SPK_FEATURE_UNIT,
1107 UAC2_ENTITY_SPK_INPUT_TERMINAL};
1108 append(buf, df1,
sizeof(df1));
1109 for (
int j = 0; j < cfg.channels + 1; j++) {
1111 U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS |
1112 AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS)};
1113 append(buf, df2,
sizeof(df2));
1116 uint8_t df3[1] = {0x00};
1117 append(buf, df3,
sizeof(df3));
1124 uint8_t d15[] = {TUD_AUDIO_DESC_STD_AS_INT(
1125 (uint8_t)(_itfnum_spk), 0x00, 0x00,
1127 append(buf, d15,
sizeof(d15));
1132 uint8_t d16[] = {TUD_AUDIO_DESC_STD_AS_INT(
1133 (uint8_t)(_itfnum_spk), 0x01, 0x02,
1135 append(buf, d16,
sizeof(d16));
1140 uint8_t d17[] = {TUD_AUDIO_DESC_CS_AS_INT(
1141 UAC2_ENTITY_SPK_INPUT_TERMINAL, AUDIO_CTRL_NONE,
1142 AUDIO_FORMAT_TYPE_I,
1143 AUDIO_DATA_FORMAT_TYPE_I_PCM,
1145 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, 0x00)};
1146 append(buf, d17,
sizeof(d17));
1151 uint8_t d18[] = {TUD_AUDIO_DESC_TYPE_I_FORMAT(
1152 (uint8_t)(cfg.bits_per_sample / 8), (uint8_t)cfg.bits_per_sample)};
1153 append(buf, d18,
sizeof(d18));
1161 uint8_t d19[] = {TUD_AUDIO_DESC_STD_AS_ISO_EP(
1163 (uint8_t)((uint8_t)TUSB_XFER_ISOCHRONOUS |
1164 (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS |
1165 (uint8_t)TUSB_ISO_EP_ATT_DATA),
1166 getMaxEPSize(), 0x01)};
1167 append(buf, d19,
sizeof(d19));
1174 uint8_t d20[] = {TUD_AUDIO_DESC_CS_AS_ISO_EP(
1175 AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK,
1177 AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC,
1179 append(buf, d20,
sizeof(d20));
1184 uint8_t d21[] = {TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(
1186 TUD_OPT_HIGH_SPEED ? 4 : 1)};
1188 uint8_t d21[] = {TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(
1190 TUD_OPT_HIGH_SPEED ? 4 : 1)};
1192 append(buf, d21,
sizeof(d21));
1195 void interfaceDescriptorHeadset(uint8_t *buf, uint8_t total_len) {
1196 interfaceDescriptorHeader(buf, total_len, AUDIO_FUNC_HEADSET);
1201 uint8_t d1[] = {TUD_AUDIO_DESC_CLK_SRC(
1203 AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK, 7,
1205 append(buf, d1,
sizeof(d1));
1214 uint8_t d2[] = {TUD_AUDIO_DESC_INPUT_TERM(
1215 UAC2_ENTITY_SPK_INPUT_TERMINAL,
1216 AUDIO_TERM_TYPE_USB_STREAMING, 0x00,
1217 UAC2_ENTITY_CLOCK, cfg.channels,
1218 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED,
1220 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS),
1222 append(buf, d2,
sizeof(d2));
1233 uint8_t feature_unit_len = getFeatureUnitLength();
1234 uint8_t df1[] = {feature_unit_len, TUSB_DESC_CS_INTERFACE,
1235 AUDIO_CS_AC_INTERFACE_FEATURE_UNIT,
1236 UAC2_ENTITY_SPK_FEATURE_UNIT,
1237 UAC2_ENTITY_SPK_INPUT_TERMINAL};
1238 append(buf, df1,
sizeof(df1));
1240 for (
int j = 0; j < cfg.channels + 1; j++) {
1242 U32_TO_U8S_LE((AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS |
1243 AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS))};
1244 append(buf, df2,
sizeof(df2));
1247 uint8_t df3[1] = {0x00};
1248 append(buf, df3,
sizeof(df3));
1257 uint8_t d3[] = {TUD_AUDIO_DESC_OUTPUT_TERM(
1258 UAC2_ENTITY_SPK_OUTPUT_TERMINAL,
1259 AUDIO_TERM_TYPE_OUT_HEADPHONES, 00,
1260 UAC2_ENTITY_SPK_FEATURE_UNIT, UAC2_ENTITY_CLOCK,
1262 append(buf, d3,
sizeof(d3));
1271 uint8_t d4[] = {TUD_AUDIO_DESC_INPUT_TERM(
1272 UAC2_ENTITY_MIC_INPUT_TERMINAL,
1273 AUDIO_TERM_TYPE_IN_GENERIC_MIC, 00,
1274 UAC2_ENTITY_CLOCK, cfg.channels,
1275 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED,
1277 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS),
1279 append(buf, d4,
sizeof(d4));
1286 uint8_t d5[] = {TUD_AUDIO_DESC_OUTPUT_TERM(
1287 UAC2_ENTITY_MIC_OUTPUT_TERMINAL,
1288 AUDIO_TERM_TYPE_USB_STREAMING, 00,
1289 UAC2_ENTITY_MIC_INPUT_TERMINAL, UAC2_ENTITY_CLOCK,
1291 append(buf, d5,
sizeof(d5));
1296 TUD_AUDIO_DESC_STD_AC_INT_EP( _ep_int, 0x01)};
1297 append(buf, d6,
sizeof(d6));
1306 uint8_t d7[] = {TUD_AUDIO_DESC_STD_AS_INT(
1307 (uint8_t)(_itfnum_spk), 0x00, 0x00,
1309 append(buf, d7,
sizeof(d7));
1316 uint8_t d8[] = {TUD_AUDIO_DESC_STD_AS_INT(
1317 (uint8_t)(_itfnum_spk), 0x01, 0x01,
1319 append(buf, d8,
sizeof(d8));
1327 uint8_t d9[] = {TUD_AUDIO_DESC_CS_AS_INT(
1328 UAC2_ENTITY_SPK_INPUT_TERMINAL, AUDIO_CTRL_NONE,
1329 AUDIO_FORMAT_TYPE_I,
1330 AUDIO_DATA_FORMAT_TYPE_I_PCM,
1332 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, 0x00)};
1333 append(buf, d9,
sizeof(d9));
1338 uint8_t d10[] = {TUD_AUDIO_DESC_TYPE_I_FORMAT(
1339 (uint8_t)(cfg.bits_per_sample / 8), (uint8_t)cfg.bits_per_sample)};
1340 append(buf, d10,
sizeof(d10));
1349 uint8_t d11[] = {TUD_AUDIO_DESC_STD_AS_ISO_EP(
1351 (uint8_t)((uint8_t)TUSB_XFER_ISOCHRONOUS |
1352 (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE |
1353 (uint8_t)TUSB_ISO_EP_ATT_DATA),
1354 getMaxEPSize(), 0x01)};
1355 append(buf, d11,
sizeof(d11));
1362 uint8_t d12[] = {TUD_AUDIO_DESC_CS_AS_ISO_EP(
1363 AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK,
1365 AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC,
1367 append(buf, d12,
sizeof(d12));
1375 uint8_t d13[] = {TUD_AUDIO_DESC_STD_AS_INT(
1376 (uint8_t)(_itfnum_mic), 0x00, 0x00,
1378 append(buf, d13,
sizeof(d13));
1385 uint8_t d14[] = {TUD_AUDIO_DESC_STD_AS_INT(
1386 (uint8_t)(_itfnum_mic), 0x01, 0x01,
1388 append(buf, d14,
sizeof(d14));
1396 uint8_t d15[] = {TUD_AUDIO_DESC_CS_AS_INT(
1397 UAC2_ENTITY_MIC_OUTPUT_TERMINAL, AUDIO_CTRL_NONE,
1398 AUDIO_FORMAT_TYPE_I,
1399 AUDIO_DATA_FORMAT_TYPE_I_PCM,
1401 AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, 0x00)};
1402 append(buf, d15,
sizeof(d15));
1407 uint8_t d16[] = {TUD_AUDIO_DESC_TYPE_I_FORMAT(
1408 (uint8_t)(cfg.bits_per_sample / 8), (uint8_t)cfg.bits_per_sample)};
1409 append(buf, d16,
sizeof(d16));
1418 uint8_t d17[] = {TUD_AUDIO_DESC_STD_AS_ISO_EP(
1420 (uint8_t)((uint8_t)TUSB_XFER_ISOCHRONOUS |
1421 (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS |
1422 (uint8_t)TUSB_ISO_EP_ATT_DATA),
1423 getMaxEPSize(), 0x01)};
1424 append(buf, d17,
sizeof(d17));
1432 uint8_t d18[] = {TUD_AUDIO_DESC_CS_AS_ISO_EP(
1433 AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK,
1435 AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED,
1437 append(buf, d18,
sizeof(d18));
A resizable buffer of bytes which manages the available bytes.
Definition: USBDeviceAudio.h:64
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
void setupDebugPins()
Definition: USBDeviceAudio.h:619
AudioProcessingStatus status()
Provide the actual status.
Definition: USBDeviceAudio.h:225
void setWriteCallback(size_t(*write_cb)(const uint8_t *data, size_t len, USBDeviceAudio &ref))
Definition: USBDeviceAudio.h:111
void setStatus(AudioProcessingStatus status)
Define the led delay.
Definition: USBDeviceAudio.h:615
void setReadCallback(size_t(*read_cb)(uint8_t *data, size_t len, USBDeviceAudio &ref))
Definition: USBDeviceAudio.h:118
size_t getInterfaceDescriptorLength(uint8_t itfnum) override
Determine the interface descriptor length.
Definition: USBDeviceAudio.h:555
bool updateLED(int pin)
Call from loop to blink led.
Definition: USBDeviceAudio.h:199
void setOutput(Print &out)
Alternative to setWriteCallback.
Definition: USBDeviceAudio.h:124
void setInput(Stream &in)
Alternaive to setReadCallback.
Definition: USBDeviceAudio.h:130
Definition: USBDeviceAudioAPI.h:28