8#include <initializer_list>
12#include "dev_core.hpp"
14#include "gs_usb_protocol.hpp"
15#include "libxr_def.hpp"
16#include "timebase.hpp"
17#include "usb/core/desc_cfg.hpp"
28template <std::
size_t CanChNum>
31 static_assert(CanChNum > 0 && CanChNum <= 255,
"CanChNum must be in (0, 255]");
32 static constexpr uint8_t CAN_CH_NUM =
static_cast<uint8_t
>(CanChNum);
92 size_t rx_queue_size = 32,
size_t echo_queue_size = 32,
94 std::initializer_list<LibXR::GPIO*> termination_gpios = {},
103 ASSERT(cans.size() == CAN_CH_NUM);
110 if (termination_gpios.size() == 0)
116 ASSERT(termination_gpios.size() == CAN_CH_NUM);
118 for (
auto* g : termination_gpios)
146 size_t rx_queue_size = 32,
size_t echo_queue_size = 32,
148 std::initializer_list<LibXR::GPIO*> termination_gpios = {},
158 ASSERT(fd_cans.size() == CAN_CH_NUM);
160 for (
auto* p : fd_cans)
167 if (termination_gpios.size() == 0)
173 ASSERT(termination_gpios.size() == CAN_CH_NUM);
175 for (
auto* g : termination_gpios)
204 ASSERT(ans == ErrorCode::OK);
207 ASSERT(ans == ErrorCode::OK);
215 desc_block_.
intf = {9,
216 static_cast<uint8_t
>(DescriptorType::INTERFACE),
226 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
232 desc_block_.
ep_in = {7,
233 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
239 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
382 return ErrorCode::NOT_SUPPORT;
396 uint16_t wLength, uint16_t wIndex,
402 auto req =
static_cast<GsUsb::BReq
>(bRequest);
407 case GsUsb::BReq::BT_CONST:
411 return ErrorCode::ARG_ERR;
415 return ErrorCode::OK;
418 case GsUsb::BReq::BT_CONST_EXT:
422 return ErrorCode::NOT_SUPPORT;
426 return ErrorCode::ARG_ERR;
430 return ErrorCode::OK;
433 case GsUsb::BReq::DEVICE_CONFIG:
437 return ErrorCode::ARG_ERR;
441 return ErrorCode::OK;
444 case GsUsb::BReq::TIMESTAMP:
447 if (wLength <
sizeof(
ctrl_buf_.timestamp_us))
449 return ErrorCode::ARG_ERR;
455 return ErrorCode::OK;
458 case GsUsb::BReq::GET_TERMINATION:
462 return ErrorCode::ARG_ERR;
467 return ErrorCode::ARG_ERR;
472 return ErrorCode::OK;
475 case GsUsb::BReq::GET_STATE:
479 return ErrorCode::ARG_ERR;
482 GsUsb::CanState st = GsUsb::CanState::ERROR_ACTIVE;
486 auto* can =
cans_[wValue];
490 if (can->GetErrorState(es) == ErrorCode::OK)
494 st = GsUsb::CanState::BUS_OFF;
498 st = GsUsb::CanState::ERROR_PASSIVE;
502 st = GsUsb::CanState::ERROR_WARNING;
506 st = GsUsb::CanState::ERROR_ACTIVE;
514 ctrl_buf_.dev_state.state =
static_cast<uint32_t
>(st);
518 if (wLength <
sizeof(
ctrl_buf_.dev_state))
520 return ErrorCode::ARG_ERR;
526 return ErrorCode::OK;
529 case GsUsb::BReq::GET_USER_ID:
534 return ErrorCode::ARG_ERR;
540 return ErrorCode::OK;
544 case GsUsb::BReq::HOST_FORMAT:
548 return ErrorCode::ARG_ERR;
552 return ErrorCode::OK;
555 case GsUsb::BReq::BITTIMING:
559 return ErrorCode::ARG_ERR;
564 return ErrorCode::OK;
567 case GsUsb::BReq::DATA_BITTIMING:
571 return ErrorCode::NOT_SUPPORT;
575 return ErrorCode::ARG_ERR;
580 return ErrorCode::OK;
583 case GsUsb::BReq::MODE:
587 return ErrorCode::ARG_ERR;
592 return ErrorCode::OK;
595 case GsUsb::BReq::BERR:
597 if (wLength !=
sizeof(uint32_t) || wValue >=
can_count_)
599 return ErrorCode::ARG_ERR;
604 return ErrorCode::OK;
607 case GsUsb::BReq::IDENTIFY:
611 return ErrorCode::ARG_ERR;
616 return ErrorCode::OK;
619 case GsUsb::BReq::SET_TERMINATION:
623 return ErrorCode::ARG_ERR;
628 return ErrorCode::OK;
631 case GsUsb::BReq::SET_USER_ID:
633 if (wLength !=
sizeof(uint32_t))
635 return ErrorCode::ARG_ERR;
639 return ErrorCode::OK;
643 return ErrorCode::NOT_SUPPORT;
658 auto req =
static_cast<GsUsb::BReq
>(bRequest);
662 case GsUsb::BReq::HOST_FORMAT:
665 return ErrorCode::ARG_ERR;
669 case GsUsb::BReq::BITTIMING:
672 return ErrorCode::ARG_ERR;
676 case GsUsb::BReq::DATA_BITTIMING:
679 return ErrorCode::NOT_SUPPORT;
683 return ErrorCode::ARG_ERR;
687 case GsUsb::BReq::MODE:
690 return ErrorCode::ARG_ERR;
694 case GsUsb::BReq::BERR:
695 if (data.
size_ !=
sizeof(uint32_t))
697 return ErrorCode::ARG_ERR;
701 case GsUsb::BReq::IDENTIFY:
704 return ErrorCode::ARG_ERR;
708 case GsUsb::BReq::SET_TERMINATION:
711 return ErrorCode::ARG_ERR;
715 case GsUsb::BReq::SET_USER_ID:
716 if (data.
size_ !=
sizeof(uint32_t))
718 return ErrorCode::ARG_ERR;
721 return ErrorCode::OK;
723 case GsUsb::BReq::DEVICE_CONFIG:
724 case GsUsb::BReq::BT_CONST:
725 case GsUsb::BReq::BT_CONST_EXT:
726 case GsUsb::BReq::TIMESTAMP:
727 case GsUsb::BReq::GET_TERMINATION:
728 case GsUsb::BReq::GET_STATE:
729 case GsUsb::BReq::GET_USER_ID:
730 return ErrorCode::OK;
733 return ErrorCode::NOT_SUPPORT;
783 const std::size_t RXLEN = data.
size_;
800 const bool IS_FD = (wh.
flags & GsUsb::CAN_FLAG_FD) != 0;
801 const uint8_t* payload =
reinterpret_cast<const uint8_t*
>(data.
addr_) +
WIRE_HDR_SIZE;
819 (void)
fdcans_[CH]->AddMessage(pack);
837 (void)
cans_[CH]->AddMessage(pack);
870 std::array<LibXR::CAN*, CanChNum>
cans_{};
871 std::array<LibXR::FDCAN*, CanChNum>
888 std::array<LibXR::GPIO*, CanChNum>
924 std::array<LibXR::CAN::Configuration, CanChNum>
926 std::array<LibXR::FDCAN::Configuration, CanChNum>
939 GsUsb::TerminationState::OFF};
956 std::array<uint8_t, WIRE_MAX_SIZE>
1080 if (fd_cfg.fd_mode.brs)
1082 qi.
hdr.
flags |= GsUsb::CAN_FLAG_BRS;
1084 if (fd_cfg.fd_mode.esi)
1086 qi.
hdr.
flags |= GsUsb::CAN_FLAG_ESI;
1105 if (EC != ErrorCode::OK)
1134 if (ec != ErrorCode::OK)
1137 if (ec != ErrorCode::OK)
1205 ASSERT(
cans_[0] !=
nullptr);
1214 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1216 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1217 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1218 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1219 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID;
1256 ASSERT(
cans_[0] !=
nullptr);
1265 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1267 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1268 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1269 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1270 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID |
1271 GsUsb::CAN_FEAT_FD | GsUsb::CAN_FEAT_BT_CONST_EXT;
1309 return ErrorCode::OK;
1319 return ErrorCode::ARG_ERR;
1324 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1326 const uint32_t FCLK =
cans_[ch]->GetClockFreq();
1329 cfg.bit_timing.brp =
bt.
brp;
1333 cfg.bit_timing.sjw =
bt.
sjw;
1335 if (
bt.
brp != 0u && TQ_NUM != 0u)
1337 cfg.bitrate = FCLK / (
bt.
brp * TQ_NUM);
1338 cfg.sample_point =
static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1343 cfg.sample_point = 0.0f;
1352 return cans_[ch]->SetConfig(cfg);
1362 return ErrorCode::ARG_ERR;
1366 return ErrorCode::NOT_SUPPORT;
1371 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1373 const uint32_t FCLK =
fdcans_[ch]->GetClockFreq();
1378 fd_cfg.data_timing.brp =
bt.
brp;
1382 fd_cfg.data_timing.sjw =
bt.
sjw;
1384 if (
bt.
brp != 0u && TQ_NUM != 0u)
1386 fd_cfg.data_bitrate = FCLK / (
bt.
brp * TQ_NUM);
1387 fd_cfg.data_sample_point =
1388 static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1392 fd_cfg.data_bitrate = 0;
1393 fd_cfg.data_sample_point = 0.0f;
1396 return fdcans_[ch]->SetConfig(fd_cfg);
1406 return ErrorCode::ARG_ERR;
1409 switch (
static_cast<GsUsb::CanMode
>(
mode.
mode))
1411 case GsUsb::CanMode::RESET:
1416 case GsUsb::CanMode::START:
1425 return ErrorCode::ARG_ERR;
1429 cfg.mode.loopback = (
mode.
flags & GsUsb::GSCAN_MODE_LOOP_BACK) != 0;
1430 cfg.mode.listen_only = (
mode.
flags & GsUsb::GSCAN_MODE_LISTEN_ONLY) != 0;
1431 cfg.mode.triple_sampling = (
mode.
flags & GsUsb::GSCAN_MODE_TRIPLE_SAMPLE) != 0;
1432 cfg.mode.one_shot = (
mode.
flags & GsUsb::GSCAN_MODE_ONE_SHOT) != 0;
1437 const ErrorCode EC =
cans_[ch]->SetConfig(cfg);
1443 fd_cfg.fd_mode.fd_enabled = (
mode.
flags & GsUsb::GSCAN_MODE_FD) != 0;
1444 (void)
fdcans_[ch]->SetConfig(fd_cfg);
1457 return ErrorCode::ARG_ERR;
1460 return ErrorCode::OK;
1468 const bool ON = (
id.mode ==
static_cast<uint32_t
>(GsUsb::IdentifyMode::ON));
1473 return ErrorCode::OK;
1483 return ErrorCode::ARG_ERR;
1486 term_state_[ch] =
static_cast<GsUsb::TerminationState
>(
1487 st.
state != 0 ?
static_cast<uint32_t
>(GsUsb::TerminationState::ON)
1488 :
static_cast<uint32_t
>(GsUsb::TerminationState::OFF));
1492 const bool ON = (
term_state_[ch] == GsUsb::TerminationState::ON);
1496 return ErrorCode::OK;
1505 const uint32_t CID = wh.
can_id;
1506 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1507 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1511 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1516 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1539 const uint32_t CID = wh.
can_id;
1540 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1541 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1545 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1550 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1577 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1580 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1583 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1586 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1589 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1620 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1623 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1626 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1629 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1632 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1647 const uint8_t LEN = (pack.
len <= 64) ? pack.
len : 64;
1667 std::size_t cap)
const
1721 constexpr uint8_t LNX_CAN_ERR_CRTL_UNSPEC = 0x00;
1722 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_WARNING = 0x04;
1723 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_WARNING = 0x08;
1724 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_PASSIVE = 0x10;
1725 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_PASSIVE = 0x20;
1727 constexpr uint8_t LNX_CAN_ERR_PROT_UNSPEC = 0x00;
1728 constexpr uint8_t LNX_CAN_ERR_PROT_FORM = 0x02;
1729 constexpr uint8_t LNX_CAN_ERR_PROT_STUFF = 0x04;
1730 constexpr uint8_t LNX_CAN_ERR_PROT_BIT0 = 0x08;
1731 constexpr uint8_t LNX_CAN_ERR_PROT_BIT1 = 0x10;
1732 constexpr uint8_t LNX_CAN_ERR_PROT_TX = 0x80;
1734 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_UNSPEC = 0x00;
1735 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_ACK = 0x19;
1737 constexpr uint32_t LNX_CAN_ERR_CNT = 0x00000200U;
1739 bool ec_valid =
false;
1740 uint32_t txerr = 0, rxerr = 0;
1743 if (
cans_[ch]->GetErrorState(es) == ErrorCode::OK)
1751 const uint8_t TXERR_U8 = (txerr > 255U) ? 255U :
static_cast<uint8_t
>(txerr);
1752 const uint8_t RXERR_U8 = (rxerr > 255U) ? 255U :
static_cast<uint8_t
>(rxerr);
1756 uint32_t cid = GsUsb::CAN_ERR_FLAG;
1757 std::array<uint8_t, 8> d{};
1760 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BUS_OFF:
1761 cid |= GsUsb::CAN_ERR_BUSOFF;
1764 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING:
1765 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE:
1767 cid |= GsUsb::CAN_ERR_CRTL;
1768 uint8_t ctrl = LNX_CAN_ERR_CRTL_UNSPEC;
1772 if (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1776 ctrl |= LNX_CAN_ERR_CRTL_TX_PASSIVE;
1780 ctrl |= LNX_CAN_ERR_CRTL_RX_PASSIVE;
1787 ctrl |= LNX_CAN_ERR_CRTL_TX_WARNING;
1791 ctrl |= LNX_CAN_ERR_CRTL_RX_WARNING;
1796 if (ctrl == LNX_CAN_ERR_CRTL_UNSPEC)
1798 ctrl = (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1799 ?
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_PASSIVE |
1800 LNX_CAN_ERR_CRTL_RX_PASSIVE)
1801 :
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_WARNING |
1802 LNX_CAN_ERR_CRTL_RX_WARNING);
1809 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ACK:
1810 cid |= GsUsb::CAN_ERR_ACK;
1811 cid |= GsUsb::CAN_ERR_PROT;
1812 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1813 d[3] = LNX_CAN_ERR_PROT_LOC_ACK;
1816 case LibXR::CAN::ErrorID::CAN_ERROR_ID_STUFF:
1817 cid |= GsUsb::CAN_ERR_PROT;
1818 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_STUFF | LNX_CAN_ERR_PROT_TX);
1819 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1822 case LibXR::CAN::ErrorID::CAN_ERROR_ID_FORM:
1823 cid |= GsUsb::CAN_ERR_PROT;
1824 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_FORM | LNX_CAN_ERR_PROT_TX);
1825 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1828 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT0:
1829 cid |= GsUsb::CAN_ERR_PROT;
1830 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT0 | LNX_CAN_ERR_PROT_TX);
1831 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1834 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT1:
1835 cid |= GsUsb::CAN_ERR_PROT;
1836 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT1 | LNX_CAN_ERR_PROT_TX);
1837 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1841 cid |= GsUsb::CAN_ERR_PROT;
1842 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1843 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1847 cid |= LNX_CAN_ERR_CNT;
1902 static constexpr uint8_t TABLE[16] = {0, 1, 2, 3, 4, 5, 6, 7,
1903 8, 12, 16, 20, 24, 32, 48, 64};
1904 return (dlc < 16) ? TABLE[dlc] : 64;
1955 return static_cast<uint32_t
>(key);
1972 (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(FunType fun, ArgType 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.
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)
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(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)
构造:经典 CAN / Construct: Classic CAN
static constexpr std::size_t WIRE_FD_DATA_SIZE
FD 数据长度 / FD data size.
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.
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)
构造:FDCAN / Construct: FDCAN
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.
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.
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)
经典 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