libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
uac_mic.hpp
1#pragma once
2#include <cstdint>
3#include <cstring>
4
5#include "core.hpp"
6#include "desc_cfg.hpp"
7#include "dev_core.hpp"
8#include "ep.hpp"
9#include "libxr_def.hpp"
10#include "libxr_mem.hpp"
11
12namespace LibXR::USB
13{
14
21template <uint8_t CHANNELS, uint8_t BITS_PER_SAMPLE>
23{
24 public:
25 static_assert(CHANNELS >= 1 && CHANNELS <= 8, "CHANNELS out of range");
26 static_assert(BITS_PER_SAMPLE == 8 || BITS_PER_SAMPLE == 16 || BITS_PER_SAMPLE == 24,
27 "BITS_PER_SAMPLE must be 8/16/24");
28 // AC / AS 接口对的默认字符串。
29 // Default interface strings for the AC / AS pair.
30 static constexpr const char* DEFAULT_CONTROL_INTERFACE_STRING = "XRUSB UAC1 Control";
31 static constexpr const char* DEFAULT_STREAMING_INTERFACE_STRING =
32 "XRUSB UAC1 Streaming";
33
34 private:
36 static const constexpr uint8_t K_SUBFRAME_SIZE = (BITS_PER_SAMPLE <= 8) ? 1
37 : (BITS_PER_SAMPLE <= 16) ? 2
38 : 3;
39 // 保守默认值:smoke 构造时固定暴露 0 dB,避免主机看到误导性的音量范围。
40 // Conservative smoke-safe defaults: expose fixed 0 dB gain by default.
41 static constexpr int16_t K_DEFAULT_VOL_MIN = 0;
42 static constexpr int16_t K_DEFAULT_VOL_MAX = 0;
43 static constexpr int16_t K_DEFAULT_VOL_RES = 1;
44 static constexpr Speed K_DEFAULT_SPEED = Speed::FULL;
45 static constexpr size_t K_DEFAULT_QUEUE_BYTES = 2048;
46 static constexpr uint8_t K_DEFAULT_INTERVAL = 1;
47
48 public:
65 uint32_t sample_rate_hz, int16_t vol_min = K_DEFAULT_VOL_MIN,
66 int16_t vol_max = K_DEFAULT_VOL_MAX, int16_t vol_res = K_DEFAULT_VOL_RES,
67 Speed speed = K_DEFAULT_SPEED, size_t queue_bytes = K_DEFAULT_QUEUE_BYTES,
68 uint8_t interval = K_DEFAULT_INTERVAL,
70 const char* control_interface_string = DEFAULT_CONTROL_INTERFACE_STRING,
71 const char* streaming_interface_string = DEFAULT_STREAMING_INTERFACE_STRING)
72 : iso_in_ep_num_(iso_in_ep_num),
73 vol_min_(vol_min),
74 vol_max_(vol_max),
75 vol_res_(vol_res),
76 interval_(interval),
77 speed_(speed),
78 sr_hz_(sample_rate_hz),
79 pcm_queue_(queue_bytes),
80 control_interface_string_(control_interface_string),
81 streaming_interface_string_(streaming_interface_string)
82 {
84 // 缓存端点采样率(3 字节小端) / Cache current sampling frequency (3‑byte LE)
85 sf_cur_[0] = static_cast<uint8_t>(sr_hz_ & 0xFF);
86 sf_cur_[1] = static_cast<uint8_t>((sr_hz_ >> 8) & 0xFF);
87 sf_cur_[2] = static_cast<uint8_t>((sr_hz_ >> 16) & 0xFF);
88 }
89
90 const char* GetInterfaceString(size_t local_interface_index) const override
91 {
92 // UAC 麦克风暴露 AC + AS 两个接口。
93 // The UAC microphone exposes AC + AS interfaces.
94 switch (local_interface_index)
95 {
96 case 0:
98 case 1:
100 default:
101 return nullptr;
102 }
103 }
104
105 // ===== 生产者接口 / Producer‑side API =====
110 ErrorCode WritePcm(const void* data, size_t nbytes)
111 {
112 return pcm_queue_.PushBatch(reinterpret_cast<const uint8_t*>(data), nbytes);
113 }
115 size_t QueueSize() const { return pcm_queue_.Size(); }
117 size_t QueueSpace() { return pcm_queue_.EmptySize(); }
119 void ResetQueue() { pcm_queue_.Reset(); }
120
121 // ===== UAC1 常量 / UAC1 constants =====
122 enum : uint8_t
123 {
124 USB_CLASS_AUDIO = 0x01,
125 SUBCLASS_AC = 0x01,
126 SUBCLASS_AS = 0x02
127 };
128 enum : uint8_t
129 {
130 CS_INTERFACE = 0x24,
131 CS_ENDPOINT = 0x25
132 };
133 enum : uint8_t
134 {
135 AC_HEADER = 0x01,
136 AC_INPUT_TERMINAL = 0x02,
137 AC_OUTPUT_TERMINAL = 0x03,
138 AC_FEATURE_UNIT = 0x06
139 };
140 enum : uint8_t
141 {
142 AS_GENERAL = 0x01,
143 AS_FORMAT_TYPE = 0x02
144 };
145 enum : uint8_t
146 {
147 EP_GENERAL = 0x01
148 };
149 enum : uint16_t
150 {
151 WFORMAT_PCM = 0x0001,
152 WFORMAT_UNKNOWN = 0xFFFF
153 };
154 enum : uint8_t
155 {
156 FORMAT_TYPE_I = 0x01
157 };
158
159 // UAC1 类请求 / Class‑specific requests
160 enum : uint8_t
161 {
162 SET_CUR = 0x01,
163 GET_CUR = 0x81,
164 SET_MIN = 0x02,
165 GET_MIN = 0x82,
166 SET_MAX = 0x03,
167 GET_MAX = 0x83,
168 SET_RES = 0x04,
169 GET_RES = 0x84
170 };
171 enum : uint8_t
172 {
173 FU_MUTE = 0x01,
174 FU_VOLUME = 0x02
175 };
176
177 // 实体 ID / Entity IDs
178 enum : uint8_t
179 {
180 ID_IT_MIC = 1,
181 ID_FU = 2,
182 ID_OT_USB = 3
183 };
184
185#pragma pack(push, 1)
191 {
192 uint8_t bLength = 9, bDescriptorType = CS_INTERFACE, bDescriptorSubtype = AC_HEADER;
193 uint16_t bcdADC = 0x0100, wTotalLength = 0;
194 uint8_t bInCollection = 1, baInterfaceNr = 0;
195 };
196
202 {
203 uint8_t bLength = 12, bDescriptorType = CS_INTERFACE,
204 bDescriptorSubtype = AC_INPUT_TERMINAL;
205 uint8_t bTerminalID = ID_IT_MIC;
206 uint16_t wTerminalType = 0x0201; // 麦克风 / Microphone
207 uint8_t bAssocTerminal = 0, bNrChannels = CHANNELS;
208 uint16_t wChannelConfig = 0x0000; // 根据 CHANNELS 设定 / Set per CHANNELS
209 uint8_t iChannelNames = 0, iTerminal = 0;
210 };
211
217 {
218 uint8_t bLength = static_cast<uint8_t>(7 + (CHANNELS + 1) * 1);
219 uint8_t bDescriptorType = CS_INTERFACE, bDescriptorSubtype = AC_FEATURE_UNIT;
220 uint8_t bUnitID = ID_FU, bSourceID = ID_IT_MIC, bControlSize = 1;
221 uint8_t bmaControlsMaster = 0x03; // 静音 + 音量 / Mute + Volume
222 uint8_t bmaControlsCh[CHANNELS] = {0x03}; // 每通道支持 / Per-channel supported
223 uint8_t iFeature = 0;
224 };
225
231 {
232 uint8_t bLength = 9, bDescriptorType = CS_INTERFACE,
233 bDescriptorSubtype = AC_OUTPUT_TERMINAL;
234 uint8_t bTerminalID = ID_OT_USB;
235 uint16_t wTerminalType = 0x0101; // USB 流 / USB Streaming
236 uint8_t bAssocTerminal = 0, bSourceID = ID_FU, iTerminal = 0;
237 };
238
244 {
245 uint8_t bLength = 7, bDescriptorType = CS_INTERFACE, bDescriptorSubtype = AS_GENERAL;
246 uint8_t bTerminalLink = ID_OT_USB, bDelay = 1;
247 uint16_t wFormatTag = WFORMAT_PCM;
248 };
249
255 {
256 uint8_t bLength = 11, bDescriptorType = CS_INTERFACE,
257 bDescriptorSubtype = AS_FORMAT_TYPE;
258 uint8_t bFormatType = FORMAT_TYPE_I, bNrChannels = CHANNELS;
259 uint8_t bSubframeSize = K_SUBFRAME_SIZE, bBitResolution = BITS_PER_SAMPLE,
260 bSamFreqType = 1;
261 uint8_t tSamFreq[3]; // 运行期填充 / Filled at runtime
262 };
263
269 {
270 uint8_t bLength = 7, bDescriptorType = CS_ENDPOINT, bDescriptorSubtype = EP_GENERAL;
271 uint8_t bmAttributes = 0x00;
272 uint8_t bLockDelayUnits = 0;
273 uint16_t wLockDelay = 0;
274 };
275
281 {
282 uint8_t bLength = 9;
283 uint8_t bDescriptorType = static_cast<uint8_t>(DescriptorType::ENDPOINT);
284 uint8_t bEndpointAddress = 0; // 含方向位 / includes direction bit
285 uint8_t bmAttributes = 0x05; // Isochronous + Async + Data
286 uint16_t wMaxPacketSize = 0; // 运行期填充 / filled at runtime
287 uint8_t bInterval = 0x01; // 1 ms
288 uint8_t bRefresh = 0x00; // 仅反馈端点使用 / feedback only
289 uint8_t bSynchAddress = 0x00; // 无伴随端点 / no sync/feedback ep
290 };
291
311#pragma pack(pop)
312
313 // ===== DeviceClass 接口实现 / DeviceClass implementation =====
321 void BindEndpoints(EndpointPool& endpoint_pool, uint8_t start_itf_num, bool) override
322 {
323 inited_ = false;
324 streaming_ = false;
325 acc_rem_ = 0;
326
327 if (speed_ == Speed::HIGH)
328 {
329 ASSERT(w_max_packet_size_ <= 1024);
330 }
331 else
332 {
333 ASSERT(interval_ == 1);
334 ASSERT(w_max_packet_size_ <= 1023);
335 }
336
337 // 这里只分配端点,不立即开启;真正开启放在 AS Alt=1 切换时。
338 // Allocate the endpoint here without starting transfers;
339 // actual streaming begins when AS Alt=1 is selected.
340 auto ans = endpoint_pool.Get(ep_iso_in_, Endpoint::Direction::IN, iso_in_ep_num_);
341 ASSERT(ans == ErrorCode::OK);
342
344 static_cast<uint16_t>(w_max_packet_size_), true});
345
346 itf_ac_num_ = start_itf_num;
347 itf_as_num_ = static_cast<uint8_t>(start_itf_num + 1);
348
349 // IAD(把 AC + AS 这组接口关联成一个音频功能)
350 // IAD for grouping the AC + AS interfaces into one audio function.
351 desc_block_.iad = {8,
352 static_cast<uint8_t>(DescriptorType::IAD),
353 itf_ac_num_,
354 2,
355 USB_CLASS_AUDIO,
356 SUBCLASS_AC,
357 0x00,
358 0};
359
360 // AC 接口(标准接口)
361 desc_block_.ac_intf = {9,
362 static_cast<uint8_t>(DescriptorType::INTERFACE),
363 itf_ac_num_,
364 0,
365 0,
366 USB_CLASS_AUDIO,
367 SUBCLASS_AC,
368 0x00,
370
371 // AC Header(声明 AC 类描述符块总长)
372 // AC header describing the total AC class-specific descriptor size.
373 desc_block_.ac_hdr.baInterfaceNr = itf_as_num_;
374 desc_block_.ac_hdr.wTotalLength =
375 static_cast<uint16_t>(sizeof(CSACHeader) + sizeof(ACInputTerminal) +
376 sizeof(ACFeatureUnit) + sizeof(ACOutputTerminal));
377
378 // AC Input Terminal 的 wChannelConfig 按通道数设置。
379 // Program the AC Input Terminal wChannelConfig from the channel count.
380 if constexpr (CHANNELS == 2)
381 {
382 desc_block_.it_mic.wChannelConfig = 0x0003; // Left Front | Right Front
383 }
384 else
385 {
386 desc_block_.it_mic.wChannelConfig = 0x0000; // 未声明或单声道 / unspecified or mono
387 }
388
389 // AS Alt 0:空闲态,不暴露数据端点。
390 // AS Alt 0: idle alternate setting with no data endpoint.
391 desc_block_.as_alt0 = {9,
392 static_cast<uint8_t>(DescriptorType::INTERFACE),
393 itf_as_num_,
394 0,
395 0,
396 USB_CLASS_AUDIO,
397 SUBCLASS_AS,
398 0x00,
400
401 // AS Alt 1:工作态,暴露 1 个 Iso IN 端点。
402 // AS Alt 1: active streaming alternate setting with one Iso IN endpoint.
403 desc_block_.as_alt1 = {9,
404 static_cast<uint8_t>(DescriptorType::INTERFACE),
405 itf_as_num_,
406 1,
407 1,
408 USB_CLASS_AUDIO,
409 SUBCLASS_AS,
410 0x00,
412
413 // AS General(把 AS 接口绑定到 USB 输出端子)
414 // AS general descriptor linking the AS interface to the USB output terminal.
415 desc_block_.as_gen = {};
416 desc_block_.as_gen.bTerminalLink = ID_OT_USB;
417 desc_block_.as_gen.bDelay = 1;
418 desc_block_.as_gen.wFormatTag = WFORMAT_PCM;
419
420 // Type I Format:当前实现只暴露一个离散采样率。
421 // Type I format descriptor: the current implementation exposes one discrete rate.
422 desc_block_.fmt.bFormatType = FORMAT_TYPE_I;
423 desc_block_.fmt.bNrChannels = CHANNELS;
424 desc_block_.fmt.bSubframeSize = K_SUBFRAME_SIZE;
425 desc_block_.fmt.bBitResolution = BITS_PER_SAMPLE;
426 desc_block_.fmt.bSamFreqType = 1;
427 desc_block_.fmt.tSamFreq[0] = static_cast<uint8_t>(sr_hz_ & 0xFF);
428 desc_block_.fmt.tSamFreq[1] = static_cast<uint8_t>((sr_hz_ >> 8) & 0xFF);
429 desc_block_.fmt.tSamFreq[2] = static_cast<uint8_t>((sr_hz_ >> 16) & 0xFF);
430
431 // 标准 ISO IN 端点(9 字节,含 bRefresh/bSynchAddress)
432 // Standard 9-byte ISO IN endpoint descriptor, including refresh/sync fields.
433 desc_block_.ep_in = {};
434 desc_block_.ep_in.bEndpointAddress = static_cast<uint8_t>(
436 desc_block_.ep_in.bmAttributes = 0x05;
437 desc_block_.ep_in.wMaxPacketSize = static_cast<uint16_t>(w_max_packet_size_);
438 desc_block_.ep_in.bInterval = (speed_ == Speed::HIGH) ? interval_ : 0x01;
439 desc_block_.ep_in.bRefresh = 0x00;
440 desc_block_.ep_in.bSynchAddress = 0x00;
441
442 desc_block_.ep_cs = {};
443 desc_block_.ep_cs.bmAttributes = 0x00;
444 // IN 传输完成后继续投下一帧。
445 // Kick the next frame after each IN transfer completes.
446 ep_iso_in_->SetOnTransferCompleteCallback(on_in_complete_cb_);
447
448 // 把整块描述符数据交给 DeviceClass。
449 // Publish the full descriptor block to DeviceClass.
450 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_block_), sizeof(desc_block_)});
451
452 inited_ = true;
453 }
454
462 void UnbindEndpoints(EndpointPool& endpoint_pool, bool) override
463 {
464 streaming_ = false;
465 inited_ = false;
466 if (ep_iso_in_)
467 {
468 ep_iso_in_->Close();
469 ep_iso_in_->SetActiveLength(0);
470 endpoint_pool.Release(ep_iso_in_);
471 ep_iso_in_ = nullptr;
472 }
473 }
474
479 ErrorCode OnGetDescriptor(bool, uint8_t, uint16_t, uint16_t, ConstRawData&) override
480 {
482 }
483
488 ErrorCode OnClassRequest(bool /*in_isr*/, uint8_t bRequest, uint16_t wValue,
489 uint16_t wLength, uint16_t wIndex,
491 {
492 // ===== 端点采样率控制(收件人:端点地址) / EP sampling‑freq control =====
493 const uint8_t EP_ADDR = static_cast<uint8_t>(wIndex & 0xFF);
494 const uint8_t CS_EP =
495 static_cast<uint8_t>((wValue >> 8) & 0xFF); // 0x01 = 采样率 / Sampling Freq
496
497 if (EP_ADDR == desc_block_.ep_in.bEndpointAddress && CS_EP == 0x01)
498 {
499 switch (bRequest)
500 {
501 case GET_CUR:
502 if (wLength == 3)
503 {
504 r.write_data = ConstRawData{sf_cur_, 3};
505 return ErrorCode::OK;
506 }
507 break;
508 case SET_CUR:
509 if (wLength == 3)
510 {
511 pending_set_sf_ = true;
512 r.read_data = RawData{sf_cur_, 3};
513 return ErrorCode::OK;
514 }
515 break;
516 case GET_MIN:
517 case GET_MAX:
518 if (wLength == 3)
519 {
520 r.write_data = ConstRawData{sf_cur_, 3};
521 return ErrorCode::OK;
522 } // 单一频点 / single discrete rate
523 break;
524 case GET_RES:
525 {
526 static uint8_t one_hz[3] = {1, 0, 0};
527 if (wLength == 3)
528 {
529 r.write_data = ConstRawData{one_hz, 3};
530 return ErrorCode::OK;
531 }
532 break;
533 }
534 default:
535 break;
536 }
537 ASSERT(false);
538 return ErrorCode::ARG_ERR; // 长度不符等 / length mismatch, etc.
539 }
540
541 // ===== Feature Unit(收件人:Interface / AC 接口) / Feature Unit =====
542 const uint8_t CS = static_cast<uint8_t>((wValue >> 8) & 0xFF); // FU_MUTE / FU_VOLUME
543 const uint8_t CH = static_cast<uint8_t>(wValue & 0xFF); // 0=主控, 1..N / 0=master, 1..N
544 const uint8_t ENT =
545 static_cast<uint8_t>((wIndex >> 8) & 0xFF); // 实体 ID / entity ID
546 const uint8_t ITF = static_cast<uint8_t>(wIndex & 0xFF); // 接口号 / interface num
547
548 if (ITF != itf_ac_num_ || ENT != ID_FU)
549 {
550 ASSERT(false);
552 }
553 if (CH > CHANNELS)
554 {
555 ASSERT(false);
556 return ErrorCode::ARG_ERR;
557 }
558
559 switch (CS)
560 {
561 case FU_MUTE:
562 if (bRequest == SET_CUR && wLength == 1)
563 {
564 r.read_data = RawData{&mute_, 1};
565 return ErrorCode::OK;
566 }
567 if (bRequest == GET_CUR && wLength == 1)
568 {
569 r.write_data = ConstRawData{&mute_, 1};
570 return ErrorCode::OK;
571 }
572 ASSERT(false);
573 return ErrorCode::ARG_ERR;
574
575 case FU_VOLUME:
576 switch (bRequest)
577 {
578 case SET_CUR:
579 if (wLength == 2)
580 {
581 r.read_data = RawData{reinterpret_cast<uint8_t*>(&vol_cur_), 2};
582 return ErrorCode::OK;
583 }
584 break;
585 case GET_CUR:
586 if (wLength == 2)
587 {
588 r.write_data = ConstRawData{reinterpret_cast<uint8_t*>(&vol_cur_), 2};
589 return ErrorCode::OK;
590 }
591 break;
592 case GET_MIN:
593 if (wLength == 2)
594 {
595 r.write_data = ConstRawData{reinterpret_cast<const uint8_t*>(&vol_min_), 2};
596 return ErrorCode::OK;
597 }
598 break;
599 case GET_MAX:
600 if (wLength == 2)
601 {
602 r.write_data = ConstRawData{reinterpret_cast<const uint8_t*>(&vol_max_), 2};
603 return ErrorCode::OK;
604 }
605 break;
606 case GET_RES:
607 if (wLength == 2)
608 {
609 r.write_data = ConstRawData{reinterpret_cast<const uint8_t*>(&vol_res_), 2};
610 return ErrorCode::OK;
611 }
612 break;
613 case SET_RES: // 吃下以避免 STALL / accept to avoid STALL
614 if (wLength == 2)
615 {
616 r.read_data = RawData{reinterpret_cast<uint8_t*>(&vol_res_), 2};
617 return ErrorCode::OK;
618 }
619 default:
620 break;
621 }
622 ASSERT(false);
623 return ErrorCode::ARG_ERR;
624
625 default:
626 ASSERT(false);
628 }
629 }
630
635 ErrorCode OnClassData(bool /*in_isr*/, uint8_t bRequest,
636 LibXR::ConstRawData& /*data*/) override
637 {
638 if (bRequest == SET_CUR && pending_set_sf_)
639 {
640 const uint32_t NEW_SR = static_cast<uint32_t>(sf_cur_[0]) |
641 (static_cast<uint32_t>(sf_cur_[1]) << 8) |
642 (static_cast<uint32_t>(sf_cur_[2]) << 16);
643 if (NEW_SR > 0 && NEW_SR != sr_hz_)
644 {
645 sr_hz_ = NEW_SR;
647 }
648 pending_set_sf_ = false;
649 return ErrorCode::OK;
650 }
651 return ErrorCode::OK;
652 }
653
658 ErrorCode GetAltSetting(uint8_t itf, uint8_t& alt) override
659 {
660 if (itf != itf_as_num_)
661 {
662 ASSERT(false);
664 }
665 alt = streaming_ ? 1 : 0;
666 return ErrorCode::OK;
667 }
668
673 ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
674 {
675 if (itf != itf_as_num_)
676 {
677 ASSERT(false);
679 }
680 if (!ep_iso_in_)
681 {
682 ASSERT(false);
683 return ErrorCode::FAILED;
684 }
685
686 switch (alt)
687 {
688 case 0: // Alt 0:无端点 / Alt 0: no endpoint
689 streaming_ = false;
690 ep_iso_in_->SetActiveLength(0);
691 ep_iso_in_->Close();
692 return ErrorCode::OK;
693
694 case 1: // Alt 1:一个 Iso IN 端点 / Alt 1: one Iso IN endpoint
696 static_cast<uint16_t>(w_max_packet_size_), false});
697 ep_iso_in_->SetActiveLength(0);
698 acc_rem_ = 0; // 重置余数累加器 / reset remainder accumulator
699 streaming_ = true;
700 KickOneFrame();
701 return ErrorCode::OK;
702
703 default:
704 ASSERT(false);
705 return ErrorCode::ARG_ERR;
706 }
707 }
708
710 size_t GetInterfaceCount() override { return 2; }
712 bool HasIAD() override { return true; }
714 size_t GetMaxConfigSize() override { return sizeof(UAC1DescBlock); }
715
716 bool OwnsEndpoint(uint8_t ep_addr) const override
717 {
718 if (!inited_)
719 {
720 return false;
721 }
722 return ep_iso_in_->GetAddress() == ep_addr;
723 }
724
725 private:
726 // ===== 端点传输 / Endpoint transfers =====
731 static void OnInCompleteStatic(bool in_isr, UAC1MicrophoneQ* self, ConstRawData& data)
732 {
733 if (!self->inited_)
734 {
735 return;
736 }
737 self->OnInComplete(in_isr, data);
738 }
739
745 {
746 if (!streaming_)
747 {
748 return;
749 }
750 KickOneFrame();
751 }
752
758 {
759 if (!streaming_)
760 {
761 return; // 仅 Alt=1 允许 / Only allowed at Alt=1
762 }
763 if (!ep_iso_in_ || ep_iso_in_->GetState() != Endpoint::State::IDLE)
764 {
765 return;
766 }
767
768 // 本帧应发送字节数 = floor + 余数累加决定是否 +1。
769 // Bytes sent this frame = floor(bytes/service) plus one when remainder carries.
770 uint16_t to_send = static_cast<uint16_t>(base_bytes_per_service_);
771 acc_rem_ += rem_bytes_per_service_;
772 if (acc_rem_ >= service_hz_)
773 {
774 ++to_send;
775 acc_rem_ -= service_hz_;
776 }
777
778 if (to_send > w_max_packet_size_)
779 {
780 to_send = static_cast<uint16_t>(w_max_packet_size_);
781 }
782
783 auto buf = ep_iso_in_->GetBuffer();
784 if (buf.size_ < to_send)
785 {
786 to_send = static_cast<uint16_t>(buf.size_);
787 }
788
789 // 从队列取可用字节 / pop available bytes from queue
790 size_t have = pcm_queue_.Size();
791 size_t take = (have >= to_send) ? to_send : have;
792
793 if (take)
794 {
795 pcm_queue_.PopBatch(reinterpret_cast<uint8_t*>(buf.addr_), take);
796 }
797 if (take < to_send)
798 {
799 LibXR::Memory::FastSet(static_cast<uint8_t*>(buf.addr_) + take, 0, to_send - take);
800 }
801
802 ep_iso_in_->Transfer(to_send);
803 }
804
810 {
811 // 1) 计算每秒服务次数(FS=1000Hz;HS=8000/2^(bInterval-1))。
812 // 1) Compute service frequency (FS=1000Hz; HS=8000/2^(bInterval-1)).
813 if (speed_ == Speed::HIGH)
814 {
815 uint8_t eff = interval_ ? interval_ : 1;
816 if (eff > 16)
817 {
818 eff = 16;
819 }
820 const uint32_t MICROFRAMES = 1u << (eff - 1u); // 2^(bInterval-1) 个微帧 / microframes
821 service_hz_ = 8000u / MICROFRAMES; // 8000 微帧/秒 / microframes per second
822 }
823 else
824 {
825 service_hz_ = 1000u; // FS 等时:规范上 bInterval 必须为 1 帧 / FS isochronous requires bInterval=1
826 }
827
828 // 2) 计算每服务周期应送字节。
829 // 2) Compute the target bytes per service interval.
830 bytes_per_sec_ = static_cast<uint32_t>(sr_hz_) * CHANNELS * K_SUBFRAME_SIZE;
831 base_bytes_per_service_ = bytes_per_sec_ / service_hz_;
832 rem_bytes_per_service_ = bytes_per_sec_ % service_hz_;
833 uint32_t ceil_bpt = base_bytes_per_service_ + (rem_bytes_per_service_ ? 1u : 0u);
834
835 // 3) 钳制每事务上限(FS 1023,HS 1024;此处只做单事务上限,未用 HS multiplier)。
836 // 3) Clamp the per-transaction limit (FS 1023, HS 1024; no HS multiplier here).
837 const uint32_t PER_TX_LIMIT = (speed_ == Speed::HIGH) ? 1024u : 1023u;
838 if (ceil_bpt > PER_TX_LIMIT)
839 {
840 ceil_bpt = PER_TX_LIMIT;
841 }
842
843 w_max_packet_size_ = static_cast<uint16_t>(ceil_bpt);
844
845 // 4) 若已构建过描述符,则运行时能力不得超过宣告值。
846 // 4) Once descriptors are built, runtime capability must not exceed the advertised value.
847 if (desc_block_.ep_in.wMaxPacketSize != 0 &&
848 w_max_packet_size_ > desc_block_.ep_in.wMaxPacketSize)
849 {
850 w_max_packet_size_ = desc_block_.ep_in.wMaxPacketSize;
851 }
852 }
853
854 // 端点与接口状态。
855 // Endpoint and interface state.
856 Endpoint::EPNumber iso_in_ep_num_;
857 Endpoint* ep_iso_in_ = nullptr;
858 uint8_t itf_ac_num_ = 0;
859 uint8_t itf_as_num_ = 0;
861 nullptr;
863 nullptr;
864
865 // 运行态状态。
866 // Runtime state.
867 bool inited_ = false;
868 bool streaming_ = false;
869
870 // 音量与静音状态。
871 // Volume and mute state.
872 uint8_t mute_ = 0;
873 int16_t vol_cur_ = 0; // 0 dB / 0 dB
874 int16_t vol_min_, vol_max_, vol_res_;
875
876 uint8_t interval_;
877 Speed speed_;
878
879 // 采样与分帧参数。
880 // Sampling and framing parameters.
881 uint32_t sr_hz_;
882 uint32_t bytes_per_sec_ = 0;
883 uint32_t base_bytes_per_service_ = 0;
884 uint32_t rem_bytes_per_service_ = 0;
885 uint32_t acc_rem_ = 0; // 0..999 / fixed-point remainder accumulator
886 uint16_t w_max_packet_size_ = 0;
887 uint32_t service_hz_ = 1000;
888
889 UAC1DescBlock desc_block_;
890
891 // 端点采样率缓存(Hz,小端 3 字节)与状态。
892 // Endpoint sampling-frequency cache (3-byte LE) and flags.
893 uint8_t sf_cur_[3] = {0, 0, 0};
894 bool pending_set_sf_ = false;
895
896 // PCM 字节队列。
897 // PCM byte queue.
899
900 // 端点回调包装。
901 // Endpoint callback wrapper.
902 LibXR::Callback<LibXR::ConstRawData&> on_in_complete_cb_ =
904};
905
906} // namespace LibXR::USB
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:142
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:159
常量原始数据封装类。 A class for encapsulating constant raw data.
无锁队列实现 / Lock-free queue implementation
void Reset()
重置队列 / Resets the queue
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
size_t EmptySize()
计算队列剩余可用空间 / Calculates the remaining available space in the queue
size_t Size() const
获取当前队列中的元素数量 / Returns the number of elements currently in the queue
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
原始数据封装类。 A class for encapsulating raw data.
void SetData(RawData data)
设置内部数据缓存 / Set internal data cache
Definition desc_cfg.hpp:193
USB 设备类接口基类 / USB device class interface base.
uint8_t GetInterfaceStringIndex(size_t local_interface_index) const
返回已分配的接口字符串索引 Return the assigned USB string index for a local interface.
USB 端点基类 / USB Endpoint base class.
Definition ep.hpp:24
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
@ EP_AUTO
自动分配端点号 / Auto allocate
uint8_t GetAddress() const
获取端点地址(方向 + 号) / Get endpoint address (dir + num)
Definition ep.hpp:195
@ IN
输入方向 / IN direction
static constexpr uint8_t EPNumberToAddr(EPNumber ep, Direction dir)
端点号转换为端点地址 / Convert endpoint number to endpoint address
Definition ep.hpp:105
void SetActiveLength(uint16_t len)
设置当前活动缓冲区有效长度 / Set active buffer valid length
Definition ep.hpp:271
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
Definition ep.hpp:262
virtual void Configure(const Config &cfg)=0
配置端点协议参数 / Configure endpoint protocol parameters
@ ISOCHRONOUS
等时端点 / Isochronous
EPNumber GetNumber() const
获取端点号 / Get endpoint number
Definition ep.hpp:170
virtual void Close()=0
关闭端点 / Close endpoint
State GetState() const
获取端点状态 / Get endpoint state
Definition ep.hpp:208
virtual ErrorCode Transfer(size_t size)=0
启动一次传输 / Start a transfer
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
Definition ep.hpp:246
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
ErrorCode Get(Endpoint *&ep_info, Endpoint::Direction direction, Endpoint::EPNumber ep_num=Endpoint::EPNumber::EP_AUTO)
分配端点 / Allocate endpoint
Definition ep_pool.cpp:11
ErrorCode Release(Endpoint *ep_info)
回收端点 / Release endpoint
Definition ep_pool.cpp:37
UAC1 队列式麦克风设备类实现 UAC1 queue‑driven microphone device class implementation.
Definition uac_mic.hpp:23
size_t GetInterfaceCount() override
返回接口数量(AC+AS=2) / Get number of interfaces (AC+AS=2)
Definition uac_mic.hpp:710
void RecomputeTiming()
统一重算时序与包长(运行时 MPS 钳制到描述符宣告值) Recompute timing and packet sizing (runtime MPS clamped to descriptor)
Definition uac_mic.hpp:809
ErrorCode OnClassRequest(bool, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, DeviceClass::ControlTransferResult &r) override
处理类请求:端点采样率控制 + Feature Unit(静音/音量) Handle class requests: EP sampling‑freq control + Feature Unit (m...
Definition uac_mic.hpp:488
ErrorCode OnGetDescriptor(bool, uint8_t, uint16_t, uint16_t, ConstRawData &) override
UAC1 无类特定描述符读出(配置中已包含) UAC1 does not use GET_DESCRIPTOR(0x21/0x22) here.
Definition uac_mic.hpp:479
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化设备,释放端点 Deinitialize device and release endpoints
Definition uac_mic.hpp:462
const char * streaming_interface_string_
流接口字符串 / Streaming interface string
Definition uac_mic.hpp:862
static const constexpr uint8_t K_SUBFRAME_SIZE
每通道每采样的子帧字节数 / Subframe size (bytes per channel per sample)
Definition uac_mic.hpp:36
bool HasIAD() override
包含 IAD / Has IAD
Definition uac_mic.hpp:712
size_t QueueSpace()
获取队列剩余空间 / Get remaining queue capacity (bytes)
Definition uac_mic.hpp:117
const char * control_interface_string_
控制接口字符串 / Control interface string
Definition uac_mic.hpp:860
size_t GetMaxConfigSize() override
配置描述符最大尺寸 / Get maximum configuration size
Definition uac_mic.hpp:714
void KickOneFrame()
计算并投递一帧(按 1ms 变包 + 零填充) Compute and submit one frame (1 ms variable size + zero fill)
Definition uac_mic.hpp:757
bool OwnsEndpoint(uint8_t ep_addr) const override
可选:端点归属判定 / Optional: endpoint ownership
Definition uac_mic.hpp:716
static void OnInCompleteStatic(bool in_isr, UAC1MicrophoneQ *self, ConstRawData &data)
IN 传输完成静态回调 Static callback for IN transfer completion.
Definition uac_mic.hpp:731
void OnInComplete(bool, ConstRawData &)
IN 传输完成处理:继续投下一帧 Handle IN transfer completion: kick next frame.
Definition uac_mic.hpp:744
void ResetQueue()
重置队列为空 / Reset queue to empty
Definition uac_mic.hpp:119
ErrorCode OnClassData(bool, uint8_t bRequest, LibXR::ConstRawData &) override
处理类请求数据阶段(应用 SET_CUR 的采样率) Handle class request data stage (apply SET_CUR sampling freq)
Definition uac_mic.hpp:635
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化设备(分配端点、填充描述符) Initialize device (allocate endpoints, populate descriptors)
Definition uac_mic.hpp:321
ErrorCode GetAltSetting(uint8_t itf, uint8_t &alt) override
获取接口的当前 Alternate Setting Get current alternate setting for interface
Definition uac_mic.hpp:658
const char * GetInterfaceString(size_t local_interface_index) const override
返回本类暴露的第 N 个接口字符串 Return the string for the Nth local interface exposed by this class.
Definition uac_mic.hpp:90
size_t QueueSize() const
获取队列当前字节数 / Get current queued bytes
Definition uac_mic.hpp:115
ErrorCode WritePcm(const void *data, size_t nbytes)
写入 PCM 字节流(如 S16LE / S24_3LE) Write interleaved PCM bytes (e.g., S16LE / S24_3LE)
Definition uac_mic.hpp:110
UAC1MicrophoneQ(uint32_t sample_rate_hz, int16_t vol_min=K_DEFAULT_VOL_MIN, int16_t vol_max=K_DEFAULT_VOL_MAX, int16_t vol_res=K_DEFAULT_VOL_RES, Speed speed=K_DEFAULT_SPEED, size_t queue_bytes=K_DEFAULT_QUEUE_BYTES, uint8_t interval=K_DEFAULT_INTERVAL, Endpoint::EPNumber iso_in_ep_num=Endpoint::EPNumber::EP_AUTO, const char *control_interface_string=DEFAULT_CONTROL_INTERFACE_STRING, const char *streaming_interface_string=DEFAULT_STREAMING_INTERFACE_STRING)
构造 UAC1 队列式麦克风 Construct a queue‑backed UAC1 microphone
Definition uac_mic.hpp:64
ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
设置接口的 Alternate Setting(切换数据流) Set interface alternate setting (toggle streaming)
Definition uac_mic.hpp:673
ErrorCode
定义错误码枚举
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
IAD(8 字节)/ Interface Association Descriptor (8 bytes)
Definition desc_cfg.hpp:60
接口描述符(9 字节)/ Interface descriptor (9 bytes)
Definition desc_cfg.hpp:75
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
AC 特性单元(静音/音量) AC feature unit (mute/volume)
Definition uac_mic.hpp:217
AC 输入端子(麦克风) AC input terminal (Microphone)
Definition uac_mic.hpp:202
AC 输出端子(USB 流) AC output terminal (USB streaming)
Definition uac_mic.hpp:231
AS 通用描述符 AS general descriptor.
Definition uac_mic.hpp:244
AC 头描述符 AC header descriptor.
Definition uac_mic.hpp:191
类特定端点(通用) Class‑specific endpoint (general)
Definition uac_mic.hpp:269
标准等时 IN 端点(9 字节,含 bRefresh/bSynchAddress) Standard isoch IN endpoint (9 bytes, with bRefresh/bSynchAd...
Definition uac_mic.hpp:281
Type I 格式(单一离散采样率) Type I format (single discrete sampling frequency)
Definition uac_mic.hpp:255
UAC1 描述符块 UAC1 descriptor block.
Definition uac_mic.hpp:297
ACInputTerminal it_mic
输入端子 / Input terminal
Definition uac_mic.hpp:301
ACFeatureUnit fu
特性单元 / Feature unit
Definition uac_mic.hpp:302
InterfaceDescriptor ac_intf
AC 接口 / AC interface.
Definition uac_mic.hpp:299
CSACHeader ac_hdr
AC 头 / AC header.
Definition uac_mic.hpp:300
InterfaceDescriptor as_alt1
AS Alt 1(1 个 IN 端点)/ AS Alt 1 (1 IN EP)
Definition uac_mic.hpp:305
InterfaceDescriptor as_alt0
AS Alt 0(无端点)/ AS Alt 0 (no EP)
Definition uac_mic.hpp:304
IADDescriptor iad
接口关联描述符 / Interface association descriptor
Definition uac_mic.hpp:298
TypeIFormat1 fmt
格式描述符 / format descriptor
Definition uac_mic.hpp:307
ASGeneral as_gen
AS 通用 / AS general.
Definition uac_mic.hpp:306
CSEndpointGeneral ep_cs
类特定端点 / CS EP
Definition uac_mic.hpp:309
ACOutputTerminal ot_usb
输出端子 / Output terminal
Definition uac_mic.hpp:303
EndpointDescriptorIso9 ep_in
标准 IN 端点(9B)/ Std IN EP (9B)
Definition uac_mic.hpp:308