9#include "libxr_def.hpp"
10#include "libxr_mem.hpp"
21template <u
int8_t CHANNELS, u
int8_t BITS_PER_SAMPLE>
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");
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";
37 : (BITS_PER_SAMPLE <= 16) ? 2
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;
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),
78 sr_hz_(sample_rate_hz),
79 pcm_queue_(queue_bytes),
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);
94 switch (local_interface_index)
112 return pcm_queue_.
PushBatch(
reinterpret_cast<const uint8_t*
>(data), nbytes);
124 USB_CLASS_AUDIO = 0x01,
136 AC_INPUT_TERMINAL = 0x02,
137 AC_OUTPUT_TERMINAL = 0x03,
138 AC_FEATURE_UNIT = 0x06
143 AS_FORMAT_TYPE = 0x02
151 WFORMAT_PCM = 0x0001,
152 WFORMAT_UNKNOWN = 0xFFFF
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;
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;
207 uint8_t bAssocTerminal = 0, bNrChannels = CHANNELS;
208 uint16_t wChannelConfig = 0x0000;
209 uint8_t iChannelNames = 0, iTerminal = 0;
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;
222 uint8_t bmaControlsCh[CHANNELS] = {0x03};
223 uint8_t iFeature = 0;
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;
236 uint8_t bAssocTerminal = 0, bSourceID = ID_FU, iTerminal = 0;
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;
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,
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;
283 uint8_t bDescriptorType =
static_cast<uint8_t
>(DescriptorType::ENDPOINT);
284 uint8_t bEndpointAddress = 0;
285 uint8_t bmAttributes = 0x05;
286 uint16_t wMaxPacketSize = 0;
287 uint8_t bInterval = 0x01;
288 uint8_t bRefresh = 0x00;
289 uint8_t bSynchAddress = 0x00;
327 if (speed_ == Speed::HIGH)
329 ASSERT(w_max_packet_size_ <= 1024);
333 ASSERT(interval_ == 1);
334 ASSERT(w_max_packet_size_ <= 1023);
344 static_cast<uint16_t
>(w_max_packet_size_),
true});
346 itf_ac_num_ = start_itf_num;
347 itf_as_num_ =
static_cast<uint8_t
>(start_itf_num + 1);
351 desc_block_.
iad = {8,
352 static_cast<uint8_t
>(DescriptorType::IAD),
362 static_cast<uint8_t
>(DescriptorType::INTERFACE),
373 desc_block_.
ac_hdr.baInterfaceNr = itf_as_num_;
374 desc_block_.
ac_hdr.wTotalLength =
380 if constexpr (CHANNELS == 2)
382 desc_block_.
it_mic.wChannelConfig = 0x0003;
386 desc_block_.
it_mic.wChannelConfig = 0x0000;
392 static_cast<uint8_t
>(DescriptorType::INTERFACE),
404 static_cast<uint8_t
>(DescriptorType::INTERFACE),
416 desc_block_.
as_gen.bTerminalLink = ID_OT_USB;
417 desc_block_.
as_gen.bDelay = 1;
418 desc_block_.
as_gen.wFormatTag = WFORMAT_PCM;
422 desc_block_.
fmt.bFormatType = FORMAT_TYPE_I;
423 desc_block_.
fmt.bNrChannels = CHANNELS;
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);
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;
442 desc_block_.
ep_cs = {};
443 desc_block_.
ep_cs.bmAttributes = 0x00;
450 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
470 endpoint_pool.
Release(ep_iso_in_);
471 ep_iso_in_ =
nullptr;
489 uint16_t wLength, uint16_t wIndex,
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);
497 if (EP_ADDR == desc_block_.
ep_in.bEndpointAddress && CS_EP == 0x01)
511 pending_set_sf_ =
true;
526 static uint8_t one_hz[3] = {1, 0, 0};
542 const uint8_t CS =
static_cast<uint8_t
>((wValue >> 8) & 0xFF);
543 const uint8_t CH =
static_cast<uint8_t
>(wValue & 0xFF);
545 static_cast<uint8_t
>((wIndex >> 8) & 0xFF);
546 const uint8_t ITF =
static_cast<uint8_t
>(wIndex & 0xFF);
548 if (ITF != itf_ac_num_ || ENT != ID_FU)
562 if (bRequest == SET_CUR && wLength == 1)
567 if (bRequest == GET_CUR && wLength == 1)
638 if (bRequest == SET_CUR && pending_set_sf_)
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_)
648 pending_set_sf_ =
false;
660 if (itf != itf_as_num_)
665 alt = streaming_ ? 1 : 0;
675 if (itf != itf_as_num_)
696 static_cast<uint16_t
>(w_max_packet_size_),
false});
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_)
775 acc_rem_ -= service_hz_;
778 if (to_send > w_max_packet_size_)
780 to_send =
static_cast<uint16_t
>(w_max_packet_size_);
784 if (buf.size_ < to_send)
786 to_send =
static_cast<uint16_t
>(buf.size_);
790 size_t have = pcm_queue_.
Size();
791 size_t take = (have >= to_send) ? to_send : have;
795 pcm_queue_.
PopBatch(
reinterpret_cast<uint8_t*
>(buf.addr_), take);
813 if (speed_ == Speed::HIGH)
815 uint8_t eff = interval_ ? interval_ : 1;
820 const uint32_t MICROFRAMES = 1u << (eff - 1u);
821 service_hz_ = 8000u / MICROFRAMES;
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);
837 const uint32_t PER_TX_LIMIT = (speed_ == Speed::HIGH) ? 1024u : 1023u;
838 if (ceil_bpt > PER_TX_LIMIT)
840 ceil_bpt = PER_TX_LIMIT;
843 w_max_packet_size_ =
static_cast<uint16_t
>(ceil_bpt);
847 if (desc_block_.
ep_in.wMaxPacketSize != 0 &&
848 w_max_packet_size_ > desc_block_.
ep_in.wMaxPacketSize)
850 w_max_packet_size_ = desc_block_.
ep_in.wMaxPacketSize;
858 uint8_t itf_ac_num_ = 0;
859 uint8_t itf_as_num_ = 0;
867 bool inited_ =
false;
868 bool streaming_ =
false;
873 int16_t vol_cur_ = 0;
874 int16_t vol_min_, vol_max_, vol_res_;
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;
886 uint16_t w_max_packet_size_ = 0;
887 uint32_t service_hz_ = 1000;
893 uint8_t sf_cur_[3] = {0, 0, 0};
894 bool pending_set_sf_ =
false;
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
常量原始数据封装类。 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
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.
EPNumber
端点号 Endpoint number
@ EP_AUTO
自动分配端点号 / Auto allocate
uint8_t GetAddress() const
获取端点地址(方向 + 号) / Get endpoint address (dir + num)
static constexpr uint8_t EPNumberToAddr(EPNumber ep, Direction dir)
端点号转换为端点地址 / Convert endpoint number to endpoint address
void SetActiveLength(uint16_t len)
设置当前活动缓冲区有效长度 / Set active buffer valid length
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
virtual void Configure(const Config &cfg)=0
配置端点协议参数 / Configure endpoint protocol parameters
@ ISOCHRONOUS
等时端点 / Isochronous
EPNumber GetNumber() const
获取端点号 / Get endpoint number
virtual void Close()=0
关闭端点 / Close endpoint
State GetState() const
获取端点状态 / Get endpoint state
virtual ErrorCode Transfer(size_t size)=0
启动一次传输 / Start a transfer
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
USB端点池类 / USB endpoint pool class.
ErrorCode Get(Endpoint *&ep_info, Endpoint::Direction direction, Endpoint::EPNumber ep_num=Endpoint::EPNumber::EP_AUTO)
分配端点 / Allocate endpoint
ErrorCode Release(Endpoint *ep_info)
回收端点 / Release endpoint
UAC1 队列式麦克风设备类实现 UAC1 queue‑driven microphone device class implementation.
size_t GetInterfaceCount() override
返回接口数量(AC+AS=2) / Get number of interfaces (AC+AS=2)
void RecomputeTiming()
统一重算时序与包长(运行时 MPS 钳制到描述符宣告值) Recompute timing and packet sizing (runtime MPS clamped to descriptor)
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...
ErrorCode OnGetDescriptor(bool, uint8_t, uint16_t, uint16_t, ConstRawData &) override
UAC1 无类特定描述符读出(配置中已包含) UAC1 does not use GET_DESCRIPTOR(0x21/0x22) here.
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化设备,释放端点 Deinitialize device and release endpoints
const char * streaming_interface_string_
流接口字符串 / Streaming interface string
static const constexpr uint8_t K_SUBFRAME_SIZE
每通道每采样的子帧字节数 / Subframe size (bytes per channel per sample)
bool HasIAD() override
包含 IAD / Has IAD
size_t QueueSpace()
获取队列剩余空间 / Get remaining queue capacity (bytes)
const char * control_interface_string_
控制接口字符串 / Control interface string
size_t GetMaxConfigSize() override
配置描述符最大尺寸 / Get maximum configuration size
void KickOneFrame()
计算并投递一帧(按 1ms 变包 + 零填充) Compute and submit one frame (1 ms variable size + zero fill)
bool OwnsEndpoint(uint8_t ep_addr) const override
可选:端点归属判定 / Optional: endpoint ownership
static void OnInCompleteStatic(bool in_isr, UAC1MicrophoneQ *self, ConstRawData &data)
IN 传输完成静态回调 Static callback for IN transfer completion.
void OnInComplete(bool, ConstRawData &)
IN 传输完成处理:继续投下一帧 Handle IN transfer completion: kick next frame.
void ResetQueue()
重置队列为空 / Reset queue to empty
ErrorCode OnClassData(bool, uint8_t bRequest, LibXR::ConstRawData &) override
处理类请求数据阶段(应用 SET_CUR 的采样率) Handle class request data stage (apply SET_CUR sampling freq)
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化设备(分配端点、填充描述符) Initialize device (allocate endpoints, populate descriptors)
ErrorCode GetAltSetting(uint8_t itf, uint8_t &alt) override
获取接口的当前 Alternate Setting Get current alternate setting for interface
const char * GetInterfaceString(size_t local_interface_index) const override
返回本类暴露的第 N 个接口字符串 Return the string for the Nth local interface exposed by this class.
size_t QueueSize() const
获取队列当前字节数 / Get current queued bytes
ErrorCode WritePcm(const void *data, size_t nbytes)
写入 PCM 字节流(如 S16LE / S24_3LE) Write interleaved PCM bytes (e.g., S16LE / S24_3LE)
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
ErrorCode SetAltSetting(uint8_t itf, uint8_t alt) override
设置接口的 Alternate Setting(切换数据流) Set interface alternate setting (toggle streaming)
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
IAD(8 字节)/ Interface Association Descriptor (8 bytes)
接口描述符(9 字节)/ Interface descriptor (9 bytes)
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
AC 特性单元(静音/音量) AC feature unit (mute/volume)
AC 输出端子(USB 流) AC output terminal (USB streaming)
AS 通用描述符 AS general descriptor.
类特定端点(通用) Class‑specific endpoint (general)
标准等时 IN 端点(9 字节,含 bRefresh/bSynchAddress) Standard isoch IN endpoint (9 bytes, with bRefresh/bSynchAd...
UAC1 描述符块 UAC1 descriptor block.
ACInputTerminal it_mic
输入端子 / Input terminal
ACFeatureUnit fu
特性单元 / Feature unit
InterfaceDescriptor ac_intf
AC 接口 / AC interface.
CSACHeader ac_hdr
AC 头 / AC header.
InterfaceDescriptor as_alt1
AS Alt 1(1 个 IN 端点)/ AS Alt 1 (1 IN EP)
InterfaceDescriptor as_alt0
AS Alt 0(无端点)/ AS Alt 0 (no EP)
IADDescriptor iad
接口关联描述符 / Interface association descriptor
TypeIFormat1 fmt
格式描述符 / format descriptor
ASGeneral as_gen
AS 通用 / AS general.
CSEndpointGeneral ep_cs
类特定端点 / CS EP
ACOutputTerminal ot_usb
输出端子 / Output terminal
EndpointDescriptorIso9 ep_in
标准 IN 端点(9B)/ Std IN EP (9B)