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";
58 static constexpr uint32_t ECHO_ID_RX =
61 static constexpr std::size_t WIRE_HDR_SIZE =
63 static constexpr std::size_t WIRE_CLASSIC_DATA_SIZE =
65 static constexpr std::size_t WIRE_FD_DATA_SIZE = 64;
66 static constexpr std::size_t WIRE_TS_SIZE =
69 static constexpr std::size_t WIRE_CLASSIC_SIZE =
71 static constexpr std::size_t WIRE_CLASSIC_TS_SIZE =
72 WIRE_HDR_SIZE + 8 + 4;
73 static constexpr std::size_t WIRE_FD_SIZE =
75 static constexpr std::size_t WIRE_FD_TS_SIZE =
76 WIRE_HDR_SIZE + 64 + 4;
77 static constexpr std::size_t WIRE_MAX_SIZE =
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)
102 : data_in_ep_num_(data_in_ep_num),
103 data_out_ep_num_(data_out_ep_num),
104 identify_gpio_(identify_gpio),
106 rx_queue_(rx_queue_size),
107 echo_queue_(echo_queue_size),
108 interface_string_(interface_string)
110 ASSERT(cans.size() == CAN_CH_NUM);
117 if (termination_gpios.size() == 0)
119 termination_gpios_.fill(
nullptr);
123 ASSERT(termination_gpios.size() == CAN_CH_NUM);
125 for (
auto* g : termination_gpios)
127 termination_gpios_[i++] = g;
131 InitDeviceConfigClassic();
138 return (local_interface_index == 0u) ? interface_string_ :
nullptr;
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)
162 : fd_supported_(true),
163 data_in_ep_num_(data_in_ep_num),
164 data_out_ep_num_(data_out_ep_num),
165 identify_gpio_(identify_gpio),
167 rx_queue_(rx_queue_size),
168 echo_queue_(echo_queue_size),
169 interface_string_(interface_string)
171 ASSERT(fd_cans.size() == CAN_CH_NUM);
173 for (
auto* p : fd_cans)
180 if (termination_gpios.size() == 0)
182 termination_gpios_.fill(
nullptr);
186 ASSERT(termination_gpios.size() == CAN_CH_NUM);
188 for (
auto* g : termination_gpios)
190 termination_gpios_[i++] = g;
194 InitDeviceConfigFd();
214 interface_num_ = start_itf_num;
230 desc_block_.intf = {9,
231 static_cast<uint8_t
>(DescriptorType::INTERFACE),
240 desc_block_.ep_out = {7,
241 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
242 static_cast<uint8_t
>(ep_data_out_->
GetAddress()),
247 desc_block_.ep_in = {7,
248 static_cast<uint8_t
>(DescriptorType::ENDPOINT),
249 static_cast<uint8_t
>(ep_data_in_->
GetAddress()),
254 SetData(
RawData{
reinterpret_cast<uint8_t*
>(&desc_block_),
sizeof(desc_block_)});
259 host_format_ok_ =
false;
261 for (uint8_t i = 0; i < can_count_; ++i)
263 can_enabled_[i] =
false;
264 berr_enabled_[i] =
false;
265 fd_enabled_[i] =
false;
266 term_state_[i] = GsUsb::TerminationState::OFF;
267 timestamps_enabled_ch_[i] =
false;
271 if (!can_rx_registered_)
273 for (uint8_t ch = 0; ch < can_count_; ++ch)
280 can_rx_ctx_[ch].self =
this;
281 can_rx_ctx_[ch].ch = ch;
290 can_rx_registered_ =
true;
293 if (fd_supported_ && !fd_can_rx_registered_)
295 for (uint8_t ch = 0; ch < can_count_; ++ch)
302 fd_can_rx_ctx_[ch].self =
this;
303 fd_can_rx_ctx_[ch].ch = ch;
310 fd_can_rx_registered_ =
true;
314 MaybeArmOutTransfer();
325 host_format_ok_ =
false;
327 for (uint8_t i = 0; i < can_count_; ++i)
329 can_enabled_[i] =
false;
330 berr_enabled_[i] =
false;
331 fd_enabled_[i] =
false;
332 term_state_[i] = GsUsb::TerminationState::OFF;
333 timestamps_enabled_ch_[i] =
false;
338 ep_data_in_->
Close();
340 endpoint_pool.
Release(ep_data_in_);
341 ep_data_in_ =
nullptr;
346 ep_data_out_->
Close();
348 endpoint_pool.
Release(ep_data_out_);
349 ep_data_out_ =
nullptr;
379 return (ep_data_in_ && ep_data_in_->
GetAddress() == ep_addr) ||
380 (ep_data_out_ && ep_data_out_->
GetAddress() == ep_addr);
411 uint16_t wLength, uint16_t wIndex,
417 auto req =
static_cast<GsUsb::BReq
>(bRequest);
422 case GsUsb::BReq::BT_CONST:
424 if (wLength <
sizeof(bt_const_))
429 ConstRawData{
reinterpret_cast<const uint8_t*
>(&bt_const_),
sizeof(bt_const_)};
433 case GsUsb::BReq::BT_CONST_EXT:
439 if (wLength <
sizeof(bt_const_ext_))
444 sizeof(bt_const_ext_)};
448 case GsUsb::BReq::DEVICE_CONFIG:
450 if (wLength <
sizeof(dev_cfg_))
455 ConstRawData{
reinterpret_cast<const uint8_t*
>(&dev_cfg_),
sizeof(dev_cfg_)};
459 case GsUsb::BReq::TIMESTAMP:
461 ctrl_buf_.timestamp_us = MakeTimestampUsGlobal();
462 if (wLength <
sizeof(ctrl_buf_.timestamp_us))
468 ConstRawData{
reinterpret_cast<const uint8_t*
>(&ctrl_buf_.timestamp_us),
469 sizeof(ctrl_buf_.timestamp_us)};
473 case GsUsb::BReq::GET_TERMINATION:
475 if (wValue >= can_count_)
479 ctrl_buf_.term.state =
static_cast<uint32_t
>(term_state_[wValue]);
480 if (wLength <
sizeof(ctrl_buf_.term))
486 reinterpret_cast<const uint8_t*
>(&ctrl_buf_.term),
sizeof(ctrl_buf_.term)};
490 case GsUsb::BReq::GET_STATE:
492 if (wValue >= can_count_)
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);
530 ctrl_buf_.dev_state.rxerr = rxerr;
531 ctrl_buf_.dev_state.txerr = txerr;
533 if (wLength <
sizeof(ctrl_buf_.dev_state))
539 ConstRawData{
reinterpret_cast<const uint8_t*
>(&ctrl_buf_.dev_state),
540 sizeof(ctrl_buf_.dev_state)};
544 case GsUsb::BReq::GET_USER_ID:
546 ctrl_buf_.user_id = GetUserIdFromStorage();
547 if (wLength <
sizeof(ctrl_buf_.user_id))
553 ConstRawData{
reinterpret_cast<const uint8_t*
>(&ctrl_buf_.user_id),
554 sizeof(ctrl_buf_.user_id)};
559 case GsUsb::BReq::HOST_FORMAT:
570 case GsUsb::BReq::BITTIMING:
576 ctrl_target_channel_ =
static_cast<uint8_t
>(wValue);
582 case GsUsb::BReq::DATA_BITTIMING:
592 ctrl_target_channel_ =
static_cast<uint8_t
>(wValue);
598 case GsUsb::BReq::MODE:
604 ctrl_target_channel_ =
static_cast<uint8_t
>(wValue);
610 case GsUsb::BReq::BERR:
612 if (wLength !=
sizeof(uint32_t) || wValue >= can_count_)
616 ctrl_target_channel_ =
static_cast<uint8_t
>(wValue);
618 RawData{
reinterpret_cast<uint8_t*
>(&ctrl_buf_.berr_on),
sizeof(uint32_t)};
622 case GsUsb::BReq::IDENTIFY:
628 ctrl_target_channel_ =
static_cast<uint8_t
>(wValue);
634 case GsUsb::BReq::SET_TERMINATION:
640 ctrl_target_channel_ =
static_cast<uint8_t
>(wValue);
646 case GsUsb::BReq::SET_USER_ID:
648 if (wLength !=
sizeof(uint32_t))
653 RawData{
reinterpret_cast<uint8_t*
>(&ctrl_buf_.user_id),
sizeof(uint32_t)};
673 auto req =
static_cast<GsUsb::BReq
>(bRequest);
677 case GsUsb::BReq::HOST_FORMAT:
682 return HandleHostFormat(ctrl_buf_.host_cfg);
684 case GsUsb::BReq::BITTIMING:
689 return HandleBitTiming(ctrl_target_channel_, ctrl_buf_.bt);
691 case GsUsb::BReq::DATA_BITTIMING:
700 return HandleDataBitTiming(ctrl_target_channel_, ctrl_buf_.bt);
702 case GsUsb::BReq::MODE:
707 return HandleMode(ctrl_target_channel_, ctrl_buf_.mode);
709 case GsUsb::BReq::BERR:
710 if (data.
size_ !=
sizeof(uint32_t))
714 return HandleBerr(ctrl_target_channel_, ctrl_buf_.berr_on);
716 case GsUsb::BReq::IDENTIFY:
721 return HandleIdentify(ctrl_target_channel_, ctrl_buf_.identify);
723 case GsUsb::BReq::SET_TERMINATION:
728 return HandleSetTermination(ctrl_target_channel_, ctrl_buf_.term);
730 case GsUsb::BReq::SET_USER_ID:
731 if (data.
size_ !=
sizeof(uint32_t))
735 SetUserIdToStorage(ctrl_buf_.user_id);
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_)
797 if (!host_format_ok_)
799 MaybeArmOutTransfer();
803 const std::size_t RXLEN = data.
size_;
804 if (RXLEN < WIRE_CLASSIC_SIZE)
806 MaybeArmOutTransfer();
811 const WireHeader& wh = *
reinterpret_cast<const WireHeader*
>(data.
addr_);
813 const uint8_t CH = wh.channel;
814 if (CH >= can_count_ || !cans_[CH])
816 MaybeArmOutTransfer();
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;
825 if (!fd_supported_ || !fdcans_[CH] || !fd_enabled_[CH])
827 MaybeArmOutTransfer();
831 if (RXLEN < WIRE_FD_SIZE)
833 MaybeArmOutTransfer();
838 HostWireToFdPack(wh, payload, pack);
839 (void)fdcans_[CH]->AddMessage(pack);
843 if (!can_enabled_[CH])
845 MaybeArmOutTransfer();
849 if (RXLEN < WIRE_CLASSIC_SIZE)
851 MaybeArmOutTransfer();
856 HostWireToClassicPack(wh, payload, pack);
857 (void)cans_[CH]->AddMessage(pack);
863 if (wh.echo_id != ECHO_ID_RX)
868 qi.data_len = IS_FD ? 64u : 8u;
869 qi.timestamp_us = MakeTimestampUs(CH);
871 (void)EnqueueFrame(qi,
true, in_isr);
874 MaybeArmOutTransfer();
891 std::array<LibXR::CAN*, CanChNum> cans_{};
892 std::array<LibXR::FDCAN*, CanChNum>
894 bool fd_supported_ =
false;
896 uint8_t can_count_ = CAN_CH_NUM;
901 Endpoint* ep_data_in_ =
nullptr;
902 Endpoint* ep_data_out_ =
nullptr;
904 bool inited_ =
false;
905 uint8_t interface_num_ = 0;
906 const char* interface_string_ =
nullptr;
910 std::array<LibXR::GPIO*, CanChNum>
911 termination_gpios_{};
915 uint32_t user_id_ram_ = 0;
925 GsUsb::DeviceConfig dev_cfg_{};
926 GsUsb::DeviceBTConst bt_const_{};
927 GsUsb::DeviceBTConstExtended
946 std::array<LibXR::CAN::Configuration, CanChNum>
948 std::array<LibXR::FDCAN::Configuration, CanChNum>
951 bool host_format_ok_ =
false;
953 bool can_enabled_[CanChNum] = {
955 bool berr_enabled_[CanChNum] = {
false};
956 bool fd_enabled_[CanChNum] = {
false};
958 bool timestamps_enabled_ch_[CanChNum] = {
960 GsUsb::TerminationState term_state_[CanChNum] = {
961 GsUsb::TerminationState::OFF};
962 uint8_t ctrl_target_channel_ =
969 struct GsUsbDescBlock
971 InterfaceDescriptor intf;
972 EndpointDescriptor ep_out;
973 EndpointDescriptor ep_in;
977 uint8_t rx_buf_[WIRE_MAX_SIZE]{};
978 std::array<uint8_t, WIRE_MAX_SIZE>
1002 bool can_rx_registered_ =
1004 CanRxCtx can_rx_ctx_[CanChNum]{};
1006 can_rx_cb_[CanChNum]{};
1008 bool fd_can_rx_registered_ =
1010 FdCanRxCtx fd_can_rx_ctx_[CanChNum]{};
1012 fd_can_rx_cb_[CanChNum]{};
1017 static void OnCanRxStatic(
bool in_isr, CanRxCtx* ctx,
1020 if (!ctx || !ctx->self || !ctx->self->inited_)
1024 ctx->self->OnCanRx(in_isr, ctx->ch, pack);
1030 static void OnFdCanRxStatic(
bool in_isr, FdCanRxCtx* ctx,
1033 if (!ctx || !ctx->self || !ctx->self->inited_)
1037 ctx->self->OnFdCanRx(in_isr, ctx->ch, pack);
1049 uint32_t timestamp_us;
1050 std::array<uint8_t, 64> data;
1063 if (ch >= can_count_ || !ep_data_in_)
1071 if (ErrorPackToHostErrorFrame(ch, pack, qi))
1073 (void)EnqueueFrame(qi,
false, in_isr);
1078 if (!can_enabled_[ch])
1084 ClassicPackToQueueItem(pack, ch, qi);
1085 (void)EnqueueFrame(qi,
false, in_isr);
1093 if (!fd_supported_ || ch >= can_count_ || !fd_enabled_[ch] || !ep_data_in_)
1099 FdPackToQueueItem(pack, ch, qi);
1101 const auto& fd_cfg = fd_config_[ch];
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;
1111 (void)EnqueueFrame(qi,
false, in_isr);
1122 bool EnqueueFrame(
const QueueItem& qi,
bool is_echo,
bool in_isr)
1133 MaybeArmOutTransfer();
1141 void TryKickTx(
bool in_isr)
1158 ec = rx_queue_.
Pop(qi);
1165 const std::size_t SEND_LEN = PackQueueItemToWire(qi, tx_buf_.data(), tx_buf_.size());
1171 RawData tx_raw{tx_buf_.data(), SEND_LEN};
1172 (void)ep_data_in_->TransferMultiBulk(tx_raw);
1174 MaybeArmOutTransfer();
1180 void MaybeArmOutTransfer()
1196 RawData rx_raw{rx_buf_,
static_cast<size_t>(WIRE_MAX_SIZE)};
1197 (void)ep_data_out_->TransferMultiBulk(rx_raw);
1207 bool HasAnyTerminationGpio()
const
1209 for (uint8_t i = 0; i < can_count_; ++i)
1211 if (termination_gpios_[i] !=
nullptr)
1223 void InitDeviceConfigClassic()
1225 can_count_ = CAN_CH_NUM;
1226 ASSERT(cans_[0] !=
nullptr);
1231 dev_cfg_.
icount =
static_cast<uint8_t
>(can_count_ - 1);
1235 const uint32_t FCLK = cans_[0]->GetClockFreq();
1237 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1238 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1239 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1240 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID;
1244 bt_const_.
feature |= GsUsb::CAN_FEAT_IDENTIFY;
1246 if (HasAnyTerminationGpio())
1248 bt_const_.
feature |= GsUsb::CAN_FEAT_TERMINATION;
1263 bt_const_ext_.
btc = bt_const_.
btc;
1264 bt_const_ext_.
dbtc = bt_const_.
btc;
1273 void InitDeviceConfigFd()
1275 can_count_ = CAN_CH_NUM;
1276 ASSERT(cans_[0] !=
nullptr);
1281 dev_cfg_.
icount =
static_cast<uint8_t
>(can_count_ - 1);
1285 const uint32_t FCLK = cans_[0]->GetClockFreq();
1287 bt_const_.
feature = GsUsb::CAN_FEAT_LISTEN_ONLY | GsUsb::CAN_FEAT_LOOP_BACK |
1288 GsUsb::CAN_FEAT_TRIPLE_SAMPLE | GsUsb::CAN_FEAT_ONE_SHOT |
1289 GsUsb::CAN_FEAT_HW_TIMESTAMP | GsUsb::CAN_FEAT_BERR_REPORTING |
1290 GsUsb::CAN_FEAT_GET_STATE | GsUsb::CAN_FEAT_USER_ID |
1291 GsUsb::CAN_FEAT_FD | GsUsb::CAN_FEAT_BT_CONST_EXT;
1295 bt_const_.
feature |= GsUsb::CAN_FEAT_IDENTIFY;
1297 if (HasAnyTerminationGpio())
1299 bt_const_.
feature |= GsUsb::CAN_FEAT_TERMINATION;
1314 bt_const_ext_.
btc = bt_const_.
btc;
1315 bt_const_ext_.
dbtc = bt_const_.
btc;
1326 ErrorCode HandleHostFormat(
const GsUsb::HostConfig& cfg)
1328 host_format_ok_ = (cfg.byte_order == 0x0000beefu);
1335 ErrorCode HandleBitTiming(uint8_t ch,
const GsUsb::DeviceBitTiming&
bt)
1337 if (!host_format_ok_ || ch >= can_count_ || !cans_[ch])
1344 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1346 const uint32_t FCLK = cans_[ch]->GetClockFreq();
1348 auto& cfg = config_[ch];
1349 cfg.bit_timing.brp =
bt.
brp;
1353 cfg.bit_timing.sjw =
bt.
sjw;
1355 if (
bt.
brp != 0u && TQ_NUM != 0u)
1357 cfg.bitrate = FCLK / (
bt.
brp * TQ_NUM);
1358 cfg.sample_point =
static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1363 cfg.sample_point = 0.0f;
1366 if (fd_supported_ && fdcans_[ch])
1368 auto& fd_cfg = fd_config_[ch];
1369 static_cast<CAN::Configuration&
>(fd_cfg) = cfg;
1372 return cans_[ch]->SetConfig(cfg);
1378 ErrorCode HandleDataBitTiming(uint8_t ch,
const GsUsb::DeviceBitTiming&
bt)
1380 if (!host_format_ok_)
1384 if (!fd_supported_ || ch >= can_count_ || !fdcans_[ch])
1391 const uint32_t TQ_NUM = 1u + TSEG1 + TSEG2;
1393 const uint32_t FCLK = fdcans_[ch]->GetClockFreq();
1395 auto& fd_cfg = fd_config_[ch];
1396 static_cast<CAN::Configuration&
>(fd_cfg) = config_[ch];
1398 fd_cfg.data_timing.brp =
bt.
brp;
1402 fd_cfg.data_timing.sjw =
bt.
sjw;
1404 if (
bt.
brp != 0u && TQ_NUM != 0u)
1406 fd_cfg.data_bitrate = FCLK / (
bt.
brp * TQ_NUM);
1407 fd_cfg.data_sample_point =
1408 static_cast<float>(1u + TSEG1) /
static_cast<float>(TQ_NUM);
1412 fd_cfg.data_bitrate = 0;
1413 fd_cfg.data_sample_point = 0.0f;
1416 return fdcans_[ch]->SetConfig(fd_cfg);
1422 ErrorCode HandleMode(uint8_t ch,
const GsUsb::DeviceMode&
mode)
1424 if (!host_format_ok_ || ch >= can_count_ || !cans_[ch])
1429 switch (
static_cast<GsUsb::CanMode
>(
mode.
mode))
1431 case GsUsb::CanMode::RESET:
1432 can_enabled_[ch] =
false;
1433 fd_enabled_[ch] =
false;
1436 case GsUsb::CanMode::START:
1437 can_enabled_[ch] =
true;
1438 if (fd_supported_ && fdcans_[ch] && (
mode.
flags & GsUsb::GSCAN_MODE_FD))
1440 fd_enabled_[ch] =
true;
1448 auto& cfg = config_[ch];
1449 cfg.mode.loopback = (
mode.
flags & GsUsb::GSCAN_MODE_LOOP_BACK) != 0;
1450 cfg.mode.listen_only = (
mode.
flags & GsUsb::GSCAN_MODE_LISTEN_ONLY) != 0;
1451 cfg.mode.triple_sampling = (
mode.
flags & GsUsb::GSCAN_MODE_TRIPLE_SAMPLE) != 0;
1452 cfg.mode.one_shot = (
mode.
flags & GsUsb::GSCAN_MODE_ONE_SHOT) != 0;
1454 timestamps_enabled_ch_[ch] = (
mode.
flags & GsUsb::GSCAN_MODE_HW_TIMESTAMP) != 0;
1455 berr_enabled_[ch] = (
mode.
flags & GsUsb::GSCAN_MODE_BERR_REPORTING) != 0;
1457 const ErrorCode EC = cans_[ch]->SetConfig(cfg);
1459 if (fd_supported_ && fdcans_[ch])
1461 auto& fd_cfg = fd_config_[ch];
1462 static_cast<CAN::Configuration&
>(fd_cfg) = cfg;
1463 fd_cfg.fd_mode.fd_enabled = (
mode.
flags & GsUsb::GSCAN_MODE_FD) != 0;
1464 (void)fdcans_[ch]->SetConfig(fd_cfg);
1475 if (ch >= can_count_)
1479 berr_enabled_[ch] = (
berr_on != 0);
1486 ErrorCode HandleIdentify(uint8_t,
const GsUsb::Identify&
id)
1488 const bool ON = (
id.mode ==
static_cast<uint32_t
>(GsUsb::IdentifyMode::ON));
1491 (void)identify_gpio_->
Write(ON);
1499 ErrorCode HandleSetTermination(uint8_t ch,
const GsUsb::DeviceTerminationState& st)
1501 if (ch >= can_count_)
1506 term_state_[ch] =
static_cast<GsUsb::TerminationState
>(
1507 st.state != 0 ?
static_cast<uint32_t
>(GsUsb::TerminationState::ON)
1508 :
static_cast<uint32_t
>(GsUsb::TerminationState::OFF));
1510 if (termination_gpios_[ch])
1512 const bool ON = (term_state_[ch] == GsUsb::TerminationState::ON);
1513 (void)termination_gpios_[ch]->Write(ON);
1522 static void HostWireToClassicPack(
const WireHeader& wh,
const uint8_t* payload,
1525 const uint32_t CID = wh.can_id;
1526 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1527 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1531 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1536 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1540 uint8_t dlc = wh.can_dlc;
1556 static void HostWireToFdPack(
const WireHeader& wh,
const uint8_t* payload,
1559 const uint32_t CID = wh.can_id;
1560 const bool IS_EFF = (CID & GsUsb::CAN_EFF_FLAG) != 0;
1561 const bool IS_RTR = (CID & GsUsb::CAN_RTR_FLAG) != 0;
1565 pack.
id = CID & GsUsb::CAN_EFF_MASK;
1570 pack.
id = CID & GsUsb::CAN_SFF_MASK;
1574 uint8_t len = DlcToLen(wh.can_dlc);
1597 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1600 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1603 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1606 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1609 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1613 qi.hdr.echo_id = ECHO_ID_RX;
1614 qi.hdr.can_id = cid;
1615 qi.hdr.can_dlc = (pack.
dlc <= 8u) ? pack.
dlc : 8u;
1616 qi.hdr.channel = ch;
1618 qi.hdr.reserved = 0;
1622 qi.timestamp_us = MakeTimestampUs(ch);
1625 if (qi.hdr.can_dlc > 0u)
1640 cid = (pack.
id & GsUsb::CAN_SFF_MASK);
1643 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG;
1646 cid = (pack.
id & GsUsb::CAN_SFF_MASK) | GsUsb::CAN_RTR_FLAG;
1649 cid = (pack.
id & GsUsb::CAN_EFF_MASK) | GsUsb::CAN_EFF_FLAG | GsUsb::CAN_RTR_FLAG;
1652 cid = pack.
id & GsUsb::CAN_SFF_MASK;
1656 qi.hdr.echo_id = ECHO_ID_RX;
1657 qi.hdr.can_id = cid;
1658 qi.hdr.can_dlc = LenToDlc(pack.
len);
1659 qi.hdr.channel = ch;
1660 qi.hdr.flags = GsUsb::CAN_FLAG_FD;
1661 qi.hdr.reserved = 0;
1665 qi.timestamp_us = MakeTimestampUs(ch);
1667 const uint8_t LEN = (pack.
len <= 64) ? pack.
len : 64;
1686 std::size_t PackQueueItemToWire(
const QueueItem& qi, uint8_t* out,
1687 std::size_t cap)
const
1689 if (cap < WIRE_HDR_SIZE)
1694 const uint8_t CH = qi.hdr.channel;
1695 const bool TS = (CH < can_count_) ? timestamps_enabled_ch_[CH] : false;
1696 const std::size_t PAYLOAD = qi.is_fd ? WIRE_FD_DATA_SIZE : WIRE_CLASSIC_DATA_SIZE;
1697 const std::size_t TOTAL = WIRE_HDR_SIZE + PAYLOAD + (TS ? WIRE_TS_SIZE : 0);
1709 Memory::FastCopy(out + WIRE_HDR_SIZE + PAYLOAD, &qi.timestamp_us, WIRE_TS_SIZE);
1727 if (ch >= can_count_ || !cans_[ch])
1731 if (!berr_enabled_[ch])
1743 constexpr uint8_t LNX_CAN_ERR_CRTL_UNSPEC = 0x00;
1744 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_WARNING = 0x04;
1745 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_WARNING = 0x08;
1746 constexpr uint8_t LNX_CAN_ERR_CRTL_RX_PASSIVE = 0x10;
1747 constexpr uint8_t LNX_CAN_ERR_CRTL_TX_PASSIVE = 0x20;
1749 constexpr uint8_t LNX_CAN_ERR_PROT_UNSPEC = 0x00;
1750 constexpr uint8_t LNX_CAN_ERR_PROT_FORM = 0x02;
1751 constexpr uint8_t LNX_CAN_ERR_PROT_STUFF = 0x04;
1752 constexpr uint8_t LNX_CAN_ERR_PROT_BIT0 = 0x08;
1753 constexpr uint8_t LNX_CAN_ERR_PROT_BIT1 = 0x10;
1754 constexpr uint8_t LNX_CAN_ERR_PROT_TX = 0x80;
1756 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_UNSPEC = 0x00;
1757 constexpr uint8_t LNX_CAN_ERR_PROT_LOC_ACK = 0x19;
1759 constexpr uint32_t LNX_CAN_ERR_CNT = 0x00000200U;
1761 bool ec_valid =
false;
1762 uint32_t txerr = 0, rxerr = 0;
1773 const uint8_t TXERR_U8 = (txerr > 255U) ? 255U : static_cast<uint8_t>(txerr);
1774 const uint8_t RXERR_U8 = (rxerr > 255U) ? 255U :
static_cast<uint8_t
>(rxerr);
1778 uint32_t cid = GsUsb::CAN_ERR_FLAG;
1779 std::array<uint8_t, 8> d{};
1782 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BUS_OFF:
1783 cid |= GsUsb::CAN_ERR_BUSOFF;
1786 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_WARNING:
1787 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE:
1789 cid |= GsUsb::CAN_ERR_CRTL;
1790 uint8_t ctrl = LNX_CAN_ERR_CRTL_UNSPEC;
1794 if (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1798 ctrl |= LNX_CAN_ERR_CRTL_TX_PASSIVE;
1802 ctrl |= LNX_CAN_ERR_CRTL_RX_PASSIVE;
1809 ctrl |= LNX_CAN_ERR_CRTL_TX_WARNING;
1813 ctrl |= LNX_CAN_ERR_CRTL_RX_WARNING;
1818 if (ctrl == LNX_CAN_ERR_CRTL_UNSPEC)
1820 ctrl = (EID == LibXR::CAN::ErrorID::CAN_ERROR_ID_ERROR_PASSIVE)
1821 ?
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_PASSIVE |
1822 LNX_CAN_ERR_CRTL_RX_PASSIVE)
1823 :
static_cast<uint8_t
>(LNX_CAN_ERR_CRTL_TX_WARNING |
1824 LNX_CAN_ERR_CRTL_RX_WARNING);
1831 case LibXR::CAN::ErrorID::CAN_ERROR_ID_ACK:
1832 cid |= GsUsb::CAN_ERR_ACK;
1833 cid |= GsUsb::CAN_ERR_PROT;
1834 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1835 d[3] = LNX_CAN_ERR_PROT_LOC_ACK;
1838 case LibXR::CAN::ErrorID::CAN_ERROR_ID_STUFF:
1839 cid |= GsUsb::CAN_ERR_PROT;
1840 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_STUFF | LNX_CAN_ERR_PROT_TX);
1841 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1844 case LibXR::CAN::ErrorID::CAN_ERROR_ID_FORM:
1845 cid |= GsUsb::CAN_ERR_PROT;
1846 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_FORM | LNX_CAN_ERR_PROT_TX);
1847 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1850 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT0:
1851 cid |= GsUsb::CAN_ERR_PROT;
1852 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT0 | LNX_CAN_ERR_PROT_TX);
1853 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1856 case LibXR::CAN::ErrorID::CAN_ERROR_ID_BIT1:
1857 cid |= GsUsb::CAN_ERR_PROT;
1858 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_BIT1 | LNX_CAN_ERR_PROT_TX);
1859 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1863 cid |= GsUsb::CAN_ERR_PROT;
1864 d[2] =
static_cast<uint8_t
>(LNX_CAN_ERR_PROT_UNSPEC | LNX_CAN_ERR_PROT_TX);
1865 d[3] = LNX_CAN_ERR_PROT_LOC_UNSPEC;
1869 cid |= LNX_CAN_ERR_CNT;
1873 qi.hdr.echo_id = ECHO_ID_RX;
1874 qi.hdr.can_id = cid;
1875 qi.hdr.can_dlc = GsUsb::CAN_ERR_DLC;
1876 qi.hdr.channel = ch;
1878 qi.hdr.reserved = 0;
1882 qi.timestamp_us = MakeTimestampUs(ch);
1896 uint32_t MakeTimestampUs(uint8_t ch)
const
1898 if (ch < can_count_ && timestamps_enabled_ch_[ch])
1909 uint32_t MakeTimestampUsGlobal()
const
1917 static uint8_t DlcToLen(uint8_t dlc)
1919 static constexpr uint8_t TABLE[16] = {0, 1, 2, 3, 4, 5, 6, 7,
1920 8, 12, 16, 20, 24, 32, 48, 64};
1921 return (dlc < 16) ? TABLE[dlc] : 64;
1927 static uint8_t LenToDlc(uint8_t len)
1964 uint32_t GetUserIdFromStorage()
const
1966 if (database_ ==
nullptr)
1968 return user_id_ram_;
1972 return static_cast<uint32_t
>(key);
1979 void SetUserIdToStorage(uint32_t value)
1981 user_id_ram_ = value;
1983 if (database_ ==
nullptr)
1989 (void)key.Set(value);