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)
203 ASSERT(ans == ErrorCode::OK);
206 ASSERT(ans == ErrorCode::OK);
214 desc_block_.
intf = {9,
215 static_cast<uint8_t
>(DescriptorType::INTERFACE),
225 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
231 desc_block_.
ep_in = {7,
232 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
238 SetData(
RawData{
reinterpret_cast<uint8_t *
>(&desc_block_),
sizeof(desc_block_)});
380 return ErrorCode::NOT_SUPPORT;
394 uint16_t wLength, uint16_t wIndex,
400 auto req =
static_cast<GsUsb::BReq
>(bRequest);
405 case GsUsb::BReq::BT_CONST:
409 return ErrorCode::ARG_ERR;
413 return ErrorCode::OK;
416 case GsUsb::BReq::BT_CONST_EXT:
420 return ErrorCode::NOT_SUPPORT;
424 return ErrorCode::ARG_ERR;
428 return ErrorCode::OK;
431 case GsUsb::BReq::DEVICE_CONFIG:
435 return ErrorCode::ARG_ERR;
439 return ErrorCode::OK;
442 case GsUsb::BReq::TIMESTAMP:
445 if (wLength <
sizeof(
ctrl_buf_.timestamp_us))
447 return ErrorCode::ARG_ERR;
453 return ErrorCode::OK;
456 case GsUsb::BReq::GET_TERMINATION:
460 return ErrorCode::ARG_ERR;
465 return ErrorCode::ARG_ERR;
470 return ErrorCode::OK;
473 case GsUsb::BReq::GET_STATE:
477 return ErrorCode::ARG_ERR;
480 GsUsb::CanState st = GsUsb::CanState::ERROR_ACTIVE;
484 auto *can =
cans_[wValue];
488 if (can->GetErrorState(es) == ErrorCode::OK)
492 st = GsUsb::CanState::BUS_OFF;
496 st = GsUsb::CanState::ERROR_PASSIVE;
500 st = GsUsb::CanState::ERROR_WARNING;
504 st = GsUsb::CanState::ERROR_ACTIVE;
512 ctrl_buf_.dev_state.state =
static_cast<uint32_t
>(st);
516 if (wLength <
sizeof(
ctrl_buf_.dev_state))
518 return ErrorCode::ARG_ERR;
524 return ErrorCode::OK;
527 case GsUsb::BReq::GET_USER_ID:
532 return ErrorCode::ARG_ERR;
538 return ErrorCode::OK;
542 case GsUsb::BReq::HOST_FORMAT:
546 return ErrorCode::ARG_ERR;
550 return ErrorCode::OK;
553 case GsUsb::BReq::BITTIMING:
557 return ErrorCode::ARG_ERR;
562 return ErrorCode::OK;
565 case GsUsb::BReq::DATA_BITTIMING:
569 return ErrorCode::NOT_SUPPORT;
573 return ErrorCode::ARG_ERR;
578 return ErrorCode::OK;
581 case GsUsb::BReq::MODE:
585 return ErrorCode::ARG_ERR;
590 return ErrorCode::OK;
593 case GsUsb::BReq::BERR:
595 if (wLength !=
sizeof(uint32_t) || wValue >=
can_count_)
597 return ErrorCode::ARG_ERR;
602 return ErrorCode::OK;
605 case GsUsb::BReq::IDENTIFY:
609 return ErrorCode::ARG_ERR;
614 return ErrorCode::OK;
617 case GsUsb::BReq::SET_TERMINATION:
621 return ErrorCode::ARG_ERR;
626 return ErrorCode::OK;
629 case GsUsb::BReq::SET_USER_ID:
631 if (wLength !=
sizeof(uint32_t))
633 return ErrorCode::ARG_ERR;
637 return ErrorCode::OK;
641 return ErrorCode::NOT_SUPPORT;
656 auto req =
static_cast<GsUsb::BReq
>(bRequest);
660 case GsUsb::BReq::HOST_FORMAT:
663 return ErrorCode::ARG_ERR;
667 case GsUsb::BReq::BITTIMING:
670 return ErrorCode::ARG_ERR;
674 case GsUsb::BReq::DATA_BITTIMING:
677 return ErrorCode::NOT_SUPPORT;
681 return ErrorCode::ARG_ERR;
685 case GsUsb::BReq::MODE:
688 return ErrorCode::ARG_ERR;
692 case GsUsb::BReq::BERR:
693 if (data.
size_ !=
sizeof(uint32_t))
695 return ErrorCode::ARG_ERR;
699 case GsUsb::BReq::IDENTIFY:
702 return ErrorCode::ARG_ERR;
706 case GsUsb::BReq::SET_TERMINATION:
709 return ErrorCode::ARG_ERR;
713 case GsUsb::BReq::SET_USER_ID:
714 if (data.
size_ !=
sizeof(uint32_t))
716 return ErrorCode::ARG_ERR;
719 return ErrorCode::OK;
721 case GsUsb::BReq::DEVICE_CONFIG:
722 case GsUsb::BReq::BT_CONST:
723 case GsUsb::BReq::BT_CONST_EXT:
724 case GsUsb::BReq::TIMESTAMP:
725 case GsUsb::BReq::GET_TERMINATION:
726 case GsUsb::BReq::GET_STATE:
727 case GsUsb::BReq::GET_USER_ID:
728 return ErrorCode::OK;
731 return ErrorCode::NOT_SUPPORT;
781 const std::size_t RXLEN = data.
size_;
798 const bool IS_FD = (wh.
flags & GsUsb::CAN_FLAG_FD) != 0;
799 const uint8_t *payload =
818 (void)
fdcans_[CH]->AddMessage(pack);
836 (void)
cans_[CH]->AddMessage(pack);
869 std::array<LibXR::CAN *, CanChNum>
cans_{};
870 std::array<LibXR::FDCAN *, CanChNum>
887 std::array<LibXR::GPIO *, CanChNum>
923 std::array<LibXR::CAN::Configuration, CanChNum>
925 std::array<LibXR::FDCAN::Configuration, CanChNum>
938 GsUsb::TerminationState::OFF};
955 std::array<uint8_t, WIRE_MAX_SIZE>
1079 if (fd_cfg.fd_mode.brs)
1081 qi.
hdr.
flags |= GsUsb::CAN_FLAG_BRS;
1083 if (fd_cfg.fd_mode.esi)
1085 qi.
hdr.
flags |= GsUsb::CAN_FLAG_ESI;
1104 if (EC != ErrorCode::OK)
1133 if (ec != ErrorCode::OK)
1136 if (ec != ErrorCode::OK)
1204 ASSERT(
cans_[0] !=
nullptr);
1213 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1215 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1216 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1217 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1218 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID;
1255 ASSERT(
cans_[0] !=
nullptr);
1264 const uint32_t FCLK =
cans_[0]->GetClockFreq();
1266 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1267 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1268 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1269 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID |
1270 GsUsb::CAN_FEAT_FD | GsUsb::CAN_FEAT_BT_CONST_EXT;
1308 return ErrorCode::OK;
1318 return ErrorCode::ARG_ERR;
1323 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1325 const uint32_t FCLK =
cans_[ch]->GetClockFreq();
1328 cfg.bit_timing.brp =
bt.
brp;
1332 cfg.bit_timing.sjw =
bt.
sjw;
1334 if (
bt.
brp != 0u && TQ_NUM != 0u)
1336 cfg.bitrate = FCLK / (
bt.
brp * TQ_NUM);
1337 cfg.sample_point =
static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1342 cfg.sample_point = 0.0f;
1351 return cans_[ch]->SetConfig(cfg);
1361 return ErrorCode::ARG_ERR;
1365 return ErrorCode::NOT_SUPPORT;
1370 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1372 const uint32_t FCLK =
fdcans_[ch]->GetClockFreq();
1377 fd_cfg.data_timing.brp =
bt.
brp;
1381 fd_cfg.data_timing.sjw =
bt.
sjw;
1383 if (
bt.
brp != 0u && TQ_NUM != 0u)
1385 fd_cfg.data_bitrate = FCLK / (
bt.
brp * TQ_NUM);
1386 fd_cfg.data_sample_point =
1387 static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1391 fd_cfg.data_bitrate = 0;
1392 fd_cfg.data_sample_point = 0.0f;
1395 return fdcans_[ch]->SetConfig(fd_cfg);
1405 return ErrorCode::ARG_ERR;
1408 switch (
static_cast<GsUsb::CanMode
>(
mode.
mode))
1410 case GsUsb::CanMode::RESET:
1415 case GsUsb::CanMode::START:
1424 return ErrorCode::ARG_ERR;
1428 cfg.mode.loopback = (
mode.
flags & GsUsb::GSCAN_MODE_LOOP_BACK) != 0;
1429 cfg.mode.listen_only = (
mode.
flags & GsUsb::GSCAN_MODE_LISTEN_ONLY) != 0;
1430 cfg.mode.triple_sampling = (
mode.
flags & GsUsb::GSCAN_MODE_TRIPLE_SAMPLE) != 0;
1431 cfg.mode.one_shot = (
mode.
flags & GsUsb::GSCAN_MODE_ONE_SHOT) != 0;
1436 const ErrorCode EC =
cans_[ch]->SetConfig(cfg);
1442 fd_cfg.fd_mode.fd_enabled = (
mode.
flags & GsUsb::GSCAN_MODE_FD) != 0;
1443 (void)
fdcans_[ch]->SetConfig(fd_cfg);
1456 return ErrorCode::ARG_ERR;
1459 return ErrorCode::OK;
1467 const bool ON = (
id.mode ==
static_cast<uint32_t
>(GsUsb::IdentifyMode::ON));
1472 return ErrorCode::OK;
1482 return ErrorCode::ARG_ERR;
1485 term_state_[ch] =
static_cast<GsUsb::TerminationState
>(
1486 st.
state != 0 ?
static_cast<uint32_t
>(GsUsb::TerminationState::ON)
1487 :
static_cast<uint32_t
>(GsUsb::TerminationState::OFF));
1491 const bool ON = (
term_state_[ch] == GsUsb::TerminationState::ON);
1495 return ErrorCode::OK;
1504 const uint32_t CID = wh.
can_id;
1505 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1506 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1510 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1515 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1538 const uint32_t CID = wh.
can_id;
1539 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1540 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1544 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1549 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1576 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1579 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1582 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1585 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1588 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1619 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1622 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1625 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1628 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1631 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1646 const uint8_t LEN = (pack.
len <= 64) ? pack.
len : 64;
1666 std::size_t cap)
const
1720 constexpr uint8_t LNX_CAN_ERR_CRTL_UNSPEC = 0x00;
1721 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_WARNING = 0x04;
1722 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_WARNING = 0x08;
1723 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_PASSIVE = 0x10;
1724 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_PASSIVE = 0x20;
1726 constexpr uint8_t LNX_CAN_ERR_PROT_UNSPEC = 0x00;
1727 constexpr uint8_t LNX_CAN_ERR_PROT_FORM = 0x02;
1728 constexpr uint8_t LNX_CAN_ERR_PROT_STUFF = 0x04;
1729 constexpr uint8_t LNX_CAN_ERR_PROT_BIT0 = 0x08;
1730 constexpr uint8_t LNX_CAN_ERR_PROT_BIT1 = 0x10;
1731 constexpr uint8_t LNX_CAN_ERR_PROT_TX = 0x80;
1733 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_UNSPEC = 0x00;
1734 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_ACK = 0x19;
1736 constexpr uint32_t LNX_CAN_ERR_CNT = 0x00000200U;
1738 bool ec_valid =
false;
1739 uint32_t txerr = 0, rxerr = 0;
1742 if (
cans_[ch]->GetErrorState(es) == ErrorCode::OK)
1750 const uint8_t TXERR_U8 = (txerr > 255U) ? 255U :
static_cast<uint8_t
>(txerr);
1751 const uint8_t RXERR_U8 = (rxerr > 255U) ? 255U :
static_cast<uint8_t
>(rxerr);
1755 uint32_t cid = GsUsb::CAN_ERR_FLAG;
1756 std::array<uint8_t, 8> d{};
1759 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BUS_OFF:
1760 cid |= GsUsb::CAN_ERR_BUSOFF;
1763 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING:
1764 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE:
1766 cid |= GsUsb::CAN_ERR_CRTL;
1767 uint8_t ctrl = LNX_CAN_ERR_CRTL_UNSPEC;
1771 if (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1775 ctrl |= LNX_CAN_ERR_CRTL_TX_PASSIVE;
1779 ctrl |= LNX_CAN_ERR_CRTL_RX_PASSIVE;
1786 ctrl |= LNX_CAN_ERR_CRTL_TX_WARNING;
1790 ctrl |= LNX_CAN_ERR_CRTL_RX_WARNING;
1795 if (ctrl == LNX_CAN_ERR_CRTL_UNSPEC)
1797 ctrl = (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1798 ?
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_PASSIVE |
1799 LNX_CAN_ERR_CRTL_RX_PASSIVE)
1800 :
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_WARNING |
1801 LNX_CAN_ERR_CRTL_RX_WARNING);
1808 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ACK:
1809 cid |= GsUsb::CAN_ERR_ACK;
1810 cid |= GsUsb::CAN_ERR_PROT;
1811 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1812 d[3] = LNX_CAN_ERR_PROT_LOC_ACK;
1815 case LibXR::CAN::ErrorID::CAN_ERROR_ID_STUFF:
1816 cid |= GsUsb::CAN_ERR_PROT;
1817 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_STUFF | LNX_CAN_ERR_PROT_TX);
1818 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1821 case LibXR::CAN::ErrorID::CAN_ERROR_ID_FORM:
1822 cid |= GsUsb::CAN_ERR_PROT;
1823 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_FORM | LNX_CAN_ERR_PROT_TX);
1824 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1827 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT0:
1828 cid |= GsUsb::CAN_ERR_PROT;
1829 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT0 | LNX_CAN_ERR_PROT_TX);
1830 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1833 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT1:
1834 cid |= GsUsb::CAN_ERR_PROT;
1835 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT1 | LNX_CAN_ERR_PROT_TX);
1836 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1840 cid |= GsUsb::CAN_ERR_PROT;
1841 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1842 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1846 cid |= LNX_CAN_ERR_CNT;
1901 static constexpr uint8_t TABLE[16] = {0, 1, 2, 3, 4, 5, 6, 7,
1902 8, 12, 16, 20, 24, 32, 48, 64};
1903 return (dlc < 16) ? TABLE[dlc] : 64;
1954 return static_cast<uint32_t
>(key);
1971 (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.
提供一个通用的回调包装,支持动态参数传递。 Provides a 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 ErrorCode 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 configuration item data
USB 设备类接口基类,所有自定义 USB 类(如 HID、CDC、MSC)都需派生自本类。 USB device class base interface, all custom device cla...
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)
std::array< LibXR::GPIO *, CanChNum > termination_gpios_
终端电阻 GPIO(可选) / Termination GPIOs (optional)
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)
void Deinit(EndpointPool &endpoint_pool) override
释放端点资源并复位状态 / Release endpoint resources and reset state
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
std::array< LibXR::CAN *, CanChNum > cans_
CAN 通道列表 / CAN channel pointers.
static constexpr std::size_t WIRE_FD_DATA_SIZE
FD 数据长度 / FD data size.
LibXR::Callback< LibXR::ConstRawData & > on_data_in_cb_
IN 回调 / IN callback.
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
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.
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
static constexpr std::size_t WIRE_FD_TS_SIZE
FD+ts 总长度 / FD+ts total size.
GsUsb::HostConfig host_cfg
HOST_FORMAT.
size_t GetInterfaceNum() override
返回接口数量(实现侧固定 1) / Return interface count (fixed to 1)
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
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.
ErrorCode OnClassRequest(bool, uint8_t, uint16_t, uint16_t, uint16_t, DeviceClass::RequestResult &) override
标准 Class Request 处理(此类不支持) / Handle standard class request (not supported)
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.
std::array< LibXR::FDCAN *, CanChNum > fdcans_
FDCAN 通道列表 / FDCAN channel pointers.
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
void Init(EndpointPool &endpoint_pool, uint8_t start_itf_num) override
初始化接口与端点资源 / Initialize interface and endpoints
ErrorCode OnVendorRequest(bool in_isr, uint8_t bRequest, uint16_t wValue, uint16_t wLength, uint16_t wIndex, DeviceClass::RequestResult &result) override
Vendor Request(gs_usb BREQ)处理 / Handle vendor requests (gs_usb BREQ)
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.
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
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.
LibXR::Callback< LibXR::ConstRawData & > on_data_out_cb_
OUT 回调 / OUT callback.
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.
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)
经典 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.
端点描述符结构体 Endpoint descriptor structure (USB 2.0 Spec 9.6.6)
接口描述符结构体 Interface descriptor structure (USB 2.0 Spec 9.6.5)
控制请求结果结构体 / Structure for control transfer results
RawData read_data
设备返回给主机的数据 / Data to read (to host)
ConstRawData write_data
主机写入设备的数据 / Data to write (from host)
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