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
11namespace LibXR::USB
12{
13
20template <uint8_t CHANNELS, uint8_t BITS_PER_SAMPLE>
22{
23 static_assert(CHANNELS >= 1 && CHANNELS <= 8, "CHANNELS out of range");
24 static_assert(BITS_PER_SAMPLE == 8 || BITS_PER_SAMPLE == 16 || BITS_PER_SAMPLE == 24,
25 "BITS_PER_SAMPLE must be 8/16/24");
26
28 static const constexpr uint8_t K_SUBFRAME_SIZE = (BITS_PER_SAMPLE <= 8) ? 1
29 : (BITS_PER_SAMPLE <= 16) ? 2
30 : 3;
31
32 public:
44 UAC1MicrophoneQ(uint32_t sample_rate_hz, int16_t vol_min, int16_t vol_max,
45 int16_t vol_res, Speed speed, size_t queue_bytes = 8192,
46 uint8_t interval = 1,
48 : iso_in_ep_num_(iso_in_ep_num),
49 vol_min_(vol_min),
50 vol_max_(vol_max),
51 vol_res_(vol_res),
52 interval_(interval),
53 speed_(speed),
54 sr_hz_(sample_rate_hz),
55 pcm_queue_(queue_bytes)
56 {
58 // 缓存端点采样率(3 字节小端) / Cache current sampling frequency (3‑byte LE)
59 sf_cur_[0] = static_cast<uint8_t>(sr_hz_ & 0xFF);
60 sf_cur_[1] = static_cast<uint8_t>((sr_hz_ >> 8) & 0xFF);
61 sf_cur_[2] = static_cast<uint8_t>((sr_hz_ >> 16) & 0xFF);
62 }
63
64 // ===== 生产者接口 / Producer‑side API =====
69 ErrorCode WritePcm(const void* data, size_t nbytes)
70 {
71 return pcm_queue_.PushBatch(reinterpret_cast<const uint8_t*>(data), nbytes);
72 }
74 size_t QueueSize() const { return pcm_queue_.Size(); }
76 size_t QueueSpace() { return pcm_queue_.EmptySize(); }
78 void ResetQueue() { pcm_queue_.Reset(); }
79
80 // ===== UAC1 常量 / UAC1 constants =====
81 enum : uint8_t
82 {
83 USB_CLASS_AUDIO = 0x01,
84 SUBCLASS_AC = 0x01,
85 SUBCLASS_AS = 0x02
86 };
87 enum : uint8_t
88 {
89 CS_INTERFACE = 0x24,
90 CS_ENDPOINT = 0x25
91 };
92 enum : uint8_t
93 {
94 AC_HEADER = 0x01,
95 AC_INPUT_TERMINAL = 0x02,
96 AC_OUTPUT_TERMINAL = 0x03,
97 AC_FEATURE_UNIT = 0x06
98 };
99 enum : uint8_t
100 {
101 AS_GENERAL = 0x01,
102 AS_FORMAT_TYPE = 0x02
103 };
104 enum : uint8_t
105 {
106 EP_GENERAL = 0x01
107 };
108 enum : uint16_t
109 {
110 WFORMAT_PCM = 0x0001,
111 WFORMAT_UNKNOWN = 0xFFFF
112 };
113 enum : uint8_t
114 {
115 FORMAT_TYPE_I = 0x01
116 };
117
118 // UAC1 类请求 / Class‑specific requests
119 enum : uint8_t
120 {
121 SET_CUR = 0x01,
122 GET_CUR = 0x81,
123 SET_MIN = 0x02,
124 GET_MIN = 0x82,
125 SET_MAX = 0x03,
126 GET_MAX = 0x83,
127 SET_RES = 0x04,
128 GET_RES = 0x84
129 };
130 enum : uint8_t
131 {
132 FU_MUTE = 0x01,
133 FU_VOLUME = 0x02
134 };
135
136 // 实体 ID / Entity IDs
137 enum : uint8_t
138 {
139 ID_IT_MIC = 1,
140 ID_FU = 2,
141 ID_OT_USB = 3
142 };
143
144#pragma pack(push, 1)
150 {
151 uint8_t bLength = 9, bDescriptorType = CS_INTERFACE, bDescriptorSubtype = AC_HEADER;
152 uint16_t bcdADC = 0x0100, wTotalLength = 0;
153 uint8_t bInCollection = 1, baInterfaceNr = 0;
154 };
155
161 {
162 uint8_t bLength = 12, bDescriptorType = CS_INTERFACE,
163 bDescriptorSubtype = AC_INPUT_TERMINAL;
164 uint8_t bTerminalID = ID_IT_MIC;
165 uint16_t wTerminalType = 0x0201; // Microphone
166 uint8_t bAssocTerminal = 0, bNrChannels = CHANNELS;
167 uint16_t wChannelConfig = 0x0000; // 根据 CHANNELS 设定 / Set per CHANNELS
168 uint8_t iChannelNames = 0, iTerminal = 0;
169 };
170
176 {
177 uint8_t bLength = static_cast<uint8_t>(7 + (CHANNELS + 1) * 1);
178 uint8_t bDescriptorType = CS_INTERFACE, bDescriptorSubtype = AC_FEATURE_UNIT;
179 uint8_t bUnitID = ID_FU, bSourceID = ID_IT_MIC, bControlSize = 1;
180 uint8_t bmaControlsMaster = 0x03; // Mute + Volume
181 uint8_t bmaControlsCh[CHANNELS] = {0x03}; // Per‑channel supported
182 uint8_t iFeature = 0;
183 };
184
190 {
191 uint8_t bLength = 9, bDescriptorType = CS_INTERFACE,
192 bDescriptorSubtype = AC_OUTPUT_TERMINAL;
193 uint8_t bTerminalID = ID_OT_USB;
194 uint16_t wTerminalType = 0x0101; // USB Streaming
195 uint8_t bAssocTerminal = 0, bSourceID = ID_FU, iTerminal = 0;
196 };
197
203 {
204 uint8_t bLength = 7, bDescriptorType = CS_INTERFACE, bDescriptorSubtype = AS_GENERAL;
205 uint8_t bTerminalLink = ID_OT_USB, bDelay = 1;
206 uint16_t wFormatTag = WFORMAT_PCM;
207 };
208
214 {
215 uint8_t bLength = 11, bDescriptorType = CS_INTERFACE,
216 bDescriptorSubtype = AS_FORMAT_TYPE;
217 uint8_t bFormatType = FORMAT_TYPE_I, bNrChannels = CHANNELS;
218 uint8_t bSubframeSize = K_SUBFRAME_SIZE, bBitResolution = BITS_PER_SAMPLE,
219 bSamFreqType = 1;
220 uint8_t tSamFreq[3]; // 运行期填充 / Filled at runtime
221 };
222
228 {
229 uint8_t bLength = 7, bDescriptorType = CS_ENDPOINT, bDescriptorSubtype = EP_GENERAL;
230 uint8_t bmAttributes = 0x00;
231 uint8_t bLockDelayUnits = 0;
232 uint16_t wLockDelay = 0;
233 };
234
240 {
241 uint8_t bLength = 9;
242 uint8_t bDescriptorType = static_cast<uint8_t>(DescriptorType::ENDPOINT);
243 uint8_t bEndpointAddress = 0; // 含方向位 / includes direction bit
244 uint8_t bmAttributes = 0x05; // Isochronous + Async + Data
245 uint16_t wMaxPacketSize = 0; // 运行期填充 / filled at runtime
246 uint8_t bInterval = 0x01; // 1 ms
247 uint8_t bRefresh = 0x00; // 仅反馈端点使用 / feedback only
248 uint8_t bSynchAddress = 0x00; // 无伴随端点 / no sync/feedback ep
249 };
250
270#pragma pack(pop)
271
272 // ===== DeviceClass 接口实现 / DeviceClass implementation =====
277 void Init(EndpointPool& endpoint_pool, uint8_t start_itf_num) override
278 {
279 inited_ = false;
280 streaming_ = false;
281 acc_rem_ = 0;
282
283 if (speed_ == Speed::HIGH)
284 {
285 ASSERT(w_max_packet_size_ <= 1024);
286 }
287 else
288 {
289 ASSERT(interval_ == 1);
290 ASSERT(w_max_packet_size_ <= 1023);
291 }
292
293 // 仅分配端点,不立即开启(在 AS Alt=1 时开启)
294 auto ans = endpoint_pool.Get(ep_iso_in_, Endpoint::Direction::IN, iso_in_ep_num_);
295 ASSERT(ans == ErrorCode::OK);
296
298 static_cast<uint16_t>(w_max_packet_size_), true});
299
300 itf_ac_num_ = start_itf_num;
301 itf_as_num_ = static_cast<uint8_t>(start_itf_num + 1);
302
303 // IAD
304 desc_block_.iad = {8,
305 static_cast<uint8_t>(DescriptorType::IAD),
306 itf_ac_num_,
307 2,
308 USB_CLASS_AUDIO,
309 SUBCLASS_AC,
310 0x00,
311 0};
312
313 // AC 接口(标准接口)
314 desc_block_.ac_intf = {9,
315 static_cast<uint8_t>(DescriptorType::INTERFACE),
316 itf_ac_num_,
317 0,
318 0,
319 USB_CLASS_AUDIO,
320 SUBCLASS_AC,
321 0x00,
322 0};
323
324 // AC Header
325 desc_block_.ac_hdr.baInterfaceNr = itf_as_num_;
326 desc_block_.ac_hdr.wTotalLength =
327 static_cast<uint16_t>(sizeof(CSACHeader) + sizeof(ACInputTerminal) +
328 sizeof(ACFeatureUnit) + sizeof(ACOutputTerminal));
329
330 // AC Input Terminal 的 wChannelConfig 按通道数设置
331 if constexpr (CHANNELS == 2)
332 {
333 desc_block_.it_mic.wChannelConfig = 0x0003; // Left Front | Right Front
334 }
335 else
336 {
337 desc_block_.it_mic.wChannelConfig = 0x0000; // 未声明或单声道 / unspecified or mono
338 }
339
340 // AS Alt 0(无端点)
341 desc_block_.as_alt0 = {9,
342 static_cast<uint8_t>(DescriptorType::INTERFACE),
343 itf_as_num_,
344 0,
345 0,
346 USB_CLASS_AUDIO,
347 SUBCLASS_AS,
348 0x00,
349 0};
350
351 // AS Alt 1(1 个 Iso IN 端点)
352 desc_block_.as_alt1 = {9,
353 static_cast<uint8_t>(DescriptorType::INTERFACE),
354 itf_as_num_,
355 1,
356 1,
357 USB_CLASS_AUDIO,
358 SUBCLASS_AS,
359 0x00,
360 0};
361
362 // AS General
363 desc_block_.as_gen = {};
364 desc_block_.as_gen.bTerminalLink = ID_OT_USB;
365 desc_block_.as_gen.bDelay = 1;
366 desc_block_.as_gen.wFormatTag = WFORMAT_PCM;
367
368 // Type I Format(单一离散采样率)
369 desc_block_.fmt.bFormatType = FORMAT_TYPE_I;
370 desc_block_.fmt.bNrChannels = CHANNELS;
371 desc_block_.fmt.bSubframeSize = K_SUBFRAME_SIZE;
372 desc_block_.fmt.bBitResolution = BITS_PER_SAMPLE;
373 desc_block_.fmt.bSamFreqType = 1;
374 desc_block_.fmt.tSamFreq[0] = static_cast<uint8_t>(sr_hz_ & 0xFF);
375 desc_block_.fmt.tSamFreq[1] = static_cast<uint8_t>((sr_hz_ >> 8) & 0xFF);
376 desc_block_.fmt.tSamFreq[2] = static_cast<uint8_t>((sr_hz_ >> 16) & 0xFF);
377
378 // 标准 ISO IN 端点(9 字节)
379 desc_block_.ep_in = {};
380 desc_block_.ep_in.bEndpointAddress = static_cast<uint8_t>(
382 desc_block_.ep_in.bmAttributes = 0x05;
383 desc_block_.ep_in.wMaxPacketSize = static_cast<uint16_t>(w_max_packet_size_);
384 desc_block_.ep_in.bInterval = (speed_ == Speed::HIGH) ? interval_ : 0x01;
385 desc_block_.ep_in.bRefresh = 0x00;
386 desc_block_.ep_in.bSynchAddress = 0x00;
387
388 desc_block_.ep_cs = {};
389 desc_block_.ep_cs.bmAttributes = 0x00;
390 // IN 传输完成回调 → 继续投下一帧
391 ep_iso_in_->SetOnTransferCompleteCallback(on_in_complete_cb_);
392
393 // 设置整块配置数据
394 SetData(RawData{reinterpret_cast<uint8_t*>(&desc_block_), sizeof(desc_block_)});
395
396 inited_ = true;
397 }
398
403 void Deinit(EndpointPool& endpoint_pool) override
404 {
405 streaming_ = false;
406 inited_ = false;
407 if (ep_iso_in_)
408 {
409 ep_iso_in_->Close();
410 ep_iso_in_->SetActiveLength(0);
411 endpoint_pool.Release(ep_iso_in_);
412 ep_iso_in_ = nullptr;
413 }
414 }
415
420 ErrorCode OnGetDescriptor(bool, uint8_t, uint16_t, uint16_t, ConstRawData&) override
421 {
422 return ErrorCode::NOT_SUPPORT;
423 }
424
429 ErrorCode OnClassRequest(bool /*in_isr*/, uint8_t bRequest, uint16_t wValue,
430 uint16_t wLength, uint16_t wIndex,
431 DeviceClass::RequestResult& r) override
432 {
433 // ===== 端点采样率控制(收件人:端点地址) / EP sampling‑freq control =====
434 const uint8_t EP_ADDR = static_cast<uint8_t>(wIndex & 0xFF);
435 const uint8_t CS_EP =
436 static_cast<uint8_t>((wValue >> 8) & 0xFF); // 0x01 = Sampling Freq
437
438 if (EP_ADDR == desc_block_.ep_in.bEndpointAddress && CS_EP == 0x01)
439 {
440 switch (bRequest)
441 {
442 case GET_CUR:
443 if (wLength == 3)
444 {
445 r.write_data = ConstRawData{sf_cur_, 3};
446 return ErrorCode::OK;
447 }
448 break;
449 case SET_CUR:
450 if (wLength == 3)
451 {
452 pending_set_sf_ = true;
453 r.read_data = RawData{sf_cur_, 3};
454 return ErrorCode::OK;
455 }
456 break;
457 case GET_MIN:
458 case GET_MAX:
459 if (wLength == 3)
460 {
461 r.write_data = ConstRawData{sf_cur_, 3};
462 return ErrorCode::OK;
463 } // 单一频点
464 break;
465 case GET_RES:
466 {
467 static uint8_t one_hz[3] = {1, 0, 0};
468 if (wLength == 3)
469 {
470 r.write_data = ConstRawData{one_hz, 3};
471 return ErrorCode::OK;
472 }
473 break;
474 }
475 default:
476 break;
477 }
478 ASSERT(false);
479 return ErrorCode::ARG_ERR; // 长度不符等 / length mismatch etc.
480 }
481
482 // ===== Feature Unit(收件人:Interface / AC 接口) / Feature Unit =====
483 const uint8_t CS = static_cast<uint8_t>((wValue >> 8) & 0xFF); // FU_MUTE / FU_VOLUME
484 const uint8_t CH = static_cast<uint8_t>(wValue & 0xFF); // 0=master, 1..N
485 const uint8_t ENT =
486 static_cast<uint8_t>((wIndex >> 8) & 0xFF); // 实体 ID / entity ID
487 const uint8_t ITF = static_cast<uint8_t>(wIndex & 0xFF); // 接口号 / interface num
488
489 if (ITF != itf_ac_num_ || ENT != ID_FU)
490 {
491 ASSERT(false);
492 return ErrorCode::NOT_SUPPORT;
493 }
494 if (CH > CHANNELS)
495 {
496 ASSERT(false);
497 return ErrorCode::ARG_ERR;
498 }
499
500 switch (CS)
501 {
502 case FU_MUTE:
503 if (bRequest == SET_CUR && wLength == 1)
504 {
505 r.read_data = RawData{&mute_, 1};
506 return ErrorCode::OK;
507 }
508 if (bRequest == GET_CUR && wLength == 1)
509 {
510 r.write_data = ConstRawData{&mute_, 1};
511 return ErrorCode::OK;
512 }
513 ASSERT(false);
514 return ErrorCode::ARG_ERR;
515
516 case FU_VOLUME:
517 switch (bRequest)
518 {
519 case SET_CUR:
520 if (wLength == 2)
521 {
522 r.read_data = RawData{reinterpret_cast<uint8_t*>(&vol_cur_), 2};
523 return ErrorCode::OK;
524 }
525 break;
526 case GET_CUR:
527 if (wLength == 2)
528 {
529 r.write_data = ConstRawData{reinterpret_cast<uint8_t*>(&vol_cur_), 2};
530 return ErrorCode::OK;
531 }
532 break;
533 case GET_MIN:
534 if (wLength == 2)
535 {
536 r.write_data = ConstRawData{reinterpret_cast<const uint8_t*>(&vol_min_), 2};
537 return ErrorCode::OK;
538 }
539 break;
540 case GET_MAX:
541 if (wLength == 2)
542 {
543 r.write_data = ConstRawData{reinterpret_cast<const uint8_t*>(&vol_max_), 2};
544 return ErrorCode::OK;
545 }
546 break;
547 case GET_RES:
548 if (wLength == 2)
549 {
550 r.write_data = ConstRawData{reinterpret_cast<const uint8_t*>(&vol_res_), 2};
551 return ErrorCode::OK;
552 }
553 break;
554 case SET_RES: // 吃下以避免 STALL / accept to avoid STALL
555 if (wLength == 2)
556 {
557 r.read_data = RawData{reinterpret_cast<uint8_t*>(&vol_res_), 2};
558 return ErrorCode::OK;
559 }
560 default:
561 break;
562 }
563 ASSERT(false);
564 return ErrorCode::ARG_ERR;
565
566 default:
567 ASSERT(false);
568 return ErrorCode::NOT_SUPPORT;
569 }
570 }
571
576 ErrorCode OnClassData(bool /*in_isr*/, uint8_t bRequest,
577 LibXR::ConstRawData& /*data*/) override
578 {
579 if (bRequest == SET_CUR && pending_set_sf_)
580 {
581 const uint32_t NEW_SR = static_cast<uint32_t>(sf_cur_[0]) |
582 (static_cast<uint32_t>(sf_cur_[1]) << 8) |
583 (static_cast<uint32_t>(sf_cur_[2]) << 16);
584 if (NEW_SR > 0 && NEW_SR != sr_hz_)
585 {
586 sr_hz_ = NEW_SR;
588 }
589 pending_set_sf_ = false;
590 return ErrorCode::OK;
591 }
592 return ErrorCode::OK;
593 }
594
599 ErrorCode GetAltSetting(uint8_t itf, uint8_t& alt) override
600 {
601 if (itf != itf_as_num_)
602 {
603 ASSERT(false);
604 return ErrorCode::NOT_SUPPORT;
605 }
606 alt = streaming_ ? 1 : 0;
607 return ErrorCode::OK;
608 }
609
614 ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
615 {
616 if (itf != itf_as_num_)
617 {
618 ASSERT(false);
619 return ErrorCode::NOT_SUPPORT;
620 }
621 if (!ep_iso_in_)
622 {
623 ASSERT(false);
624 return ErrorCode::FAILED;
625 }
626
627 switch (alt)
628 {
629 case 0: // Alt 0:无端点
630 streaming_ = false;
631 ep_iso_in_->SetActiveLength(0);
632 ep_iso_in_->Close();
633 return ErrorCode::OK;
634
635 case 1: // Alt 1:一个 Iso IN 端点
637 static_cast<uint16_t>(w_max_packet_size_), false});
638 ep_iso_in_->SetActiveLength(0);
639 acc_rem_ = 0; // 重置余数累加器 / reset remainder accumulator
640 streaming_ = true;
641 KickOneFrame();
642 return ErrorCode::OK;
643
644 default:
645 ASSERT(false);
646 return ErrorCode::ARG_ERR;
647 }
648 }
649
651 size_t GetInterfaceNum() override { return 2; }
653 bool HasIAD() override { return true; }
655 size_t GetMaxConfigSize() override { return sizeof(UAC1DescBlock); }
656
657 bool OwnsEndpoint(uint8_t ep_addr) const override
658 {
659 if (!inited_)
660 {
661 return false;
662 }
663 return ep_iso_in_->GetAddress() == ep_addr;
664 }
665
666 private:
667 // ===== 端点传输 / Endpoint transfers =====
672 static void OnInCompleteStatic(bool in_isr, UAC1MicrophoneQ* self, ConstRawData& data)
673 {
674 if (!self->inited_)
675 {
676 return;
677 }
678 self->OnInComplete(in_isr, data);
679 }
680
686 {
687 if (!streaming_)
688 {
689 return;
690 }
691 KickOneFrame();
692 }
693
699 {
700 if (!streaming_)
701 {
702 return; // Alt=1 才允许
703 }
704 if (!ep_iso_in_ || ep_iso_in_->GetState() != Endpoint::State::IDLE)
705 {
706 return;
707 }
708
709 // 本帧应发送字节数 = floor + 余数累加决定是否 +1
710 uint16_t to_send = static_cast<uint16_t>(base_bytes_per_service_);
711 acc_rem_ += rem_bytes_per_service_;
712 if (acc_rem_ >= service_hz_)
713 {
714 ++to_send;
715 acc_rem_ -= service_hz_;
716 }
717
718 if (to_send > w_max_packet_size_)
719 {
720 to_send = static_cast<uint16_t>(w_max_packet_size_);
721 }
722
723 auto buf = ep_iso_in_->GetBuffer();
724 if (buf.size_ < to_send)
725 {
726 to_send = static_cast<uint16_t>(buf.size_);
727 }
728
729 // 从队列取可用字节 / pop available bytes from queue
730 size_t have = pcm_queue_.Size();
731 size_t take = (have >= to_send) ? to_send : have;
732
733 if (take)
734 {
735 pcm_queue_.PopBatch(reinterpret_cast<uint8_t*>(buf.addr_), take);
736 }
737
738 ep_iso_in_->Transfer(take);
739 }
740
746 {
747 // 1) 计算每秒服务次数(FS=1000Hz;HS=8000/2^(bInterval-1))
748 if (speed_ == Speed::HIGH)
749 {
750 uint8_t eff = interval_ ? interval_ : 1;
751 if (eff > 16)
752 {
753 eff = 16;
754 }
755 const uint32_t MICROFRAMES = 1u << (eff - 1u); // 2^(bInterval-1) 个微帧
756 service_hz_ = 8000u / MICROFRAMES; // 8000 微帧/秒
757 }
758 else
759 {
760 service_hz_ = 1000u; // FS 等时:规范上 bInterval 必须为 1 帧 => 1kHz
761 }
762
763 // 2) 计算每服务周期应送字节
764 bytes_per_sec_ = static_cast<uint32_t>(sr_hz_) * CHANNELS * K_SUBFRAME_SIZE;
765 base_bytes_per_service_ = bytes_per_sec_ / service_hz_;
766 rem_bytes_per_service_ = bytes_per_sec_ % service_hz_;
767 uint32_t ceil_bpt = base_bytes_per_service_ + (rem_bytes_per_service_ ? 1u : 0u);
768
769 // 3) 钳制每事务上限(FS 1023,HS 1024;此处只做单事务上限,未用 HS multiplier)
770 const uint32_t PER_TX_LIMIT = (speed_ == Speed::HIGH) ? 1024u : 1023u;
771 if (ceil_bpt > PER_TX_LIMIT)
772 {
773 ceil_bpt = PER_TX_LIMIT;
774 }
775
776 w_max_packet_size_ = static_cast<uint16_t>(ceil_bpt);
777
778 // 4) 若已构建过描述符,则运行时能力不得超过宣告值
779 if (desc_block_.ep_in.wMaxPacketSize != 0 &&
780 w_max_packet_size_ > desc_block_.ep_in.wMaxPacketSize)
781 {
782 w_max_packet_size_ = desc_block_.ep_in.wMaxPacketSize;
783 }
784 }
785
786 // 端点/接口 / Endpoints & interfaces
787 Endpoint::EPNumber iso_in_ep_num_;
788 Endpoint* ep_iso_in_ = nullptr;
789 uint8_t itf_ac_num_ = 0;
790 uint8_t itf_as_num_ = 0;
791
792 // 状态 / State
793 bool inited_ = false;
794 bool streaming_ = false;
795
796 // 音量/静音 / Volume & mute
797 uint8_t mute_ = 0;
798 int16_t vol_cur_ = 0; // 0 dB
799 int16_t vol_min_, vol_max_, vol_res_;
800
801 uint8_t interval_;
802 Speed speed_;
803
804 // 采样与帧切分 / Sampling & framing
805 uint32_t sr_hz_;
806 uint32_t bytes_per_sec_ = 0;
807 uint32_t base_bytes_per_service_ = 0;
808 uint32_t rem_bytes_per_service_ = 0;
809 uint32_t acc_rem_ = 0; // 0..999
810 uint16_t w_max_packet_size_ = 0;
811 uint32_t service_hz_ = 1000;
812
813 UAC1DescBlock desc_block_;
814
815 // 端点采样率缓存(Hz,小端 3 字节)与状态 / EP sampling‑freq cache & flag
816 uint8_t sf_cur_[3] = {0, 0, 0};
817 bool pending_set_sf_ = false;
818
819 // PCM 队列(字节) / PCM byte queue
821
822 // 端点回调包装 / Endpoint callback wrapper
823 LibXR::Callback<LibXR::ConstRawData&> on_in_complete_cb_ =
825};
826
827} // namespace LibXR::USB
提供一个通用的回调包装,支持动态参数传递。 Provides a generic callback wrapper, supporting dynamic argument passing.
Definition libxr_cb.hpp:124
static Callback Create(FunType fun, ArgType arg)
创建一个新的回调对象,并绑定回调函数和参数。 Creates a new callback instance, binding a function and an argument.
Definition libxr_cb.hpp:142
常量原始数据封装类。 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
原始数据封装类。 A class for encapsulating raw data.
void SetData(RawData data)
设置配置项数据 Set configuration item data
Definition desc_cfg.hpp:212
USB 设备类接口基类,所有自定义 USB 类(如 HID、CDC、MSC)都需派生自本类。 USB device class base interface, all custom device cla...
Definition dev_core.hpp:22
USB端点基类 / USB Endpoint base class.
Definition ep.hpp:22
EPNumber
端点号 / Endpoint number
Definition ep.hpp:39
@ EP_AUTO
自动分配端点号 / Auto allocate
uint8_t GetAddress() const
获取端点地址(方向 + 号) Get endpoint address (dir + num)
Definition ep.hpp:199
@ IN
输入方向 / IN direction
static constexpr uint8_t EPNumberToAddr(EPNumber ep, Direction dir)
端点号转换为端点地址 / Convert endpoint number to endpoint address
Definition ep.hpp:104
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
Definition ep.hpp:273
virtual void Configure(const Config &cfg)=0
二次初始化/配置端点协议参数(由Pool/Manager分配后调用) Configure endpoint protocol parameters (call after pool allocation...
@ ISOCHRONOUS
等时端点 / Isochronous
EPNumber GetNumber() const
获取端点号 Get endpoint number
Definition ep.hpp:174
virtual void Close()=0
关闭端点(软禁用/资源复位) Close (soft disable)
State GetState() const
获取端点状态 Get endpoint state
Definition ep.hpp:212
virtual ErrorCode Transfer(size_t size)=0
传输数据 Transfer data
RawData GetBuffer() const
获取端点缓冲区 Get endpoint buffer
Definition ep.hpp:256
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:22
void RecomputeTiming()
统一重算时序与包长(运行时 MPS 钳制到描述符宣告值) Recompute timing and packet sizing (runtime MPS clamped to descriptor)
Definition uac_mic.hpp:745
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:420
static const constexpr uint8_t K_SUBFRAME_SIZE
每通道每采样的子帧字节数 / Subframe size (bytes per channel per sample)
Definition uac_mic.hpp:28
bool HasIAD() override
包含 IAD | Has IAD
Definition uac_mic.hpp:653
size_t QueueSpace()
获取队列剩余空间 | Get remaining queue capacity (bytes)
Definition uac_mic.hpp:76
UAC1MicrophoneQ(uint32_t sample_rate_hz, int16_t vol_min, int16_t vol_max, int16_t vol_res, Speed speed, size_t queue_bytes=8192, uint8_t interval=1, Endpoint::EPNumber iso_in_ep_num=Endpoint::EPNumber::EP_AUTO)
构造 UAC1 队列式麦克风 Construct a queue‑backed UAC1 microphone
Definition uac_mic.hpp:44
size_t GetMaxConfigSize() override
配置描述符最大尺寸 | Get maximum configuration size
Definition uac_mic.hpp:655
void KickOneFrame()
计算并投递一帧(按 1ms 变包 + 零填充) Compute and submit one frame (1 ms variable size + zero fill)
Definition uac_mic.hpp:698
bool OwnsEndpoint(uint8_t ep_addr) const override
判断是否拥有该端点 Check if this configuration item owns this endpoint
Definition uac_mic.hpp:657
static void OnInCompleteStatic(bool in_isr, UAC1MicrophoneQ *self, ConstRawData &data)
IN 传输完成静态回调 Static callback for IN transfer completion.
Definition uac_mic.hpp:672
void OnInComplete(bool, ConstRawData &)
IN 传输完成处理:继续投下一帧 Handle IN transfer completion: kick next frame.
Definition uac_mic.hpp:685
void Init(EndpointPool &endpoint_pool, uint8_t start_itf_num) override
初始化设备(分配端点、填充描述符) Initialize device (allocate endpoints, populate descriptors)
Definition uac_mic.hpp:277
void ResetQueue()
重置队列为空 | Reset queue to empty
Definition uac_mic.hpp:78
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:576
size_t GetInterfaceNum() override
返回接口数量(AC+AS=2)| Get number of interfaces (AC+AS=2)
Definition uac_mic.hpp:651
ErrorCode GetAltSetting(uint8_t itf, uint8_t &alt) override
获取接口的当前 Alternate Setting Get current alternate setting for interface
Definition uac_mic.hpp:599
void Deinit(EndpointPool &endpoint_pool) override
反初始化设备,释放端点 Deinitialize device and release endpoints
Definition uac_mic.hpp:403
size_t QueueSize() const
获取队列当前字节数 | Get current queued bytes
Definition uac_mic.hpp:74
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:69
ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
设置接口的 Alternate Setting(切换数据流) Set interface alternate setting (toggle streaming)
Definition uac_mic.hpp:614
ErrorCode OnClassRequest(bool, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, DeviceClass::RequestResult &r) override
处理类请求:端点采样率控制 + Feature Unit(静音/音量) Handle class requests: EP sampling‑freq control + Feature Unit (m...
Definition uac_mic.hpp:429
接口关联描述符(IAD,Interface Association Descriptor) IAD descriptor structure (用于复合设备多接口归组 / used for groupi...
Definition desc_cfg.hpp:58
接口描述符结构体 Interface descriptor structure (USB 2.0 Spec 9.6.5)
Definition desc_cfg.hpp:74
控制请求结果结构体 / Structure for control transfer results
Definition dev_core.hpp:28
RawData read_data
设备返回给主机的数据 / Data to read (to host)
Definition dev_core.hpp:29
ConstRawData write_data
主机写入设备的数据 / Data to write (from host)
Definition dev_core.hpp:30
AC 特性单元(静音/音量) AC feature unit (mute/volume)
Definition uac_mic.hpp:176
AC 输入端子(麦克风) AC input terminal (Microphone)
Definition uac_mic.hpp:161
AC 输出端子(USB 流) AC output terminal (USB streaming)
Definition uac_mic.hpp:190
AS 通用描述符 AS general descriptor.
Definition uac_mic.hpp:203
AC 头描述符 AC header descriptor.
Definition uac_mic.hpp:150
类特定端点(通用) Class‑specific endpoint (general)
Definition uac_mic.hpp:228
标准等时 IN 端点(9 字节,含 bRefresh/bSynchAddress) Standard isoch IN endpoint (9 bytes, with bRefresh/bSynchAd...
Definition uac_mic.hpp:240
Type I 格式(单一离散采样率) Type I format (single discrete sampling frequency)
Definition uac_mic.hpp:214
UAC1 描述符块 UAC1 descriptor block.
Definition uac_mic.hpp:256
ACInputTerminal it_mic
输入端子 / Input terminal
Definition uac_mic.hpp:260
ACFeatureUnit fu
特性单元 / Feature unit
Definition uac_mic.hpp:261
InterfaceDescriptor ac_intf
AC 接口 / AC interface.
Definition uac_mic.hpp:258
CSACHeader ac_hdr
AC 头 / AC header.
Definition uac_mic.hpp:259
InterfaceDescriptor as_alt1
AS Alt 1(1 个 IN 端点)/ AS Alt 1 (1 IN EP)
Definition uac_mic.hpp:264
InterfaceDescriptor as_alt0
AS Alt 0(无端点)/ AS Alt 0 (no EP)
Definition uac_mic.hpp:263
IADDescriptor iad
接口关联描述符 / Interface association descriptor
Definition uac_mic.hpp:257
TypeIFormat1 fmt
格式描述符 / format descriptor
Definition uac_mic.hpp:266
ASGeneral as_gen
AS 通用 / AS general.
Definition uac_mic.hpp:265
CSEndpointGeneral ep_cs
类特定端点 / CS EP
Definition uac_mic.hpp:268
ACOutputTerminal ot_usb
输出端子 / Output terminal
Definition uac_mic.hpp:262
EndpointDescriptorIso9 ep_in
标准 IN 端点(9B)/ Std IN EP (9B)
Definition uac_mic.hpp:267