8#include <initializer_list>
12#include "dev_core.hpp"
14#include "gs_usb_protocol.hpp"
15#include "libxr_def.hpp"
16#include "libxr_mem.hpp"
17#include "timebase.hpp"
18#include "usb/core/desc_cfg.hpp"
29template <std::
size_t CanChNum>
33 static_assert(CanChNum > 0 && CanChNum <= 255,
"CanChNum must be in (0, 255]");
34 static constexpr uint8_t CAN_CH_NUM =
static_cast<uint8_t
>(CanChNum);
37 static constexpr const char* DEFAULT_INTERFACE_STRING =
"XRUSB GS USB";
97 std::initializer_list<LibXR::CAN*> cans,
size_t rx_queue_size = 32,
98 size_t echo_queue_size = 32,
LibXR::GPIO* identify_gpio =
nullptr,
99 std::initializer_list<LibXR::GPIO*> termination_gpios = {},
101 const char* interface_string = DEFAULT_INTERFACE_STRING)
110 ASSERT(cans.size() == CAN_CH_NUM);
117 if (termination_gpios.size() == 0)
123 ASSERT(termination_gpios.size() == CAN_CH_NUM);
125 for (
auto* g : termination_gpios)
157 std::initializer_list<LibXR::FDCAN*> fd_cans,
size_t rx_queue_size = 32,
158 size_t echo_queue_size = 32,
LibXR::GPIO* identify_gpio =
nullptr,
159 std::initializer_list<LibXR::GPIO*> termination_gpios = {},
161 const char* interface_string = DEFAULT_INTERFACE_STRING)
171 ASSERT(fd_cans.size() == CAN_CH_NUM);
173 for (
auto* p : fd_cans)
180 if (termination_gpios.size() == 0)
186 ASSERT(termination_gpios.size() == CAN_CH_NUM);
188 for (
auto* g : termination_gpios)
230 desc_block_.
intf = {9,
231 static_cast<uint8_t
>(DescriptorType::INTERFACE),
241 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
247 desc_block_.
ep_in = {7,
248 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
254 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
411 uint16_t wLength, uint16_t wIndex,
417 auto req =
static_cast<GsUsb::BReq
>(bRequest);
422 case GsUsb::BReq::BT_CONST:
433 case GsUsb::BReq::BT_CONST_EXT:
448 case GsUsb::BReq::DEVICE_CONFIG:
459 case GsUsb::BReq::TIMESTAMP:
462 if (wLength <
sizeof(
ctrl_buf_.timestamp_us))
473 case GsUsb::BReq::GET_TERMINATION:
490 case GsUsb::BReq::GET_STATE:
497 GsUsb::CanState st = GsUsb::CanState::ERROR_ACTIVE;
501 auto* can =
cans_[wValue];
509 st = GsUsb::CanState::BUS_OFF;
513 st = GsUsb::CanState::ERROR_PASSIVE;
517 st = GsUsb::CanState::ERROR_WARNING;
521 st = GsUsb::CanState::ERROR_ACTIVE;
529 ctrl_buf_.dev_state.state =
static_cast<uint32_t
>(st);
533 if (wLength <
sizeof(
ctrl_buf_.dev_state))
544 case GsUsb::BReq::GET_USER_ID:
559 case GsUsb::BReq::HOST_FORMAT:
570 case GsUsb::BReq::BITTIMING:
582 case GsUsb::BReq::DATA_BITTIMING:
598 case GsUsb::BReq::MODE:
610 case GsUsb::BReq::BERR:
612 if (wLength !=
sizeof(uint32_t) || wValue >=
can_count_)
622 case GsUsb::BReq::IDENTIFY:
634 case GsUsb::BReq::SET_TERMINATION:
646 case GsUsb::BReq::SET_USER_ID:
648 if (wLength !=
sizeof(uint32_t))
673 auto req =
static_cast<GsUsb::BReq
>(bRequest);
677 case GsUsb::BReq::HOST_FORMAT:
684 case GsUsb::BReq::BITTIMING:
691 case GsUsb::BReq::DATA_BITTIMING:
702 case GsUsb::BReq::MODE:
709 case GsUsb::BReq::BERR:
710 if (data.
size_ !=
sizeof(uint32_t))
716 case GsUsb::BReq::IDENTIFY:
723 case GsUsb::BReq::SET_TERMINATION:
730 case GsUsb::BReq::SET_USER_ID:
731 if (data.
size_ !=
sizeof(uint32_t))
738 case GsUsb::BReq::DEVICE_CONFIG:
739 case GsUsb::BReq::BT_CONST:
740 case GsUsb::BReq::BT_CONST_EXT:
741 case GsUsb::BReq::TIMESTAMP:
742 case GsUsb::BReq::GET_TERMINATION:
743 case GsUsb::BReq::GET_STATE:
744 case GsUsb::BReq::GET_USER_ID:
762 if (self ==
nullptr || !self->
inited_)
777 if (self ==
nullptr || !self->
inited_)
803 const std::size_t RXLEN = data.
size_;
820 const bool IS_FD = (wh.
flags & GsUsb::CAN_FLAG_FD) != 0;
821 const uint8_t* payload =
reinterpret_cast<const uint8_t*
>(data.
addr_) +
WIRE_HDR_SIZE;
839 (void)
fdcans_[CH]->AddMessage(pack);
857 (void)
cans_[CH]->AddMessage(pack);
891 std::array<LibXR::CAN*, CanChNum>
cans_{};
892 std::array<LibXR::FDCAN*, CanChNum>
910 std::array<LibXR::GPIO*, CanChNum>
946 std::array<LibXR::CAN::Configuration, CanChNum>
948 std::array<LibXR::FDCAN::Configuration, CanChNum>
961 GsUsb::TerminationState::OFF};
978 std::array<uint8_t, WIRE_MAX_SIZE>
1102 if (fd_cfg.fd_mode.brs)
1104 qi.
hdr.
flags |= GsUsb::CAN_FLAG_BRS;
1106 if (fd_cfg.fd_mode.esi)
1108 qi.
hdr.
flags |= GsUsb::CAN_FLAG_ESI;
1227 ASSERT(
cans_[0] !=
nullptr);
1236 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1238 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1239 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1240 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1241 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID;
1278 ASSERT(
cans_[0] !=
nullptr);
1287 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1289 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1290 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1291 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1292 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID |
1293 GsUsb::CAN_FEAT_FD | GsUsb::CAN_FEAT_BT_CONST_EXT;
1346 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1348 const uint32_t FCLK =
cans_[ch]->GetClockFreq();
1351 cfg.bit_timing.brp =
bt.
brp;
1355 cfg.bit_timing.sjw =
bt.
sjw;
1357 if (
bt.
brp != 0u && TQ_NUM != 0u)
1359 cfg.bitrate = FCLK / (
bt.
brp * TQ_NUM);
1360 cfg.sample_point =
static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1365 cfg.sample_point = 0.0f;
1374 return cans_[ch]->SetConfig(cfg);
1393 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1395 const uint32_t FCLK =
fdcans_[ch]->GetClockFreq();
1400 fd_cfg.data_timing.brp =
bt.
brp;
1404 fd_cfg.data_timing.sjw =
bt.
sjw;
1406 if (
bt.
brp != 0u && TQ_NUM != 0u)
1408 fd_cfg.data_bitrate = FCLK / (
bt.
brp * TQ_NUM);
1409 fd_cfg.data_sample_point =
1410 static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1414 fd_cfg.data_bitrate = 0;
1415 fd_cfg.data_sample_point = 0.0f;
1418 return fdcans_[ch]->SetConfig(fd_cfg);
1431 switch (
static_cast<GsUsb::CanMode
>(
mode.
mode))
1433 case GsUsb::CanMode::RESET:
1438 case GsUsb::CanMode::START:
1451 cfg.mode.loopback = (
mode.
flags & GsUsb::GSCAN_MODE_LOOP_BACK) != 0;
1452 cfg.mode.listen_only = (
mode.
flags & GsUsb::GSCAN_MODE_LISTEN_ONLY) != 0;
1453 cfg.mode.triple_sampling = (
mode.
flags & GsUsb::GSCAN_MODE_TRIPLE_SAMPLE) != 0;
1454 cfg.mode.one_shot = (
mode.
flags & GsUsb::GSCAN_MODE_ONE_SHOT) != 0;
1465 fd_cfg.fd_mode.fd_enabled = (
mode.
flags & GsUsb::GSCAN_MODE_FD) != 0;
1466 (void)
fdcans_[ch]->SetConfig(fd_cfg);
1490 const bool ON = (
id.mode ==
static_cast<uint32_t
>(GsUsb::IdentifyMode::ON));
1508 term_state_[ch] =
static_cast<GsUsb::TerminationState
>(
1509 st.
state != 0 ?
static_cast<uint32_t
>(GsUsb::TerminationState::ON)
1510 :
static_cast<uint32_t
>(GsUsb::TerminationState::OFF));
1514 const bool ON = (
term_state_[ch] == GsUsb::TerminationState::ON);
1527 const uint32_t CID = wh.
can_id;
1528 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1529 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1533 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1538 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1561 const uint32_t CID = wh.
can_id;
1562 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1563 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1567 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1572 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1599 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1602 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1605 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1608 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1611 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1642 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1645 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1648 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1651 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1654 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1669 const uint8_t LEN = (pack.
len <= 64) ? pack.
len : 64;
1689 std::size_t cap)
const
1745 constexpr uint8_t LNX_CAN_ERR_CRTL_UNSPEC = 0x00;
1746 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_WARNING = 0x04;
1747 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_WARNING = 0x08;
1748 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_PASSIVE = 0x10;
1749 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_PASSIVE = 0x20;
1751 constexpr uint8_t LNX_CAN_ERR_PROT_UNSPEC = 0x00;
1752 constexpr uint8_t LNX_CAN_ERR_PROT_FORM = 0x02;
1753 constexpr uint8_t LNX_CAN_ERR_PROT_STUFF = 0x04;
1754 constexpr uint8_t LNX_CAN_ERR_PROT_BIT0 = 0x08;
1755 constexpr uint8_t LNX_CAN_ERR_PROT_BIT1 = 0x10;
1756 constexpr uint8_t LNX_CAN_ERR_PROT_TX = 0x80;
1758 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_UNSPEC = 0x00;
1759 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_ACK = 0x19;
1761 constexpr uint32_t LNX_CAN_ERR_CNT = 0x00000200U;
1763 bool ec_valid =
false;
1764 uint32_t txerr = 0, rxerr = 0;
1775 const uint8_t TXERR_U8 = (txerr > 255U) ? 255U :
static_cast<uint8_t
>(txerr);
1776 const uint8_t RXERR_U8 = (rxerr > 255U) ? 255U :
static_cast<uint8_t
>(rxerr);
1780 uint32_t cid = GsUsb::CAN_ERR_FLAG;
1781 std::array<uint8_t, 8> d{};
1784 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BUS_OFF:
1785 cid |= GsUsb::CAN_ERR_BUSOFF;
1788 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING:
1789 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE:
1791 cid |= GsUsb::CAN_ERR_CRTL;
1792 uint8_t ctrl = LNX_CAN_ERR_CRTL_UNSPEC;
1796 if (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1800 ctrl |= LNX_CAN_ERR_CRTL_TX_PASSIVE;
1804 ctrl |= LNX_CAN_ERR_CRTL_RX_PASSIVE;
1811 ctrl |= LNX_CAN_ERR_CRTL_TX_WARNING;
1815 ctrl |= LNX_CAN_ERR_CRTL_RX_WARNING;
1820 if (ctrl == LNX_CAN_ERR_CRTL_UNSPEC)
1822 ctrl = (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1823 ?
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_PASSIVE |
1824 LNX_CAN_ERR_CRTL_RX_PASSIVE)
1825 :
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_WARNING |
1826 LNX_CAN_ERR_CRTL_RX_WARNING);
1833 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ACK:
1834 cid |= GsUsb::CAN_ERR_ACK;
1835 cid |= GsUsb::CAN_ERR_PROT;
1836 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1837 d[3] = LNX_CAN_ERR_PROT_LOC_ACK;
1840 case LibXR::CAN::ErrorID::CAN_ERROR_ID_STUFF:
1841 cid |= GsUsb::CAN_ERR_PROT;
1842 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_STUFF | LNX_CAN_ERR_PROT_TX);
1843 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1846 case LibXR::CAN::ErrorID::CAN_ERROR_ID_FORM:
1847 cid |= GsUsb::CAN_ERR_PROT;
1848 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_FORM | LNX_CAN_ERR_PROT_TX);
1849 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1852 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT0:
1853 cid |= GsUsb::CAN_ERR_PROT;
1854 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT0 | LNX_CAN_ERR_PROT_TX);
1855 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1858 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT1:
1859 cid |= GsUsb::CAN_ERR_PROT;
1860 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT1 | LNX_CAN_ERR_PROT_TX);
1861 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1865 cid |= GsUsb::CAN_ERR_PROT;
1866 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1867 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1871 cid |= LNX_CAN_ERR_CNT;
1921 static constexpr uint8_t TABLE[16] = {0, 1, 2, 3, 4, 5, 6, 7,
1922 8, 12, 16, 20, 24, 32, 48, 64};
1923 return (dlc < 16) ? TABLE[dlc] : 64;
1974 return static_cast<uint32_t
>(key);
1991 (void)key.
Set(value);
static constexpr bool IsErrorId(uint32_t id) noexcept
判断 id 是否处于错误 ID 空间。Check if id is in error ID space.
@ EXTENDED
扩展数据帧(29-bit ID)。Extended data frame (29-bit ID).
@ REMOTE_EXTENDED
扩展远程帧。Extended remote frame.
@ STANDARD
标准数据帧(11-bit ID)。Standard data frame (11-bit ID).
@ REMOTE_STANDARD
标准远程帧。Standard remote frame.
@ ERROR
错误帧(虚拟事件)。Error frame (virtual event).
static constexpr ErrorID ToErrorID(uint32_t id) noexcept
将 id 解释为 ErrorID。Interpret id as ErrorID.
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
static Callback Create(CallableType fun, BoundArgType arg)
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
模板类,表示数据库中的具体键 (Template class representing a specific key in the database).
ErrorCode Set(Data data)
设置键的值并更新数据库 (Set the key's value and update the database).
数据库接口,提供键值存储和管理功能 (Database interface providing key-value storage and management).
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
virtual void Write(bool value)=0
写入 GPIO 引脚状态。Writes the GPIO pin state.
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
可写原始数据视图 / Mutable raw data view
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
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
uint8_t GetAddress() const
获取端点地址(方向 + 号) / Get endpoint address (dir + num)
@ OUT
输出方向 / OUT direction
virtual ErrorCode TransferMultiBulk(RawData &data)
Bulk 多包传输辅助接口 / Helper for multi-packet bulk transfer.
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
virtual void Close()=0
关闭端点 / Close endpoint
uint16_t MaxPacketSize() const
获取最大包长 / Get max packet size
State GetState() const
获取端点状态 / Get endpoint state
USB端点池类 / USB endpoint pool class.
ErrorCode Release(Endpoint *ep_info)
回收端点 / Release endpoint
ErrorCode Get(Endpoint *&ep_info, Endpoint::Direction direction, Endpoint::EPNumber ep_num)
分配端点 / Allocate endpoint
GsUsb 设备类,实现 Linux gs_usb 协议(经典 CAN + CAN FD) / GsUsb device class implementing Linux gs_usb protocol...
bool can_enabled_[CanChNum]
通道启用(classic) / Channel enabled (classic)
void ClassicPackToQueueItem(const LibXR::CAN::ClassicPack &pack, uint8_t ch, QueueItem &qi)
ClassicPack -> QueueItem / Convert ClassicPack to QueueItem.
ErrorCode HandleBitTiming(uint8_t ch, const GsUsb::DeviceBitTiming &bt)
处理 BITTIMING(仲裁相位) / Handle BITTIMING (arbitration phase)
union LibXR::USB::GsUsbClass::@14 ctrl_buf_
控制传输复用缓冲区 / Union buffer for control transfers
bool ErrorPackToHostErrorFrame(uint8_t ch, const LibXR::CAN::ClassicPack &err_pack, QueueItem &qi)
将 LibXR 错误帧转换为 Host 错误帧(SocketCAN 语义) / Convert LibXR error pack to host error frame (SocketCAN seman...
void SetUserIdToStorage(uint32_t value)
写入 USER_ID(RAM 或 Database) / Write USER_ID (RAM or Database)
bool inited_
是否已初始化 / Initialized
static void OnCanRxStatic(bool in_isr, CanRxCtx *ctx, const LibXR::CAN::ClassicPack &pack)
classic CAN RX 静态回调入口 / Static entry for classic CAN RX callback
static uint8_t LenToDlc(uint8_t len)
长度转 DLC(FD 表) / Length to DLC (FD table)
GsUsb::DeviceBitTiming bt
BITTIMING / DATA_BITTIMING.
ErrorCode HandleBerr(uint8_t ch, uint32_t berr_on)
处理 BERR 开关 / Handle BERR enable/disable
ErrorCode HandleMode(uint8_t ch, const GsUsb::DeviceMode &mode)
处理 MODE(启动/复位 + 标志位) / Handle MODE (start/reset + flags)
GsUsbClass(Endpoint::EPNumber data_in_ep_num, Endpoint::EPNumber data_out_ep_num, std::initializer_list< LibXR::FDCAN * > fd_cans, size_t rx_queue_size=32, size_t echo_queue_size=32, LibXR::GPIO *identify_gpio=nullptr, std::initializer_list< LibXR::GPIO * > termination_gpios={}, LibXR::Database *database=nullptr, const char *interface_string=DEFAULT_INTERFACE_STRING)
构造:FDCAN / Construct: FDCAN
static constexpr std::size_t WIRE_FD_DATA_SIZE
FD 数据长度 / FD data size.
const char * interface_string_
接口字符串 / Interface string
bool fd_can_rx_registered_
FD RX 回调是否已注册 / FD RX callback registered.
uint8_t can_count_
实际通道数 / Actual channel count
static constexpr std::size_t WIRE_CLASSIC_TS_SIZE
classic+ts 总长度 / Classic+ts total size
static void HostWireToClassicPack(const WireHeader &wh, const uint8_t *payload, LibXR::CAN::ClassicPack &pack)
wire -> ClassicPack / Convert wire frame to ClassicPack
bool OwnsEndpoint(uint8_t ep_addr) const override
判断端点地址是否属于本类 / Check whether an endpoint belongs to this class
GsUsb::Identify identify
IDENTIFY.
LibXR::Callback< LibXR::ConstRawData & > on_data_out_cb_
OUT 回调 / OUT callback.
std::array< LibXR::FDCAN *, CanChNum > fdcans_
FDCAN 通道列表 / FDCAN channel pointers.
std::array< LibXR::CAN::Configuration, CanChNum > config_
经典 CAN 配置 / Classic CAN configuration
LibXR::SPSCQueue< QueueItem > echo_queue_
Echo 队列(回送 echo_id) / Echo queue (echo back echo_id)
GsUsb::DeviceTerminationState term
SET_TERMINATION / GET_TERMINATION.
Endpoint::EPNumber data_out_ep_num_
Bulk OUT 端点号 / Bulk OUT endpoint number.
std::array< LibXR::CAN *, CanChNum > cans_
CAN 通道列表 / CAN channel pointers.
bool berr_enabled_[CanChNum]
错误报告启用 / Bus error reporting enabled
GsUsb::TerminationState term_state_[CanChNum]
终端电阻状态 / Termination state
static constexpr std::size_t WIRE_HDR_SIZE
Header 长度 / Header size.
bool can_rx_registered_
classic RX 回调是否已注册 / Classic RX callback registered
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
释放端点资源并复位状态 / Release endpoint resources and reset state
static constexpr std::size_t WIRE_FD_TS_SIZE
FD+ts 总长度 / FD+ts total size.
GsUsb::HostConfig host_cfg
HOST_FORMAT.
static uint8_t DlcToLen(uint8_t dlc)
DLC 转长度(FD 表) / DLC to length (FD table)
bool HasAnyTerminationGpio() const
是否存在任意 termination GPIO / Whether any termination GPIO exists
ErrorCode HandleHostFormat(const GsUsb::HostConfig &cfg)
处理 HOST_FORMAT / Handle HOST_FORMAT
LibXR::Callback< LibXR::ConstRawData & > on_data_in_cb_
IN 回调 / IN callback.
const char * GetInterfaceString(size_t local_interface_index) const override
返回本类暴露的第 N 个接口字符串 Return the string for the Nth local interface exposed by this class.
static constexpr std::size_t WIRE_TS_SIZE
时间戳字段长度 / Timestamp field size
GsUsb::DeviceConfig dev_cfg_
设备配置 / Device configuration
std::array< uint8_t, WIRE_MAX_SIZE > tx_buf_
IN 发送暂存区 / IN transmit staging buffer.
void OnFdCanRx(bool in_isr, uint8_t ch, const LibXR::FDCAN::FDPack &pack)
FD CAN RX 处理 / Handle FD CAN RX.
LibXR::CAN::Callback can_rx_cb_[CanChNum]
classic RX 回调数组 / Classic RX callbacks
LibXR::Database * database_
void OnDataInComplete(bool in_isr, ConstRawData &data)
Bulk IN 完成处理(Device->Host) / Handle Bulk IN completion (Device->Host)
Endpoint * ep_data_in_
Bulk IN 端点对象 / Bulk IN endpoint object.
static constexpr std::size_t WIRE_FD_SIZE
FD 总长度 / FD total size.
ErrorCode HandleDataBitTiming(uint8_t ch, const GsUsb::DeviceBitTiming &bt)
处理 DATA_BITTIMING(数据相位) / Handle DATA_BITTIMING (data phase)
static constexpr std::size_t WIRE_CLASSIC_SIZE
classic 总长度 / Classic total size
GsUsb::DeviceBTConstExtended bt_const_ext_
BT 常量(扩展/FD) / BT constants (extended/FD)
LIBXR_PACKED_END uint8_t rx_buf_[WIRE_MAX_SIZE]
OUT 接收缓冲区 / OUT receive buffer.
FdCanRxCtx fd_can_rx_ctx_[CanChNum]
FD RX 上下文数组 / FD RX contexts.
LibXR::SPSCQueue< QueueItem > rx_queue_
RX 队列(Device->Host) / RX queue (Device->Host)
uint32_t user_id
GET_USER_ID / SET_USER_ID.
void InitDeviceConfigFd()
初始化 FD 设备配置与能力位 / Initialize FD device config and feature bits
bool HasIAD() override
是否包含 IAD / Whether class has IAD
static void HostWireToFdPack(const WireHeader &wh, const uint8_t *payload, LibXR::FDCAN::FDPack &pack)
wire -> FDPack / Convert wire frame to FDPack
ErrorCode HandleSetTermination(uint8_t ch, const GsUsb::DeviceTerminationState &st)
处理 SET_TERMINATION / Handle SET_TERMINATION
std::array< LibXR::GPIO *, CanChNum > termination_gpios_
终端电阻 GPIO(可选) / Termination GPIOs (optional)
CanRxCtx can_rx_ctx_[CanChNum]
classic RX 上下文数组 / Classic RX contexts
std::array< LibXR::FDCAN::Configuration, CanChNum > fd_config_
FD 配置 / FD configuration.
static void OnDataOutCompleteStatic(bool in_isr, GsUsbClass *self, ConstRawData &data)
Bulk OUT 完成静态回调包装 / Static wrapper for Bulk OUT completion.
uint32_t GetUserIdFromStorage() const
读取 USER_ID(RAM 或 Database) / Read USER_ID (RAM or Database)
uint8_t ctrl_target_channel_
控制请求目标通道 / Control request target channel
GsUsb::DeviceMode mode
MODE.
ErrorCode OnClassData(bool in_isr, uint8_t bRequest, LibXR::ConstRawData &data) override
Vendor Request 的 DATA 阶段处理 / Handle DATA stage for vendor requests.
bool timestamps_enabled_ch_[CanChNum]
通道时间戳启用 / Per-channel timestamp enabled
bool IsHostFormatOK() const
Host 字节序协商是否通过 / Whether host format negotiation passed.
GsUsb::DeviceBTConst bt_const_
BT 常量(classic) / BT constants (classic)
uint32_t timestamp_us
TIMESTAMP.
size_t GetInterfaceCount() override
返回接口数量(实现侧固定 1) / Return interface count (fixed to 1)
static constexpr std::size_t WIRE_CLASSIC_DATA_SIZE
classic 数据长度 / Classic data size
uint8_t interface_num_
接口号 / Interface number
void TryKickTx(bool in_isr)
尝试启动 Bulk IN 发送 / Try to start Bulk IN transmit
ErrorCode OnVendorRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, DeviceClass::ControlTransferResult &result) override
Vendor Request(gs_usb BREQ)处理 / Handle vendor requests (gs_usb BREQ)
bool fd_enabled_[CanChNum]
通道启用(FD) / Channel enabled (FD)
void InitDeviceConfigClassic()
初始化 classic CAN 设备配置与能力位 / Initialize classic CAN device config and feature bits
bool EnqueueFrame(const QueueItem &qi, bool is_echo, bool in_isr)
入队并尝试触发发送 / Enqueue and try to trigger TX
LibXR::FDCAN::CallbackFD fd_can_rx_cb_[CanChNum]
FD RX 回调数组 / FD RX callbacks.
uint32_t MakeTimestampUs(uint8_t ch) const
获取通道时间戳(us, 32-bit) / Get per-channel timestamp (us, 32-bit)
Endpoint * ep_data_out_
Bulk OUT 端点对象 / Bulk OUT endpoint object.
static void OnDataInCompleteStatic(bool in_isr, GsUsbClass *self, ConstRawData &data)
Bulk IN 完成静态回调包装 / Static wrapper for Bulk IN completion.
ErrorCode HandleIdentify(uint8_t, const GsUsb::Identify &id)
处理 IDENTIFY / Handle IDENTIFY
size_t GetMaxConfigSize() override
返回描述符块最大长度 / Return max configuration descriptor block size
void OnDataOutComplete(bool in_isr, ConstRawData &data)
Bulk OUT 完成处理(Host->Device) / Handle Bulk OUT completion (Host->Device)
static LIBXR_PACKED_END constexpr uint32_t ECHO_ID_RX
RX 帧 echo_id 固定值 / Fixed echo_id for RX frames.
GsUsbClass(Endpoint::EPNumber data_in_ep_num, Endpoint::EPNumber data_out_ep_num, std::initializer_list< LibXR::CAN * > cans, size_t rx_queue_size=32, size_t echo_queue_size=32, LibXR::GPIO *identify_gpio=nullptr, std::initializer_list< LibXR::GPIO * > termination_gpios={}, LibXR::Database *database=nullptr, const char *interface_string=DEFAULT_INTERFACE_STRING)
构造:经典 CAN / Construct: Classic CAN
static constexpr std::size_t WIRE_MAX_SIZE
最大线缆帧长度 / Maximum wire frame size
GsUsb::DeviceState dev_state
GET_STATE.
LibXR::GPIO * identify_gpio_
Identify GPIO(可选) / Identify GPIO (optional)
bool host_format_ok_
HOST_FORMAT 是否通过 / HOST_FORMAT OK.
void OnCanRx(bool in_isr, uint8_t ch, const LibXR::CAN::ClassicPack &pack)
classic CAN RX 处理 / Handle classic CAN RX
static void OnFdCanRxStatic(bool in_isr, FdCanRxCtx *ctx, const LibXR::FDCAN::FDPack &pack)
FD CAN RX 静态回调入口 / Static entry for FD CAN RX callback.
void FdPackToQueueItem(const LibXR::FDCAN::FDPack &pack, uint8_t ch, QueueItem &qi)
FDPack -> QueueItem / Convert FDPack to QueueItem.
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化接口与端点资源 / Initialize interface and endpoints
Endpoint::EPNumber data_in_ep_num_
Bulk IN 端点号 / Bulk IN endpoint number.
std::size_t PackQueueItemToWire(const QueueItem &qi, uint8_t *out, std::size_t cap) const
QueueItem -> wire bytes / Convert QueueItem to wire bytes.
uint32_t user_id_ram_
USER_ID 的 RAM 备份 / USER_ID RAM backup.
void MaybeArmOutTransfer()
确保 Bulk OUT 保持挂起接收 / Ensure Bulk OUT is armed for receiving
bool fd_supported_
是否支持 FD / FD supported
uint32_t MakeTimestampUsGlobal() const
获取全局时间戳(us, 32-bit) / Get global timestamp (us, 32-bit)
ErrorCode OnClassRequest(bool, uint8_t, uint16_t, uint16_t, uint16_t, DeviceClass::ControlTransferResult &) override
标准 Class Request 处理(此类不支持) / Handle standard class request (not supported)
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
经典 CAN 帧数据结构。Classic CAN frame structure.
uint32_t id
CAN ID(11/29 bit 或 ErrorID)。CAN ID (11/29 bits or ErrorID).
uint8_t data[8]
数据载荷。Data payload (up to 8 bytes).
uint8_t dlc
有效数据长度(0~8)。Data length code (0–8).
CAN 配置参数。CAN configuration parameters.
CAN 当前错误状态快照(来自硬件计数器/状态机)。 Snapshot of current CAN controller error state (from HW counters/state).
bool bus_off
是否处于 BUS-OFF。True if controller is bus-off.
bool error_passive
是否处于 Error Passive。True if error-passive.
uint8_t tx_error_counter
发送错误计数 TEC。Transmit error counter (TEC).
bool error_warning
是否处于 Error Warning。True if error-warning.
uint8_t rx_error_counter
接收错误计数 REC。Receive error counter (REC).
CAN FD 帧数据结构。CAN FD frame structure.
uint32_t id
CAN ID。CAN ID.
uint8_t len
数据长度(0~64)。Data length (0–64 bytes).
uint8_t data[64]
数据载荷。Data payload.
端点描述符(7 字节)/ Endpoint descriptor (7 bytes)
接口描述符(9 字节)/ Interface descriptor (9 bytes)
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
uint32_t tseg1_min
TSEG1 最小 / Min TSEG1.
uint32_t tseg2_min
TSEG2 最小 / Min TSEG2.
uint32_t brp_min
BRP 最小 / Min BRP.
uint32_t tseg2_max
TSEG2 最大 / Max TSEG2.
uint32_t brp_max
BRP 最大 / Max BRP.
uint32_t sjw_max
SJW 最大 / Max SJW.
uint32_t tseg1_max
TSEG1 最大 / Max TSEG1.
uint32_t brp_inc
BRP 步进 / BRP increment.
扩展比特定时能力(含 FD 数据相位) / Extended timing capabilities (with FD data phase)
CanBitTimingConst btc
仲裁相位 / Arbitration phase
CanBitTimingConst dbtc
数据相位 / Data phase
uint32_t feature
CAN_FEAT_*(含 FD) / CAN_FEAT_* (with FD)
uint32_t fclk_can
CAN 时钟 / CAN clock.
设备比特定时能力(经典/仲裁) / Device bit timing capabilities (classic/arbitration)
uint32_t fclk_can
CAN 时钟 / CAN clock.
uint32_t feature
CAN_FEAT_*.
CanBitTimingConst btc
定时常量 / Timing constants
比特定时参数 / Bit timing parameters
uint32_t prop_seg
PROP_SEG.
uint32_t phase_seg1
PHASE_SEG1.
uint32_t phase_seg2
PHASE_SEG2.
设备配置(per-device) / Device configuration (per-device)
uint32_t sw_version
软件版本 / Software version
uint8_t reserved2
保留 / Reserved
uint32_t hw_version
硬件版本 / Hardware version
uint8_t reserved3
保留 / Reserved
uint8_t icount
CAN 通道数 - 1 / CAN channel count minus 1.
uint8_t reserved1
保留 / Reserved
通道模式设置(per-channel) / Channel mode configuration (per-channel)
uint32_t flags
GS_CAN_MODE_*.
通道状态(per-channel) / Channel state (per-channel)
终端电阻控制 / Termination control
uint32_t state
TerminationState.
主机配置(字节序协商) / Host configuration (byte order negotiation)
CAN RX 回调上下文 / CAN RX callback context.
uint8_t ch
通道号 / Channel index
GsUsbClass * self
实例指针 / Instance pointer
FDCAN RX 回调上下文 / FDCAN RX callback context.
GsUsbClass * self
实例指针 / Instance pointer
uint8_t ch
通道号 / Channel index
本类的接口与端点描述符块 / Descriptor block for interface and endpoints
InterfaceDescriptor intf
Interface 描述符 / Interface descriptor.
EndpointDescriptor ep_in
IN 端点描述符 / IN endpoint descriptor.
EndpointDescriptor ep_out
OUT 端点描述符 / OUT endpoint descriptor.
发送队列元素(包含 header/data/timestamp) / TX queue item (header/data/timestamp)
uint8_t data_len
payload 长度(8/64) / Payload length (8/64)
uint32_t timestamp_us
时间戳 / Timestamp
WireHeader hdr
线缆头 / Wire header
std::array< uint8_t, 64 > data
数据段 / Data bytes