6#include "libxr_def.hpp"
56 ErrorCode
Take(uint8_t* dst, std::size_t cap, std::size_t& out_len)
59 if (ec != ErrorCode::OK)
65 const std::size_t REMAINING =
Remaining();
69 return ErrorCode::FAILED;
72 const std::size_t TAKE = (REMAINING < cap) ? REMAINING : cap;
77 return ErrorCode::FAILED;
107 return ErrorCode::FAILED;
111 auto ans =
port_.queue_info_->Pop(popped);
112 ASSERT(ans == ErrorCode::OK);
116 *completed_info = popped;
120 return ErrorCode::OK;
135 return ErrorCode::OK;
139 if (
port_.queue_info_->Peek(info) != ErrorCode::OK)
141 return ErrorCode::EMPTY;
147 return ErrorCode::OK;
225 using LibXR::UART::Read;
227 using LibXR::UART::Write;
241 CDCUart(
size_t rx_buffer_size = 128,
size_t tx_buffer_size = 128,
242 size_t tx_queue_size = 5,
246 :
CDCBase(data_in_ep_num, data_out_ep_num, comm_ep_num),
265 auto& line_coding = GetLineCoding();
270 line_coding.bCharFormat = 0;
273 line_coding.bCharFormat = 2;
276 return ErrorCode::ARG_ERR;
282 line_coding.bParityType = 0;
285 line_coding.bParityType = 1;
288 line_coding.bParityType = 2;
291 return ErrorCode::ARG_ERR;
301 line_coding.bDataBits =
static_cast<uint8_t
>(cfg.
data_bits);
304 return ErrorCode::ARG_ERR;
307 line_coding.dwDTERate = cfg.
baudrate;
309 return ErrorCode::OK;
323 auto ep_data_out = GetDataOutEndpoint();
324 if (ep_data_out ==
nullptr)
329 const std::size_t MPS = ep_data_out->MaxPacketSize();
342 if (push_ans == ErrorCode::OK)
362 auto ans = ep_data_out->Transfer(MPS);
363 if (ans == ErrorCode::OK)
432 return ErrorCode::PENDING;
435 auto ep = cdc->GetDataInEndpoint();
438 return ErrorCode::FAILED;
444 auto pop_ans = port.queue_info_->Pop(info);
445 if (pop_ans != ErrorCode::OK)
447 return ErrorCode::EMPTY;
450 auto drop_ans = port.queue_data_->
PopBatch(
nullptr, info.data.size_);
452 ASSERT(drop_ans == ErrorCode::OK);
454 return ErrorCode::INIT_ERR;
463 if (ep->GetActiveLength() != 0)
465 return ErrorCode::PENDING;
482 ErrorCode slot_ec = ErrorCode::PENDING;
486 auto buffer = ep->GetBuffer();
490 cdc->
tx_deq_.
Take(
reinterpret_cast<uint8_t*
>(buffer.addr_), buffer.size_, len);
491 if (slot_ec == ErrorCode::EMPTY || len == 0)
493 return ErrorCode::PENDING;
495 if (slot_ec != ErrorCode::OK && slot_ec != ErrorCode::PENDING)
500 ep->SetActiveLength(len);
503 std::atomic_signal_fence(std::memory_order_seq_cst);
509 const std::size_t TO_SEND = ep->GetActiveLength();
523 return ErrorCode::PENDING;
526 std::atomic_signal_fence(std::memory_order_seq_cst);
529 ep->SetActiveLength(0);
530 auto ans = ep->Transfer(TO_SEND);
531 ASSERT(ans == ErrorCode::OK);
542 ASSERT(pop_ok == ErrorCode::OK);
545 const std::size_t MPS = ep->MaxPacketSize();
546 if (MPS > 0 && (TO_SEND % MPS) == 0 && ep->GetActiveLength() == 0 &&
552 return ErrorCode::OK;
559 return ErrorCode::PENDING;
562 auto buffer = ep->GetBuffer();
563 std::size_t len2 = 0;
566 cdc->
tx_deq_.
Take(
reinterpret_cast<uint8_t*
>(buffer.addr_), buffer.size_, len2);
567 if (slot_ec == ErrorCode::EMPTY || len2 == 0)
569 return ErrorCode::PENDING;
571 if (slot_ec != ErrorCode::OK && slot_ec != ErrorCode::PENDING)
576 ep->SetActiveLength(len2);
581 static ErrorCode
ReadFun(
ReadPort&,
bool) {
return ErrorCode::PENDING; }
595 reinterpret_cast<const uint8_t*
>(data.
addr_), data.
size_);
596 if (push_ans == ErrorCode::OK)
624 auto ep = GetDataInEndpoint();
650 auto z = ep->TransferZLP();
651 ASSERT(z == ErrorCode::OK);
659 const std::size_t PENDING_LEN = ep->GetActiveLength();
660 if (PENDING_LEN == 0)
667 ep->SetActiveLength(0);
668 auto ans = ep->Transfer(PENDING_LEN);
669 ASSERT(ans == ErrorCode::OK);
677 ASSERT(pop_ok == ErrorCode::OK);
686 auto buffer = ep->GetBuffer();
687 std::size_t len2 = 0;
690 tx_deq_.
Take(
reinterpret_cast<uint8_t*
>(buffer.addr_), buffer.size_, len2);
691 if ((ec2 == ErrorCode::OK || ec2 == ErrorCode::PENDING) && len2 > 0)
693 ep->SetActiveLength(len2);
699 const std::size_t MPS = ep->MaxPacketSize();
700 if (!primed && PENDING_LEN > 0 && MPS > 0 && (PENDING_LEN % MPS) == 0 &&
732 if (ans == ErrorCode::OK)
WritePort(info 队列 + data 队列)的“单 op 不跨界”出队辅助器 Dequeue helper for WritePort (info + data) without cross...
WritePort & port_
写端口引用 / Write port reference
bool HeadCompleted() const
head op 是否已全部出队 Whether the cached head op is fully dequeued
CDCUartTxOpDequeueHelper(WritePort &port)
构造函数 Constructor
bool head_valid_
head 缓存有效标志 / Cached head valid flag
void Reset()
重置内部状态(head 缓存与偏移) Reset internal state (cached head and offset)
ErrorCode EnsureHead()
确保 head 缓存可用(必要时 Peek info) Ensure cached head is valid (Peek info if needed)
WriteInfoBlock head_
缓存的 head info / Cached head info
ErrorCode PopCompleted(WriteInfoBlock *completed_info=nullptr)
在 head 完成后 pop info 并重置状态 Pop info after head completes and reset state
bool HasOp()
是否存在可处理的 op Whether any op exists
std::size_t offset_
当前 op 已出队偏移 / Dequeued offset within current op
std::size_t Remaining() const
当前 op 剩余未出队字节数 Remaining bytes of current op
ErrorCode Take(uint8_t *dst, std::size_t cap, std::size_t &out_len)
从 data 队列搬运数据到目标 buffer,并推进 offset(不 pop info) Dequeue bytes from data queue into destination buffer ...
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
普通标志位(非原子)/ Non-atomic flag
bool IsSet() const noexcept
判断是否已置位 / Check whether the flag is set
作用域标志管理器:构造时写入指定值,析构时恢复原值 / Scoped flag restorer: set on entry, restore on exit
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
ReadPort class for handling read operations.
void ProcessPendingReads(bool in_isr)
Processes pending reads.
ReadPort & operator=(ReadFun fun)
赋值运算符重载,用于设置读取函数。 Overloaded assignment operator to set the read function.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
ReadPort * read_port_
读取端口 / Read port
@ NO_PARITY
无校验 / No parity
WritePort * write_port_
写入端口 / Write port
USB CDC ACM (Abstract Control Model) 设备类实现 USB CDC ACM (Abstract Control Model) device class implemen...
ErrorCode SendSerialState()
发送串行状态通知 Send serial state notification
virtual void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化CDC设备 Deinitialize CDC device
USB CDC-ACM UART 适配器 USB CDC-ACM UART adapter.
CDCUartReadPort read_port_cdc_
CDC RX 读端口 / CDC RX read port.
CDCUart(size_t rx_buffer_size=128, size_t tx_buffer_size=128, size_t tx_queue_size=5, Endpoint::EPNumber data_in_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber data_out_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber comm_ep_num=Endpoint::EPNumber::EP_AUTO)
构造函数 Constructor
bool TryRearmOut(bool in_isr)
尝试 rearm OUT(背压恢复/持续接收) Try to rearm OUT endpoint (backpressure recovery / continuous RX)
void UnbindEndpoints(EndpointPool &endpoint_pool, bool in_isr) override
解绑端点(清理队列、状态与背压标志) Unbind endpoints (cleanup queues, states, and backpressure flags)
static ErrorCode WriteFun(WritePort &port, bool in_isr)
写端口回调(TX) Write port callback (TX)
void OnDataInComplete(bool in_isr, ConstRawData &data) override
IN 完成回调(TX) IN complete callback (TX)
LibXR::CDCUartTxOpDequeueHelper tx_deq_
TX 出队辅助器 / TX dequeue helper.
void OnDataOutComplete(bool in_isr, ConstRawData &data) override
OUT 完成回调(RX) OUT complete callback (RX)
bool need_write_zlp_
ZLP 需求标志 / ZLP required flag.
LibXR::WritePort write_port_cdc_
CDC TX 写端口 / CDC TX write port.
ErrorCode SetConfig(UART::Configuration cfg) override
设置 UART 配置(CDC Line Coding) Set UART configuration (CDC Line Coding)
Flag::Plain in_write_isr_
写 ISR 保护标志 / Write ISR guard flag
CDC UART 读端口(背压 + pending 缓存) CDC UART read port (backpressure + pending cache)
CDCUartReadPort(uint32_t size, CDCUart &owner)
构造函数 Constructor
ConstRawData pending_data_
pending 数据(指向底层 USB buffer)/ Pending data pointing to USB buffer
CDCUart & owner_
所属 CDCUart / Owning CDCUart
bool recv_pause_
背压标志:true 表示 OUT 未 rearm / Backpressure flag: OUT not rearmed
void OnRxDequeue(bool in_isr) override
数据队列被消费时回调(解除背压并尝试恢复 OUT rearm) Called when RX queue is dequeued (lift backpressure and try to rearm ...
EPNumber
端点号 Endpoint number
@ EP_AUTO
自动分配端点号 / Auto allocate
USB端点池类 / USB endpoint pool class.
WritePort class for handling write operations.
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
void Reset()
Resets the WritePort.
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
UART 配置结构体 / UART configuration structure.
uint8_t stop_bits
停止位长度 / Number of stop bits
Parity parity
校验模式 / Parity mode
uint8_t data_bits
数据位长度 / Number of data bits
uint32_t baudrate
波特率 / Baud rate
ConstRawData data
Data buffer. 数据缓冲区。