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";
99 size_t rx_queue_size = 32,
size_t echo_queue_size = 32,
101 std::initializer_list<LibXR::GPIO*> termination_gpios = {},
103 const char* interface_string = DEFAULT_INTERFACE_STRING)
112 ASSERT(cans.size() == CAN_CH_NUM);
119 if (termination_gpios.size() == 0)
125 ASSERT(termination_gpios.size() == CAN_CH_NUM);
127 for (
auto* g : termination_gpios)
163 size_t rx_queue_size = 32,
size_t echo_queue_size = 32,
165 std::initializer_list<LibXR::GPIO*> termination_gpios = {},
167 const char* interface_string = DEFAULT_INTERFACE_STRING)
177 ASSERT(fd_cans.size() == CAN_CH_NUM);
179 for (
auto* p : fd_cans)
186 if (termination_gpios.size() == 0)
192 ASSERT(termination_gpios.size() == CAN_CH_NUM);
194 for (
auto* g : termination_gpios)
235 desc_block_.
intf = {9,
236 static_cast<uint8_t
>(DescriptorType::INTERFACE),
246 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
252 desc_block_.
ep_in = {7,
253 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
259 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
416 uint16_t wLength, uint16_t wIndex,
422 auto req =
static_cast<GsUsb::BReq
>(bRequest);
427 case GsUsb::BReq::BT_CONST:
438 case GsUsb::BReq::BT_CONST_EXT:
453 case GsUsb::BReq::DEVICE_CONFIG:
464 case GsUsb::BReq::TIMESTAMP:
467 if (wLength <
sizeof(
ctrl_buf_.timestamp_us))
478 case GsUsb::BReq::GET_TERMINATION:
495 case GsUsb::BReq::GET_STATE:
502 GsUsb::CanState st = GsUsb::CanState::ERROR_ACTIVE;
506 auto* can =
cans_[wValue];
514 st = GsUsb::CanState::BUS_OFF;
518 st = GsUsb::CanState::ERROR_PASSIVE;
522 st = GsUsb::CanState::ERROR_WARNING;
526 st = GsUsb::CanState::ERROR_ACTIVE;
534 ctrl_buf_.dev_state.state =
static_cast<uint32_t
>(st);
538 if (wLength <
sizeof(
ctrl_buf_.dev_state))
549 case GsUsb::BReq::GET_USER_ID:
564 case GsUsb::BReq::HOST_FORMAT:
575 case GsUsb::BReq::BITTIMING:
587 case GsUsb::BReq::DATA_BITTIMING:
603 case GsUsb::BReq::MODE:
615 case GsUsb::BReq::BERR:
617 if (wLength !=
sizeof(uint32_t) || wValue >=
can_count_)
627 case GsUsb::BReq::IDENTIFY:
639 case GsUsb::BReq::SET_TERMINATION:
651 case GsUsb::BReq::SET_USER_ID:
653 if (wLength !=
sizeof(uint32_t))
678 auto req =
static_cast<GsUsb::BReq
>(bRequest);
682 case GsUsb::BReq::HOST_FORMAT:
689 case GsUsb::BReq::BITTIMING:
696 case GsUsb::BReq::DATA_BITTIMING:
707 case GsUsb::BReq::MODE:
714 case GsUsb::BReq::BERR:
715 if (data.
size_ !=
sizeof(uint32_t))
721 case GsUsb::BReq::IDENTIFY:
728 case GsUsb::BReq::SET_TERMINATION:
735 case GsUsb::BReq::SET_USER_ID:
736 if (data.
size_ !=
sizeof(uint32_t))
743 case GsUsb::BReq::DEVICE_CONFIG:
744 case GsUsb::BReq::BT_CONST:
745 case GsUsb::BReq::BT_CONST_EXT:
746 case GsUsb::BReq::TIMESTAMP:
747 case GsUsb::BReq::GET_TERMINATION:
748 case GsUsb::BReq::GET_STATE:
749 case GsUsb::BReq::GET_USER_ID:
767 if (self ==
nullptr || !self->
inited_)
782 if (self ==
nullptr || !self->
inited_)
808 const std::size_t RXLEN = data.
size_;
825 const bool IS_FD = (wh.
flags & GsUsb::CAN_FLAG_FD) != 0;
826 const uint8_t* payload =
reinterpret_cast<const uint8_t*
>(data.
addr_) +
WIRE_HDR_SIZE;
844 (void)
fdcans_[CH]->AddMessage(pack);
862 (void)
cans_[CH]->AddMessage(pack);
895 std::array<LibXR::CAN*, CanChNum>
cans_{};
896 std::array<LibXR::FDCAN*, CanChNum>
914 std::array<LibXR::GPIO*, CanChNum>
950 std::array<LibXR::CAN::Configuration, CanChNum>
952 std::array<LibXR::FDCAN::Configuration, CanChNum>
965 GsUsb::TerminationState::OFF};
982 std::array<uint8_t, WIRE_MAX_SIZE>
1106 if (fd_cfg.fd_mode.brs)
1108 qi.
hdr.
flags |= GsUsb::CAN_FLAG_BRS;
1110 if (fd_cfg.fd_mode.esi)
1112 qi.
hdr.
flags |= GsUsb::CAN_FLAG_ESI;
1231 ASSERT(
cans_[0] !=
nullptr);
1240 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1242 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1243 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1244 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1245 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID;
1282 ASSERT(
cans_[0] !=
nullptr);
1291 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1293 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1294 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1295 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1296 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID |
1297 GsUsb::CAN_FEAT_FD | GsUsb::CAN_FEAT_BT_CONST_EXT;
1350 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1352 const uint32_t FCLK =
cans_[ch]->GetClockFreq();
1355 cfg.bit_timing.brp =
bt.
brp;
1359 cfg.bit_timing.sjw =
bt.
sjw;
1361 if (
bt.
brp != 0u && TQ_NUM != 0u)
1363 cfg.bitrate = FCLK / (
bt.
brp * TQ_NUM);
1364 cfg.sample_point =
static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1369 cfg.sample_point = 0.0f;
1378 return cans_[ch]->SetConfig(cfg);
1397 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1399 const uint32_t FCLK =
fdcans_[ch]->GetClockFreq();
1404 fd_cfg.data_timing.brp =
bt.
brp;
1408 fd_cfg.data_timing.sjw =
bt.
sjw;
1410 if (
bt.
brp != 0u && TQ_NUM != 0u)
1412 fd_cfg.data_bitrate = FCLK / (
bt.
brp * TQ_NUM);
1413 fd_cfg.data_sample_point =
1414 static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1418 fd_cfg.data_bitrate = 0;
1419 fd_cfg.data_sample_point = 0.0f;
1422 return fdcans_[ch]->SetConfig(fd_cfg);
1435 switch (
static_cast<GsUsb::CanMode
>(
mode.
mode))
1437 case GsUsb::CanMode::RESET:
1442 case GsUsb::CanMode::START:
1455 cfg.mode.loopback = (
mode.
flags & GsUsb::GSCAN_MODE_LOOP_BACK) != 0;
1456 cfg.mode.listen_only = (
mode.
flags & GsUsb::GSCAN_MODE_LISTEN_ONLY) != 0;
1457 cfg.mode.triple_sampling = (
mode.
flags & GsUsb::GSCAN_MODE_TRIPLE_SAMPLE) != 0;
1458 cfg.mode.one_shot = (
mode.
flags & GsUsb::GSCAN_MODE_ONE_SHOT) != 0;
1469 fd_cfg.fd_mode.fd_enabled = (
mode.
flags & GsUsb::GSCAN_MODE_FD) != 0;
1470 (void)
fdcans_[ch]->SetConfig(fd_cfg);
1494 const bool ON = (
id.mode ==
static_cast<uint32_t
>(GsUsb::IdentifyMode::ON));
1512 term_state_[ch] =
static_cast<GsUsb::TerminationState
>(
1513 st.
state != 0 ?
static_cast<uint32_t
>(GsUsb::TerminationState::ON)
1514 :
static_cast<uint32_t
>(GsUsb::TerminationState::OFF));
1518 const bool ON = (
term_state_[ch] == GsUsb::TerminationState::ON);
1531 const uint32_t CID = wh.
can_id;
1532 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1533 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1537 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1542 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1565 const uint32_t CID = wh.
can_id;
1566 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1567 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1571 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1576 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1603 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1606 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1609 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1612 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1615 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1646 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1649 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1652 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1655 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1658 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1673 const uint8_t LEN = (pack.
len <= 64) ? pack.
len : 64;
1693 std::size_t cap)
const
1748 constexpr uint8_t LNX_CAN_ERR_CRTL_UNSPEC = 0x00;
1749 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_WARNING = 0x04;
1750 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_WARNING = 0x08;
1751 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_PASSIVE = 0x10;
1752 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_PASSIVE = 0x20;
1754 constexpr uint8_t LNX_CAN_ERR_PROT_UNSPEC = 0x00;
1755 constexpr uint8_t LNX_CAN_ERR_PROT_FORM = 0x02;
1756 constexpr uint8_t LNX_CAN_ERR_PROT_STUFF = 0x04;
1757 constexpr uint8_t LNX_CAN_ERR_PROT_BIT0 = 0x08;
1758 constexpr uint8_t LNX_CAN_ERR_PROT_BIT1 = 0x10;
1759 constexpr uint8_t LNX_CAN_ERR_PROT_TX = 0x80;
1761 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_UNSPEC = 0x00;
1762 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_ACK = 0x19;
1764 constexpr uint32_t LNX_CAN_ERR_CNT = 0x00000200U;
1766 bool ec_valid =
false;
1767 uint32_t txerr = 0, rxerr = 0;
1778 const uint8_t TXERR_U8 = (txerr > 255U) ? 255U :
static_cast<uint8_t
>(txerr);
1779 const uint8_t RXERR_U8 = (rxerr > 255U) ? 255U :
static_cast<uint8_t
>(rxerr);
1783 uint32_t cid = GsUsb::CAN_ERR_FLAG;
1784 std::array<uint8_t, 8> d{};
1787 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BUS_OFF:
1788 cid |= GsUsb::CAN_ERR_BUSOFF;
1791 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING:
1792 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE:
1794 cid |= GsUsb::CAN_ERR_CRTL;
1795 uint8_t ctrl = LNX_CAN_ERR_CRTL_UNSPEC;
1799 if (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1803 ctrl |= LNX_CAN_ERR_CRTL_TX_PASSIVE;
1807 ctrl |= LNX_CAN_ERR_CRTL_RX_PASSIVE;
1814 ctrl |= LNX_CAN_ERR_CRTL_TX_WARNING;
1818 ctrl |= LNX_CAN_ERR_CRTL_RX_WARNING;
1823 if (ctrl == LNX_CAN_ERR_CRTL_UNSPEC)
1825 ctrl = (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1826 ?
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_PASSIVE |
1827 LNX_CAN_ERR_CRTL_RX_PASSIVE)
1828 :
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_WARNING |
1829 LNX_CAN_ERR_CRTL_RX_WARNING);
1836 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ACK:
1837 cid |= GsUsb::CAN_ERR_ACK;
1838 cid |= GsUsb::CAN_ERR_PROT;
1839 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1840 d[3] = LNX_CAN_ERR_PROT_LOC_ACK;
1843 case LibXR::CAN::ErrorID::CAN_ERROR_ID_STUFF:
1844 cid |= GsUsb::CAN_ERR_PROT;
1845 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_STUFF | LNX_CAN_ERR_PROT_TX);
1846 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1849 case LibXR::CAN::ErrorID::CAN_ERROR_ID_FORM:
1850 cid |= GsUsb::CAN_ERR_PROT;
1851 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_FORM | LNX_CAN_ERR_PROT_TX);
1852 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1855 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT0:
1856 cid |= GsUsb::CAN_ERR_PROT;
1857 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT0 | LNX_CAN_ERR_PROT_TX);
1858 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1861 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT1:
1862 cid |= GsUsb::CAN_ERR_PROT;
1863 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT1 | LNX_CAN_ERR_PROT_TX);
1864 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1868 cid |= GsUsb::CAN_ERR_PROT;
1869 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1870 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1874 cid |= LNX_CAN_ERR_CNT;
1929 static constexpr uint8_t TABLE[16] = {0, 1, 2, 3, 4, 5, 6, 7,
1930 8, 12, 16, 20, 24, 32, 48, 64};
1931 return (dlc < 16) ? TABLE[dlc] : 64;
1982 return static_cast<uint32_t
>(key);
1999 (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)
常量原始数据封装类。 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).
模板类,表示数据库中的具体键 (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.
无锁队列实现 / Lock-free queue implementation
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
原始数据封装类。 A class for encapsulating raw data.
static Timebase * timebase
静态指针,用于存储全局时间基对象。 Static pointer storing the global timebase instance.
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
@ EP_AUTO
自动分配端点号 / Auto allocate
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 Get(Endpoint *&ep_info, Endpoint::Direction direction, Endpoint::EPNumber ep_num=Endpoint::EPNumber::EP_AUTO)
分配端点 / Allocate endpoint
ErrorCode Release(Endpoint *ep_info)
回收端点 / Release 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
LibXR::LockFreeQueue< QueueItem > echo_queue_
Echo 队列(回送 echo_id) / Echo queue (echo back echo_id)
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)
GsUsbClass(std::initializer_list< LibXR::CAN * > cans, Endpoint::EPNumber data_in_ep_num=Endpoint::EPNumber::EP1, Endpoint::EPNumber data_out_ep_num=Endpoint::EPNumber::EP2, 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
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)
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
GsUsb::DeviceTerminationState term
SET_TERMINATION / GET_TERMINATION.
LibXR::LockFreeQueue< QueueItem > rx_queue_
RX 队列(Device->Host) / RX queue (Device->Host)
Endpoint::EPNumber data_out_ep_num_
Bulk OUT 端点号 / Bulk OUT endpoint number.
GsUsbClass(std::initializer_list< LibXR::FDCAN * > fd_cans, Endpoint::EPNumber data_in_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber data_out_ep_num=Endpoint::EPNumber::EP_AUTO, 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
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 uint32_t ECHO_ID_RX
RX 帧 echo_id 固定值 / Fixed echo_id for RX frames.
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)
FdCanRxCtx fd_can_rx_ctx_[CanChNum]
FD RX 上下文数组 / FD RX contexts.
uint32_t user_id
GET_USER_ID / SET_USER_ID.
void InitDeviceConfigFd()
初始化 FD 设备配置与能力位 / Initialize FD device config and feature bits
uint8_t rx_buf_[WIRE_MAX_SIZE]
OUT 接收缓冲区 / OUT receive buffer.
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 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