libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
daplink_v1.hpp
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <cstring>
6
7#include "daplink_v1_def.hpp"
8#include "debug/swd.hpp"
9#include "gpio.hpp"
10#include "hid.hpp"
11#include "libxr_def.hpp"
12#include "libxr_mem.hpp"
13#include "libxr_type.hpp"
14#include "timebase.hpp"
15
16namespace LibXR::USB
17{
18
19static constexpr uint8_t DAPLINK_V1_REPORT_DESC[] = {
20 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
21 0x09, 0x01, // Usage (0x01)
22 0xA1, 0x01, // Collection (Application)
23 0x15, 0x00, // Logical Minimum (0)
24 0x26, 0xFF, 0x00, // Logical Maximum (255)
25 0x75, 0x08, // Report Size (8)
26 0x95, 0x40, // Report Count (64)
27 0x09, 0x01, // Usage (0x01)
28 0x81, 0x02, // Input (Data, Variable, Absolute)
29 0x95, 0x40, // Report Count (64)
30 0x09, 0x01, // Usage (0x01)
31 0x91, 0x02, // Output (Data, Variable, Absolute)
32 0x95, 0x40, // Report Count (64)
33 0x09, 0x01, // Usage (0x01)
34 0xB1, 0x02, // Feature (Data, Variable, Absolute)
35 0xC0 // End Collection
36};
37
38template <typename SwdPort>
40 : public HID<sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
41 DapLinkV1Def::MAX_RESPONSE_SIZE>
42{
43 public:
45 {
46 const char* vendor = nullptr;
47 const char* product = nullptr;
48 const char* serial = nullptr;
49 const char* firmware_ver = nullptr;
50
51 const char* device_vendor = nullptr;
52 const char* device_name = nullptr;
53 const char* board_vendor = nullptr;
54 const char* board_name = nullptr;
55 const char* product_fw_ver = nullptr;
56 };
57
58 explicit DapLinkV1Class(SwdPort& swd_link, LibXR::GPIO* nreset_gpio = nullptr,
61
62 ~DapLinkV1Class() override = default;
63
64 DapLinkV1Class(const DapLinkV1Class&) = delete;
65 DapLinkV1Class& operator=(const DapLinkV1Class&) = delete;
66
67 void SetInfoStrings(const InfoStrings& info);
68 const LibXR::USB::DapLinkV1Def::State& GetState() const;
69 bool IsInited() const;
70
71 protected:
73 ConstRawData GetReportDesc() override;
74
75 void BindEndpoints(EndpointPool& endpoint_pool, uint8_t start_itf_num,
76 bool in_isr) override;
77 void UnbindEndpoints(EndpointPool& endpoint_pool, bool in_isr) override;
78
79 void OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data) override;
80 void OnDataInComplete(bool in_isr, LibXR::ConstRawData& data) override;
81 ErrorCode OnSetReportData(bool in_isr, LibXR::ConstRawData& data) override;
82 ErrorCode OnGetInputReport(uint8_t report_id,
83 DeviceClass::ControlTransferResult& result) override;
84 ErrorCode OnGetFeatureReport(uint8_t report_id,
85 DeviceClass::ControlTransferResult& result) override;
86
87 private:
88 static void OnDataOutCompleteStatic(bool in_isr, DapLinkV1Class* self,
90 static void OnDataInCompleteStatic(bool in_isr, DapLinkV1Class* self,
92
93 uint16_t GetDapPacketSize() const;
94 uint16_t ClipResponseLength(uint16_t len, uint16_t cap) const;
95 static constexpr uint8_t NextRespQueueIndex(uint8_t idx);
96 void ResetResponseQueue();
97 bool HasDeferredResponseInEpBuffer() const;
98 void SetDeferredResponseInEpBuffer(uint16_t len);
99 bool SubmitDeferredResponseIfIdle();
100 bool IsResponseQueueEmpty() const;
101 bool IsResponseQueueFull() const;
102 bool TryBuildAndEnqueueResponse(bool in_isr, const uint8_t* req, uint16_t req_len);
103 uint8_t OutstandingResponseCount() const;
104 bool EnqueueResponse(const uint8_t* data, uint16_t len);
105 bool SubmitNextQueuedResponseIfIdle();
106 void ArmOutTransferIfIdle();
107 uint16_t PrepareResponseReport(uint8_t* resp, uint16_t payload_len, uint16_t cap);
108 void UpdateControlInputReport(const uint8_t* resp, uint16_t len);
109 ErrorCode HandleControlReportRequest(bool in_isr, const uint8_t* req, uint16_t req_len);
110 void HandleHostRequest(bool in_isr, const uint8_t* req, uint16_t req_len);
111
112 ErrorCode ProcessOneCommand(bool in_isr, const uint8_t* req, uint16_t req_len,
113 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
114 void BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
115
116 ErrorCode HandleInfo(bool in_isr, const uint8_t* req, uint16_t req_len, uint8_t* resp,
117 uint16_t resp_cap, uint16_t& out_len);
118 ErrorCode HandleHostStatus(bool in_isr, const uint8_t* req, uint16_t req_len,
119 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
120 ErrorCode HandleConnect(bool in_isr, const uint8_t* req, uint16_t req_len,
121 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
122 ErrorCode HandleDisconnect(bool in_isr, const uint8_t* req, uint16_t req_len,
123 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
124 ErrorCode HandleTransferConfigure(bool in_isr, const uint8_t* req, uint16_t req_len,
125 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
126 ErrorCode HandleTransfer(bool in_isr, const uint8_t* req, uint16_t req_len,
127 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
128 ErrorCode HandleTransferBlock(bool in_isr, const uint8_t* req, uint16_t req_len,
129 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
130 ErrorCode HandleTransferAbort(bool in_isr, const uint8_t* req, uint16_t req_len,
131 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
132 ErrorCode HandleWriteABORT(bool in_isr, const uint8_t* req, uint16_t req_len,
133 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
134 ErrorCode HandleDelay(bool in_isr, const uint8_t* req, uint16_t req_len, uint8_t* resp,
135 uint16_t resp_cap, uint16_t& out_len);
136 ErrorCode HandleResetTarget(bool in_isr, const uint8_t* req, uint16_t req_len,
137 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
138 ErrorCode HandleSWJPins(bool in_isr, const uint8_t* req, uint16_t req_len,
139 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
140 ErrorCode HandleSWJClock(bool in_isr, const uint8_t* req, uint16_t req_len,
141 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
142 ErrorCode HandleSWJSequence(bool in_isr, const uint8_t* req, uint16_t req_len,
143 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
144 ErrorCode HandleSWDConfigure(bool in_isr, const uint8_t* req, uint16_t req_len,
145 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
146 ErrorCode HandleSWDSequence(bool in_isr, const uint8_t* req, uint16_t req_len,
147 uint8_t* resp, uint16_t resp_cap, uint16_t& out_len);
148
149 ErrorCode BuildInfoStringResponse(uint8_t cmd, const char* str, uint8_t* resp,
150 uint16_t resp_cap, uint16_t& out_len);
151 ErrorCode BuildInfoU8Response(uint8_t cmd, uint8_t val, uint8_t* resp,
152 uint16_t resp_cap, uint16_t& out_len);
153 ErrorCode BuildInfoU16Response(uint8_t cmd, uint16_t val, uint8_t* resp,
154 uint16_t resp_cap, uint16_t& out_len);
155 ErrorCode BuildInfoU32Response(uint8_t cmd, uint32_t val, uint8_t* resp,
156 uint16_t resp_cap, uint16_t& out_len);
157
158 uint8_t MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack) const;
159 void SetTransferAbortFlag(bool on);
160
161 void DriveReset(bool release);
162 void DelayUsIfAllowed(bool in_isr, uint32_t us);
163
164 private:
165 template <typename E>
166 static constexpr uint8_t ToU8(E e)
167 {
168 return static_cast<uint8_t>(e);
169 }
170
171 static constexpr uint8_t DAP_OK = 0x00u;
172 static constexpr uint8_t DAP_ERROR = 0xFFu;
173
174 static inline ErrorCode BuildUnknowCmdResponse(uint8_t* resp, uint16_t cap,
175 uint16_t& out_len)
176 {
177 if (!resp || cap < 1u)
178 {
179 out_len = 0u;
181 }
182 resp[0] = 0xFFu;
183 out_len = 1u;
184 return ErrorCode::OK;
185 }
186
187 static constexpr uint16_t MAX_REQ = DapLinkV1Def::MAX_REQUEST_SIZE;
188 static constexpr uint16_t MAX_RESP = DapLinkV1Def::MAX_RESPONSE_SIZE;
189 static constexpr uint16_t DEFAULT_DAP_PACKET_SIZE = MAX_RESP;
190 static constexpr uint8_t PACKET_COUNT_ADVERTISED = 1u;
191 static constexpr uint8_t MAX_OUTSTANDING_RESPONSES = PACKET_COUNT_ADVERTISED;
192 static constexpr uint16_t MAX_DAP_PACKET_SIZE = MAX_RESP;
193 static constexpr uint16_t RESP_SLOT_SIZE = MAX_DAP_PACKET_SIZE;
194 static constexpr uint8_t RESP_QUEUE_DEPTH = PACKET_COUNT_ADVERTISED;
195 static_assert(RESP_SLOT_SIZE >= DEFAULT_DAP_PACKET_SIZE,
196 "RESP_SLOT_SIZE must cover HID packet size");
197 static_assert((RESP_QUEUE_DEPTH & (RESP_QUEUE_DEPTH - 1u)) == 0u,
198 "Response queue depth must be power-of-two");
199
201 {
202 uint16_t len = 0u;
203 uint8_t payload[RESP_SLOT_SIZE] = {};
204 };
205
206 SwdPort& swd_;
207 LibXR::GPIO* nreset_gpio_ = nullptr;
208
209 uint8_t swj_shadow_ = static_cast<uint8_t>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
210 DapLinkV1Def::DAP_SWJ_NRESET);
211 bool last_nreset_level_high_ = true;
212
214 InfoStrings info_{"XRobot", "DAPLinkV1", "00000001", "1.0.0", "XRUSB",
215 "XRDAP", "XRobot", "DAP_DEMO", "0.1.0"};
216
217 uint32_t swj_clock_hz_ = 1000000u;
218 uint32_t match_mask_ = 0xFFFFFFFFu;
219
220 Endpoint* ep_in_ = nullptr; // Cached HID IN endpoint
221 Endpoint* ep_out_ = nullptr; // Cached HID OUT endpoint
222
224 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataOutCompleteStatic, this);
226 LibXR::Callback<LibXR::ConstRawData&>::Create(OnDataInCompleteStatic, this);
227
228 bool inited_ = false;
229 ResponseSlot resp_q_[RESP_QUEUE_DEPTH] = {};
230 uint8_t resp_q_head_ = 0u;
231 uint8_t resp_q_tail_ = 0u;
232 uint8_t resp_q_count_ = 0u;
233 bool deferred_in_resp_valid_ = false;
234 uint16_t deferred_in_resp_len_ = 0u;
235 uint8_t control_input_report_[MAX_DAP_PACKET_SIZE] = {};
236 uint16_t control_input_report_len_ = DEFAULT_DAP_PACKET_SIZE;
237};
238
239template <typename SwdPort>
240DapLinkV1Class<SwdPort>::DapLinkV1Class(SwdPort& swd_link, LibXR::GPIO* nreset_gpio,
241 Endpoint::EPNumber in_ep_num,
242 Endpoint::EPNumber out_ep_num)
243 : HID(true, 1, 1, in_ep_num, out_ep_num), swd_(swd_link), nreset_gpio_(nreset_gpio)
244{
245 (void)swd_.SetClockHz(swj_clock_hz_);
246}
247
248template <typename SwdPort>
249void DapLinkV1Class<SwdPort>::SetInfoStrings(const InfoStrings& info)
250{
251 info_ = info;
252}
253
254template <typename SwdPort>
255const LibXR::USB::DapLinkV1Def::State& DapLinkV1Class<SwdPort>::GetState() const
256{
257 return dap_state_;
258}
259
260template <typename SwdPort>
261bool DapLinkV1Class<SwdPort>::IsInited() const
262{
263 return inited_;
264}
265
266template <typename SwdPort>
274
275template <typename SwdPort>
277{
278 return ConstRawData{DAPLINK_V1_REPORT_DESC, sizeof(DAPLINK_V1_REPORT_DESC)};
279}
280
281template <typename SwdPort>
283 uint8_t start_itf_num, bool in_isr)
284{
285 HID::BindEndpoints(endpoint_pool, start_itf_num, in_isr);
286
287 ep_in_ = GetInEndpoint();
288 ep_out_ = GetOutEndpoint();
289
290 if (ep_in_ != nullptr)
291 {
292 ep_in_->Configure(
294 ep_in_->SetOnTransferCompleteCallback(on_data_in_cb_);
295 }
296
297 if (ep_out_ != nullptr)
298 {
299 ep_out_->Configure(
301 ep_out_->SetOnTransferCompleteCallback(on_data_out_cb_);
302 }
303
304 inited_ = true;
305 match_mask_ = 0xFFFFFFFFu;
306
307 dap_state_ = {};
308 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
309 dap_state_.transfer_abort = false;
310 ResetResponseQueue();
311 if (ep_in_ != nullptr)
312 {
313 ep_in_->SetActiveLength(0);
314 }
315
316 swj_clock_hz_ = 1000000u;
317 (void)swd_.SetClockHz(swj_clock_hz_);
318
319 last_nreset_level_high_ = true;
320 swj_shadow_ = static_cast<uint8_t>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
321 DapLinkV1Def::DAP_SWJ_NRESET);
322
323 ArmOutTransferIfIdle();
324}
325
326template <typename SwdPort>
328{
329 inited_ = false;
330 ResetResponseQueue();
331
332 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
333 dap_state_.transfer_abort = false;
334
335 if (ep_in_ != nullptr)
336 {
337 ep_in_->SetActiveLength(0);
338 }
339 if (ep_out_ != nullptr)
340 {
341 ep_out_->SetActiveLength(0);
342 }
343
344 HID::UnbindEndpoints(endpoint_pool, in_isr);
345
346 ep_in_ = nullptr;
347 ep_out_ = nullptr;
348
349 swd_.Close();
350
351 last_nreset_level_high_ = true;
352 swj_shadow_ = static_cast<uint8_t>(DapLinkV1Def::DAP_SWJ_SWDIO_TMS |
353 DapLinkV1Def::DAP_SWJ_NRESET);
354}
355
356template <typename SwdPort>
359{
360 if (self && self->inited_)
361 {
362 self->OnDataOutComplete(in_isr, data);
363 }
364}
365
366template <typename SwdPort>
367void DapLinkV1Class<SwdPort>::OnDataInCompleteStatic(bool in_isr, DapLinkV1Class* self,
369{
370 if (self && self->inited_)
371 {
372 self->OnDataInComplete(in_isr, data);
373 }
374}
375
376template <typename SwdPort>
377void DapLinkV1Class<SwdPort>::OnDataOutComplete(bool in_isr, LibXR::ConstRawData& data)
378{
379 if (!inited_ || !ep_in_ || !ep_out_)
380 {
381 return;
382 }
383
384 ArmOutTransferIfIdle();
385 HandleHostRequest(in_isr, static_cast<const uint8_t*>(data.addr_),
386 static_cast<uint16_t>(data.size_));
387}
388
389template <typename SwdPort>
390void DapLinkV1Class<SwdPort>::OnDataInComplete(bool /*in_isr*/,
391 LibXR::ConstRawData& /*data*/)
392{
393 (void)SubmitDeferredResponseIfIdle();
394 (void)SubmitNextQueuedResponseIfIdle();
395 ArmOutTransferIfIdle();
396}
397
398template <typename SwdPort>
400{
401 (void)HID<sizeof(DAPLINK_V1_REPORT_DESC), DapLinkV1Def::MAX_REQUEST_SIZE,
402 DapLinkV1Def::MAX_RESPONSE_SIZE>::OnSetReportData(in_isr, data);
403 const auto* req = static_cast<const uint8_t*>(data.addr_);
404 uint16_t req_len = static_cast<uint16_t>(data.size_);
405 return HandleControlReportRequest(in_isr, req, req_len);
406}
407
408template <typename SwdPort>
410 const uint8_t* req,
411 uint16_t req_len)
412{
413 if (!req || req_len == 0u)
414 {
415 control_input_report_len_ = 0u;
416 return ErrorCode::ARG_ERR;
417 }
418
419 uint16_t out_len = 0u;
420 const ErrorCode ANS = ProcessOneCommand(in_isr, req, req_len, control_input_report_,
421 MAX_DAP_PACKET_SIZE, out_len);
422
423 out_len = ClipResponseLength(out_len, MAX_DAP_PACKET_SIZE);
424
425 uint16_t tx_len = GetDapPacketSize();
426 if (tx_len == 0u || tx_len > MAX_DAP_PACKET_SIZE)
427 {
428 tx_len = MAX_DAP_PACKET_SIZE;
429 }
430 if (tx_len < out_len)
431 {
432 tx_len = out_len;
433 }
434 if (tx_len > out_len)
435 {
436 Memory::FastSet(control_input_report_ + out_len, 0, tx_len - out_len);
437 }
438
439 control_input_report_len_ = tx_len;
440 return ANS;
441}
442
443template <typename SwdPort>
445 uint8_t /*report_id*/, DeviceClass::ControlTransferResult& result)
446{
447 const uint16_t TX_LEN =
448 (control_input_report_len_ > 0u) ? control_input_report_len_ : GetDapPacketSize();
449 result.write_data = ConstRawData{control_input_report_, TX_LEN};
450 return ErrorCode::OK;
451}
452
453template <typename SwdPort>
455 uint8_t /*report_id*/, DeviceClass::ControlTransferResult& result)
456{
457 const uint16_t TX_LEN =
458 (control_input_report_len_ > 0u) ? control_input_report_len_ : GetDapPacketSize();
459 result.write_data = ConstRawData{control_input_report_, TX_LEN};
460 return ErrorCode::OK;
461}
462
463template <typename SwdPort>
465 uint16_t payload_len,
466 uint16_t cap)
467{
468 if (!resp || cap == 0u)
469 {
470 control_input_report_len_ = 0u;
471 return 0u;
472 }
473
474 payload_len = ClipResponseLength(payload_len, cap);
475
476 uint16_t tx_len = GetDapPacketSize();
477 if (tx_len == 0u || tx_len > cap)
478 {
479 tx_len = cap;
480 }
481 if (tx_len < payload_len)
482 {
483 tx_len = payload_len;
484 }
485 if (tx_len > payload_len)
486 {
487 Memory::FastSet(resp + payload_len, 0, tx_len - payload_len);
488 }
489
490 UpdateControlInputReport(resp, tx_len);
491 return tx_len;
492}
493
494template <typename SwdPort>
495void DapLinkV1Class<SwdPort>::UpdateControlInputReport(const uint8_t* resp, uint16_t len)
496{
497 if (!resp)
498 {
499 control_input_report_len_ = 0u;
500 return;
501 }
502
503 if (len > MAX_DAP_PACKET_SIZE)
504 {
505 len = MAX_DAP_PACKET_SIZE;
506 }
507
508 if (len > 0u)
509 {
510 Memory::FastCopy(control_input_report_, resp, len);
511 }
512 if (len < MAX_DAP_PACKET_SIZE)
513 {
514 Memory::FastSet(control_input_report_ + len, 0, MAX_DAP_PACKET_SIZE - len);
515 }
516
517 control_input_report_len_ = len;
518}
519
520template <typename SwdPort>
521void DapLinkV1Class<SwdPort>::HandleHostRequest(bool in_isr, const uint8_t* req,
522 uint16_t req_len)
523{
524 if (!inited_ || !ep_in_)
525 {
526 return;
527 }
528
529 if (!req || req_len == 0u)
530 {
531 ArmOutTransferIfIdle();
532 return;
533 }
534
535 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
536 ep_in_->GetState() == Endpoint::State::IDLE)
537 {
538 auto tx_buff = ep_in_->GetBuffer();
539 if (tx_buff.addr_ && tx_buff.size_ > 0u)
540 {
541 auto* tx_buf = static_cast<uint8_t*>(tx_buff.addr_);
542 uint16_t out_len = 0u;
543 const auto ANS = ProcessOneCommand(in_isr, req, req_len, tx_buf,
544 static_cast<uint16_t>(tx_buff.size_), out_len);
545 UNUSED(ANS);
546
547 out_len = ClipResponseLength(out_len, static_cast<uint16_t>(tx_buff.size_));
548 const uint16_t TX_LEN =
549 PrepareResponseReport(tx_buf, out_len, static_cast<uint16_t>(tx_buff.size_));
550 if (TX_LEN > 0u && ep_in_->Transfer(TX_LEN) == ErrorCode::OK)
551 {
552 return;
553 }
554
555 if (!EnqueueResponse(tx_buf, out_len))
556 {
557 (void)SubmitNextQueuedResponseIfIdle();
558 (void)EnqueueResponse(tx_buf, out_len);
559 }
560
561 (void)SubmitNextQueuedResponseIfIdle();
562 ArmOutTransferIfIdle();
563 return;
564 }
565 }
566
567 if (!HasDeferredResponseInEpBuffer() && IsResponseQueueEmpty() &&
568 ep_in_->GetState() == Endpoint::State::BUSY)
569 {
570 auto tx_buff = ep_in_->GetBuffer();
571 if (tx_buff.addr_ && tx_buff.size_ > 0u)
572 {
573 auto* tx_buf = static_cast<uint8_t*>(tx_buff.addr_);
574 uint16_t out_len = 0u;
575 const auto ANS = ProcessOneCommand(in_isr, req, req_len, tx_buf,
576 static_cast<uint16_t>(tx_buff.size_), out_len);
577 UNUSED(ANS);
578
579 out_len = ClipResponseLength(out_len, static_cast<uint16_t>(tx_buff.size_));
580 const uint16_t TX_LEN =
581 PrepareResponseReport(tx_buf, out_len, static_cast<uint16_t>(tx_buff.size_));
582 SetDeferredResponseInEpBuffer(TX_LEN);
583 ArmOutTransferIfIdle();
584 return;
585 }
586 }
587
588 if (TryBuildAndEnqueueResponse(in_isr, req, req_len))
589 {
590 (void)SubmitDeferredResponseIfIdle();
591 (void)SubmitNextQueuedResponseIfIdle();
592 ArmOutTransferIfIdle();
593 return;
594 }
595
596 (void)SubmitNextQueuedResponseIfIdle();
597 (void)TryBuildAndEnqueueResponse(in_isr, req, req_len);
598
599 (void)SubmitDeferredResponseIfIdle();
600 (void)SubmitNextQueuedResponseIfIdle();
601 ArmOutTransferIfIdle();
602}
603
604template <typename SwdPort>
605uint16_t DapLinkV1Class<SwdPort>::GetDapPacketSize() const
606{
607 const uint16_t IN_PS = ep_in_ ? ep_in_->MaxPacketSize() : 0u;
608 const uint16_t OUT_PS = ep_out_ ? ep_out_->MaxPacketSize() : 0u;
609 uint16_t dap_ps = 0u;
610
611 if (IN_PS > 0u && OUT_PS > 0u)
612 {
613 dap_ps = (IN_PS < OUT_PS) ? IN_PS : OUT_PS;
614 }
615 else
616 {
617 dap_ps = (IN_PS > 0u) ? IN_PS : OUT_PS;
618 }
619
620 if (dap_ps == 0u)
621 {
622 dap_ps = DEFAULT_DAP_PACKET_SIZE;
623 }
624 if (dap_ps > MAX_DAP_PACKET_SIZE)
625 {
626 dap_ps = MAX_DAP_PACKET_SIZE;
627 }
628 return dap_ps;
629}
630
631template <typename SwdPort>
632uint16_t DapLinkV1Class<SwdPort>::ClipResponseLength(uint16_t len, uint16_t cap) const
633{
634 const uint16_t DAP_PS = GetDapPacketSize();
635 if (len > DAP_PS)
636 {
637 len = DAP_PS;
638 }
639 if (len > RESP_SLOT_SIZE)
640 {
641 len = RESP_SLOT_SIZE;
642 }
643 if (len > cap)
644 {
645 len = cap;
646 }
647 return len;
648}
649
650template <typename SwdPort>
651constexpr uint8_t DapLinkV1Class<SwdPort>::NextRespQueueIndex(uint8_t idx)
652{
653 return static_cast<uint8_t>((idx + 1u) & (RESP_QUEUE_DEPTH - 1u));
654}
655
656template <typename SwdPort>
657void DapLinkV1Class<SwdPort>::ResetResponseQueue()
658{
659 resp_q_head_ = 0u;
660 resp_q_tail_ = 0u;
661 resp_q_count_ = 0u;
662 deferred_in_resp_valid_ = false;
663 deferred_in_resp_len_ = 0u;
664}
665
666template <typename SwdPort>
667bool DapLinkV1Class<SwdPort>::HasDeferredResponseInEpBuffer() const
668{
669 return deferred_in_resp_valid_;
670}
671
672template <typename SwdPort>
673void DapLinkV1Class<SwdPort>::SetDeferredResponseInEpBuffer(uint16_t len)
674{
675 deferred_in_resp_len_ = len;
676 deferred_in_resp_valid_ = true;
677}
678
679template <typename SwdPort>
680bool DapLinkV1Class<SwdPort>::SubmitDeferredResponseIfIdle()
681{
682 if (!deferred_in_resp_valid_ || !ep_in_ || ep_in_->GetState() != Endpoint::State::IDLE)
683 {
684 return false;
685 }
686
687 const uint16_t TX_LEN = deferred_in_resp_len_;
688 if (ep_in_->Transfer(TX_LEN) != ErrorCode::OK)
689 {
690 return false;
691 }
692
693 deferred_in_resp_valid_ = false;
694 deferred_in_resp_len_ = 0u;
695 return true;
696}
697
698template <typename SwdPort>
699bool DapLinkV1Class<SwdPort>::IsResponseQueueEmpty() const
700{
701 return resp_q_count_ == 0u;
702}
703
704template <typename SwdPort>
705bool DapLinkV1Class<SwdPort>::IsResponseQueueFull() const
706{
707 return resp_q_count_ >= RESP_QUEUE_DEPTH;
708}
709
710template <typename SwdPort>
711bool DapLinkV1Class<SwdPort>::TryBuildAndEnqueueResponse(bool in_isr, const uint8_t* req,
712 uint16_t req_len)
713{
714 if (!req || IsResponseQueueFull())
715 {
716 return false;
717 }
718
719 auto& slot = resp_q_[resp_q_tail_];
720 uint16_t out_len = 0u;
721 auto ans =
722 ProcessOneCommand(in_isr, req, req_len, slot.payload, RESP_SLOT_SIZE, out_len);
723 UNUSED(ans);
724 slot.len = ClipResponseLength(out_len, RESP_SLOT_SIZE);
725 (void)PrepareResponseReport(slot.payload, slot.len, RESP_SLOT_SIZE);
726
727 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
728 ++resp_q_count_;
729 return true;
730}
731
732template <typename SwdPort>
733uint8_t DapLinkV1Class<SwdPort>::OutstandingResponseCount() const
734{
735 const uint8_t IN_FLIGHT =
736 (ep_in_ && ep_in_->GetState() == Endpoint::State::BUSY) ? 1u : 0u;
737 const uint8_t DEFERRED = deferred_in_resp_valid_ ? 1u : 0u;
738 return static_cast<uint8_t>(resp_q_count_ + IN_FLIGHT + DEFERRED);
739}
740
741template <typename SwdPort>
742bool DapLinkV1Class<SwdPort>::EnqueueResponse(const uint8_t* data, uint16_t len)
743{
744 if (!data || IsResponseQueueFull())
745 {
746 return false;
747 }
748
749 auto& slot = resp_q_[resp_q_tail_];
750 const uint16_t CLIPPED = ClipResponseLength(len, RESP_SLOT_SIZE);
751 slot.len = CLIPPED;
752 if (CLIPPED > 0u)
753 {
754 Memory::FastCopy(slot.payload, data, CLIPPED);
755 }
756
757 resp_q_tail_ = NextRespQueueIndex(resp_q_tail_);
758 ++resp_q_count_;
759 return true;
760}
761
762template <typename SwdPort>
763bool DapLinkV1Class<SwdPort>::SubmitNextQueuedResponseIfIdle()
764{
765 if (!ep_in_ || ep_in_->GetState() != Endpoint::State::IDLE || IsResponseQueueEmpty())
766 {
767 return false;
768 }
769
770 auto tx_buff = ep_in_->GetBuffer();
771 if (!tx_buff.addr_ || tx_buff.size_ == 0u)
772 {
773 return false;
774 }
775
776 auto& slot = resp_q_[resp_q_head_];
777 uint16_t payload_len = slot.len;
778 if (payload_len > tx_buff.size_)
779 {
780 payload_len = static_cast<uint16_t>(tx_buff.size_);
781 }
782
783 if (payload_len > 0u)
784 {
785 Memory::FastCopy(tx_buff.addr_, slot.payload, payload_len);
786 }
787
788 uint16_t tx_len = GetDapPacketSize();
789 if (tx_len == 0u || tx_len > tx_buff.size_)
790 {
791 tx_len = static_cast<uint16_t>(tx_buff.size_);
792 }
793 if (tx_len < payload_len)
794 {
795 tx_len = payload_len;
796 }
797 if (tx_len > payload_len)
798 {
799 Memory::FastSet(reinterpret_cast<uint8_t*>(tx_buff.addr_) + payload_len, 0,
800 tx_len - payload_len);
801 }
802
803 if (ep_in_->Transfer(tx_len) != ErrorCode::OK)
804 {
805 return false;
806 }
807
808 resp_q_head_ = NextRespQueueIndex(resp_q_head_);
809 --resp_q_count_;
810 return true;
811}
812
813template <typename SwdPort>
814void DapLinkV1Class<SwdPort>::ArmOutTransferIfIdle()
815{
816 if (!inited_ || ep_out_ == nullptr || ep_in_ == nullptr)
817 {
818 return;
819 }
820
821 if (ep_out_->GetState() != Endpoint::State::IDLE)
822 {
823 return;
824 }
825
826 if (OutstandingResponseCount() >= MAX_OUTSTANDING_RESPONSES)
827 {
828 return;
829 }
830
831 uint16_t out_rx_len = ep_out_->MaxPacketSize();
832 if (out_rx_len == 0u)
833 {
834 out_rx_len = ep_out_->MaxTransferSize();
835 }
836 (void)ep_out_->Transfer(out_rx_len);
837}
838
839template <typename SwdPort>
840ErrorCode DapLinkV1Class<SwdPort>::ProcessOneCommand(bool in_isr, const uint8_t* req,
841 uint16_t req_len, uint8_t* resp,
842 uint16_t resp_cap, uint16_t& out_len)
843{
844 out_len = 0u;
845
846 if (!req || !resp || req_len < 1u || resp_cap < 1u)
847 {
848 if (resp && resp_cap >= 1u)
849 {
850 BuildNotSupportResponse(resp, resp_cap, out_len);
851 }
852 return ErrorCode::ARG_ERR;
853 }
854
855 const uint8_t CMD = req[0];
856
857 switch (CMD)
858 {
859 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::INFO):
860 return HandleInfo(in_isr, req, req_len, resp, resp_cap, out_len);
861 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS):
862 return HandleHostStatus(in_isr, req, req_len, resp, resp_cap, out_len);
863 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT):
864 return HandleConnect(in_isr, req, req_len, resp, resp_cap, out_len);
865 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT):
866 return HandleDisconnect(in_isr, req, req_len, resp, resp_cap, out_len);
867 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE):
868 return HandleTransferConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
869 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER):
870 return HandleTransfer(in_isr, req, req_len, resp, resp_cap, out_len);
871 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK):
872 return HandleTransferBlock(in_isr, req, req_len, resp, resp_cap, out_len);
873 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT):
874 return HandleTransferAbort(in_isr, req, req_len, resp, resp_cap, out_len);
875 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT):
876 return HandleWriteABORT(in_isr, req, req_len, resp, resp_cap, out_len);
877 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::DELAY):
878 return HandleDelay(in_isr, req, req_len, resp, resp_cap, out_len);
879 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET):
880 return HandleResetTarget(in_isr, req, req_len, resp, resp_cap, out_len);
881 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS):
882 return HandleSWJPins(in_isr, req, req_len, resp, resp_cap, out_len);
883 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK):
884 return HandleSWJClock(in_isr, req, req_len, resp, resp_cap, out_len);
885 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE):
886 return HandleSWJSequence(in_isr, req, req_len, resp, resp_cap, out_len);
887 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE):
888 return HandleSWDConfigure(in_isr, req, req_len, resp, resp_cap, out_len);
889 case ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE):
890 return HandleSWDSequence(in_isr, req, req_len, resp, resp_cap, out_len);
891 default:
892 (void)BuildUnknowCmdResponse(resp, resp_cap, out_len);
894 }
895}
896
897template <typename SwdPort>
898void DapLinkV1Class<SwdPort>::BuildNotSupportResponse(uint8_t* resp, uint16_t resp_cap,
899 uint16_t& out_len)
900{
901 if (!resp || resp_cap < 1u)
902 {
903 out_len = 0u;
904 return;
905 }
906 resp[0] = 0xFFu;
907 out_len = 1u;
908}
909
910template <typename SwdPort>
911ErrorCode DapLinkV1Class<SwdPort>::HandleInfo(bool /*in_isr*/, const uint8_t* req,
912 uint16_t req_len, uint8_t* resp,
913 uint16_t resp_cap, uint16_t& out_len)
914{
915 if (req_len < 2u)
916 {
917 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
918 resp[1] = 0u;
919 out_len = 2u;
920 return ErrorCode::ARG_ERR;
921 }
922
923 const uint8_t INFO_ID = req[1];
924
925 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::INFO);
926
927 switch (INFO_ID)
928 {
929 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::VENDOR):
930 return BuildInfoStringResponse(resp[0], info_.vendor, resp, resp_cap, out_len);
931 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT):
932 return BuildInfoStringResponse(resp[0], info_.product, resp, resp_cap, out_len);
933 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::SERIAL_NUMBER):
934 return BuildInfoStringResponse(resp[0], info_.serial, resp, resp_cap, out_len);
935 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::FIRMWARE_VERSION):
936 return BuildInfoStringResponse(resp[0], info_.firmware_ver, resp, resp_cap,
937 out_len);
938 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_VENDOR):
939 return BuildInfoStringResponse(resp[0], info_.device_vendor, resp, resp_cap,
940 out_len);
941 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::DEVICE_NAME):
942 return BuildInfoStringResponse(resp[0], info_.device_name, resp, resp_cap, out_len);
943 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_VENDOR):
944 return BuildInfoStringResponse(resp[0], info_.board_vendor, resp, resp_cap,
945 out_len);
946 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::BOARD_NAME):
947 return BuildInfoStringResponse(resp[0], info_.board_name, resp, resp_cap, out_len);
948 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PRODUCT_FIRMWARE_VERSION):
949 return BuildInfoStringResponse(resp[0], info_.product_fw_ver, resp, resp_cap,
950 out_len);
951 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::CAPABILITIES):
952 return BuildInfoU8Response(resp[0], LibXR::USB::DapLinkV1Def::DAP_CAP_SWD, resp,
953 resp_cap, out_len);
954 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_COUNT):
955 return BuildInfoU8Response(resp[0], PACKET_COUNT_ADVERTISED, resp, resp_cap,
956 out_len);
957 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::PACKET_SIZE):
958 {
959 const uint16_t DAP_PS = GetDapPacketSize();
960 return BuildInfoU16Response(resp[0], DAP_PS, resp, resp_cap, out_len);
961 }
962 case ToU8(LibXR::USB::DapLinkV1Def::InfoId::TIMESTAMP_CLOCK):
963 return BuildInfoU32Response(resp[0], 1000000U, resp, resp_cap, out_len);
964 default:
965 resp[1] = 0u;
966 out_len = 2u;
967 return ErrorCode::OK;
968 }
969}
970
971template <typename SwdPort>
972ErrorCode DapLinkV1Class<SwdPort>::BuildInfoStringResponse(uint8_t cmd, const char* str,
973 uint8_t* resp,
974 uint16_t resp_cap,
975 uint16_t& out_len)
976{
977 resp[0] = cmd;
978 resp[1] = 0u;
979
980 if (!str)
981 {
982 out_len = 2u;
983 return ErrorCode::OK;
984 }
985
986 const size_t N_WITH_NUL = std::strlen(str) + 1;
987 const size_t MAX_PAYLOAD = (resp_cap >= 2u) ? (resp_cap - 2u) : 0u;
988 if (MAX_PAYLOAD == 0u)
989 {
990 out_len = 2u;
991 return ErrorCode::OK;
992 }
993
994 const size_t COPY_N = (N_WITH_NUL > MAX_PAYLOAD) ? MAX_PAYLOAD : N_WITH_NUL;
995 Memory::FastCopy(&resp[2], str, COPY_N);
996 resp[2 + COPY_N - 1] = 0x00;
997 resp[1] = static_cast<uint8_t>(COPY_N);
998 out_len = static_cast<uint16_t>(COPY_N + 2u);
999 return ErrorCode::OK;
1000}
1001
1002template <typename SwdPort>
1003ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU8Response(uint8_t cmd, uint8_t val,
1004 uint8_t* resp, uint16_t resp_cap,
1005 uint16_t& out_len)
1006{
1007 if (resp_cap < 3u)
1008 {
1009 out_len = 0u;
1010 return ErrorCode::NOT_FOUND;
1011 }
1012 resp[0] = cmd;
1013 resp[1] = 1u;
1014 resp[2] = val;
1015 out_len = 3u;
1016 return ErrorCode::OK;
1017}
1018
1019template <typename SwdPort>
1020ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU16Response(uint8_t cmd, uint16_t val,
1021 uint8_t* resp, uint16_t resp_cap,
1022 uint16_t& out_len)
1023{
1024 if (resp_cap < 4u)
1025 {
1026 out_len = 0u;
1027 return ErrorCode::NOT_FOUND;
1028 }
1029 resp[0] = cmd;
1030 resp[1] = 2u;
1031 Memory::FastCopy(&resp[2], &val, sizeof(val));
1032 out_len = 4u;
1033 return ErrorCode::OK;
1034}
1035
1036template <typename SwdPort>
1037ErrorCode DapLinkV1Class<SwdPort>::BuildInfoU32Response(uint8_t cmd, uint32_t val,
1038 uint8_t* resp, uint16_t resp_cap,
1039 uint16_t& out_len)
1040{
1041 if (resp_cap < 6u)
1042 {
1043 out_len = 0u;
1044 return ErrorCode::NOT_FOUND;
1045 }
1046 resp[0] = cmd;
1047 resp[1] = 4u;
1048 Memory::FastCopy(&resp[2], &val, sizeof(val));
1049 out_len = 6u;
1050 return ErrorCode::OK;
1051}
1052
1053template <typename SwdPort>
1054ErrorCode DapLinkV1Class<SwdPort>::HandleHostStatus(bool /*in_isr*/,
1055 const uint8_t* /*req*/,
1056 uint16_t /*req_len*/, uint8_t* resp,
1057 uint16_t resp_cap, uint16_t& out_len)
1058{
1059 if (resp_cap < 2u)
1060 {
1061 out_len = 0u;
1062 return ErrorCode::NOT_FOUND;
1063 }
1064 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::HOST_STATUS);
1065 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1066 out_len = 2u;
1067 return ErrorCode::OK;
1068}
1069
1070template <typename SwdPort>
1071ErrorCode DapLinkV1Class<SwdPort>::HandleConnect(bool /*in_isr*/, const uint8_t* req,
1072 uint16_t req_len, uint8_t* resp,
1073 uint16_t resp_cap, uint16_t& out_len)
1074{
1075 if (resp_cap < 2u)
1076 {
1077 out_len = 0u;
1078 return ErrorCode::NOT_FOUND;
1079 }
1080
1081 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::CONNECT);
1082
1083 uint8_t port = 0u;
1084 if (req_len >= 2u)
1085 {
1086 port = req[1];
1087 }
1088
1089 if (port == 0u || port == ToU8(LibXR::USB::DapLinkV1Def::Port::SWD))
1090 {
1091 (void)swd_.EnterSwd();
1092 (void)swd_.SetClockHz(swj_clock_hz_);
1093
1094 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::SWD;
1095 dap_state_.transfer_abort = false;
1096
1097 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Port::SWD);
1098 }
1099 else
1100 {
1101 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Port::DISABLED);
1102 }
1103
1104 out_len = 2u;
1105 return ErrorCode::OK;
1106}
1107
1108template <typename SwdPort>
1109ErrorCode DapLinkV1Class<SwdPort>::HandleDisconnect(bool /*in_isr*/,
1110 const uint8_t* /*req*/,
1111 uint16_t /*req_len*/, uint8_t* resp,
1112 uint16_t resp_cap, uint16_t& out_len)
1113{
1114 if (resp_cap < 2u)
1115 {
1116 out_len = 0u;
1117 return ErrorCode::NOT_FOUND;
1118 }
1119
1120 swd_.Close();
1121 dap_state_.debug_port = LibXR::USB::DapLinkV1Def::DebugPort::DISABLED;
1122 dap_state_.transfer_abort = false;
1123
1124 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::DISCONNECT);
1125 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1126 out_len = 2u;
1127 return ErrorCode::OK;
1128}
1129
1130template <typename SwdPort>
1131ErrorCode DapLinkV1Class<SwdPort>::HandleTransferConfigure(
1132 bool /*in_isr*/, const uint8_t* req, uint16_t req_len, uint8_t* resp,
1133 uint16_t resp_cap, uint16_t& out_len)
1134{
1135 if (resp_cap < 2u)
1136 {
1137 out_len = 0u;
1138 return ErrorCode::NOT_FOUND;
1139 }
1140
1141 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_CONFIGURE);
1142
1143 if (req_len < 6u)
1144 {
1145 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1146 out_len = 2u;
1147 return ErrorCode::ARG_ERR;
1148 }
1149
1150 const uint8_t IDLE = req[1];
1151
1152 uint16_t wait_retry = 0u;
1153 uint16_t match_retry = 0u;
1154 Memory::FastCopy(&wait_retry, &req[2], sizeof(wait_retry));
1155 Memory::FastCopy(&match_retry, &req[4], sizeof(match_retry));
1156
1157 dap_state_.transfer_cfg.idle_cycles = IDLE;
1158 dap_state_.transfer_cfg.retry_count = wait_retry;
1159 dap_state_.transfer_cfg.match_retry = match_retry;
1160
1161 LibXR::Debug::Swd::TransferPolicy pol = swd_.GetTransferPolicy();
1162 pol.idle_cycles = IDLE;
1163 pol.wait_retry = wait_retry;
1164 swd_.SetTransferPolicy(pol);
1165
1166 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1167 out_len = 2u;
1168 return ErrorCode::OK;
1169}
1170
1171template <typename SwdPort>
1172ErrorCode DapLinkV1Class<SwdPort>::HandleTransferAbort(bool /*in_isr*/,
1173 const uint8_t* /*req*/,
1174 uint16_t /*req_len*/,
1175 uint8_t* resp, uint16_t resp_cap,
1176 uint16_t& out_len)
1177{
1178 if (resp_cap < 2u)
1179 {
1180 out_len = 0u;
1181 return ErrorCode::NOT_FOUND;
1182 }
1183
1184 SetTransferAbortFlag(true);
1185
1186 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_ABORT);
1187 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1188 out_len = 2u;
1189 return ErrorCode::OK;
1190}
1191
1192template <typename SwdPort>
1193ErrorCode DapLinkV1Class<SwdPort>::HandleWriteABORT(bool /*in_isr*/, const uint8_t* req,
1194 uint16_t req_len, uint8_t* resp,
1195 uint16_t resp_cap, uint16_t& out_len)
1196{
1197 if (resp_cap < 2u)
1198 {
1199 out_len = 0u;
1200 return ErrorCode::NOT_FOUND;
1201 }
1202
1203 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::WRITE_ABORT);
1204
1205 if (req_len < 6u)
1206 {
1207 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1208 out_len = 2u;
1209 return ErrorCode::ARG_ERR;
1210 }
1211
1212 uint32_t flags = 0u;
1213 Memory::FastCopy(&flags, &req[2], sizeof(flags));
1214
1215 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1216 const ErrorCode EC = swd_.WriteAbortTxn(flags, ack);
1217 resp[1] = (EC == ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1218 ? ToU8(LibXR::USB::DapLinkV1Def::Status::OK)
1219 : ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1220
1221 out_len = 2u;
1222 return ErrorCode::OK;
1223}
1224
1225template <typename SwdPort>
1226ErrorCode DapLinkV1Class<SwdPort>::HandleDelay(bool /*in_isr*/, const uint8_t* req,
1227 uint16_t req_len, uint8_t* resp,
1228 uint16_t resp_cap, uint16_t& out_len)
1229{
1230 if (resp_cap < 2u)
1231 {
1232 out_len = 0u;
1233 return ErrorCode::NOT_FOUND;
1234 }
1235
1236 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::DELAY);
1237
1238 if (req_len < 3u)
1239 {
1240 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1241 out_len = 2u;
1242 return ErrorCode::ARG_ERR;
1243 }
1244
1245 uint16_t us = 0u;
1246 Memory::FastCopy(&us, &req[1], sizeof(us));
1247
1249
1250 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1251 out_len = 2u;
1252 return ErrorCode::OK;
1253}
1254
1255template <typename SwdPort>
1256ErrorCode DapLinkV1Class<SwdPort>::HandleResetTarget(bool in_isr, const uint8_t* /*req*/,
1257 uint16_t /*req_len*/, uint8_t* resp,
1258 uint16_t resp_cap, uint16_t& out_len)
1259{
1260 if (!resp || resp_cap < 3u)
1261 {
1262 out_len = 0u;
1263 return ErrorCode::NOT_FOUND;
1264 }
1265
1266 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::RESET_TARGET);
1267
1268 uint8_t execute = 0u;
1269 if (nreset_gpio_ != nullptr)
1270 {
1271 DriveReset(false);
1272 DelayUsIfAllowed(in_isr, 1000u);
1273 DriveReset(true);
1274 DelayUsIfAllowed(in_isr, 1000u);
1275 execute = 1u;
1276 }
1277
1278 resp[1] = DAP_OK;
1279 resp[2] = execute;
1280 out_len = 3u;
1281 return ErrorCode::OK;
1282}
1283
1284template <typename SwdPort>
1285ErrorCode DapLinkV1Class<SwdPort>::HandleSWJPins(bool /*in_isr*/, const uint8_t* req,
1286 uint16_t req_len, uint8_t* resp,
1287 uint16_t resp_cap, uint16_t& out_len)
1288{
1289 if (!resp || resp_cap < 2u)
1290 {
1291 out_len = 0u;
1292 return ErrorCode::NOT_FOUND;
1293 }
1294
1295 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_PINS);
1296
1297 if (!req || req_len < 7u)
1298 {
1299 resp[1] = 0u;
1300 out_len = 2u;
1301 return ErrorCode::ARG_ERR;
1302 }
1303
1304 const uint8_t PIN_OUT = req[1];
1305 const uint8_t PIN_SEL = req[2];
1306
1307 uint32_t wait_us = 0u;
1308 Memory::FastCopy(&wait_us, &req[3], sizeof(wait_us));
1309
1310 swj_shadow_ = static_cast<uint8_t>((swj_shadow_ & static_cast<uint8_t>(~PIN_SEL)) |
1311 (PIN_OUT & PIN_SEL));
1312
1313 if ((PIN_SEL & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u)
1314 {
1315 const bool LEVEL_HIGH = ((PIN_OUT & LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET) != 0u);
1316 DriveReset(LEVEL_HIGH);
1317 }
1318
1319 auto read_pins = [&]() -> uint8_t
1320 {
1321 uint8_t pin_in = swj_shadow_;
1322
1323 if (nreset_gpio_ != nullptr)
1324 {
1325 if (nreset_gpio_->Read())
1326 {
1327 pin_in |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
1328 }
1329 else
1330 {
1331 pin_in = static_cast<uint8_t>(
1332 pin_in & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
1333 }
1334 }
1335
1336 return pin_in;
1337 };
1338
1339 uint8_t pin_in = 0u;
1340 if (wait_us == 0u || PIN_SEL == 0u)
1341 {
1342 pin_in = read_pins();
1343 }
1344 else
1345 {
1346 const uint64_t START = LibXR::Timebase::GetMicroseconds();
1347 const uint8_t EXPECT = static_cast<uint8_t>(PIN_OUT & PIN_SEL);
1348
1349 do
1350 {
1351 pin_in = read_pins();
1352 if ((pin_in & PIN_SEL) == EXPECT)
1353 {
1354 break;
1355 }
1356 } while ((static_cast<uint64_t>(LibXR::Timebase::GetMicroseconds()) - START) <
1357 wait_us);
1358 }
1359
1360 resp[1] = pin_in;
1361 out_len = 2u;
1362 return ErrorCode::OK;
1363}
1364
1365template <typename SwdPort>
1366ErrorCode DapLinkV1Class<SwdPort>::HandleSWJClock(bool /*in_isr*/, const uint8_t* req,
1367 uint16_t req_len, uint8_t* resp,
1368 uint16_t resp_cap, uint16_t& out_len)
1369{
1370 if (resp_cap < 2u)
1371 {
1372 out_len = 0u;
1373 return ErrorCode::NOT_FOUND;
1374 }
1375
1376 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_CLOCK);
1377
1378 if (req_len < 5u)
1379 {
1380 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1381 out_len = 2u;
1382 return ErrorCode::ARG_ERR;
1383 }
1384
1385 uint32_t hz = 0u;
1386 Memory::FastCopy(&hz, &req[1], sizeof(hz));
1387
1388 swj_clock_hz_ = hz;
1389 (void)swd_.SetClockHz(hz);
1390
1391 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1392 out_len = 2u;
1393 return ErrorCode::OK;
1394}
1395
1396template <typename SwdPort>
1397ErrorCode DapLinkV1Class<SwdPort>::HandleSWJSequence(bool /*in_isr*/, const uint8_t* req,
1398 uint16_t req_len, uint8_t* resp,
1399 uint16_t resp_cap, uint16_t& out_len)
1400{
1401 if (!resp || resp_cap < 2u)
1402 {
1403 out_len = 0u;
1404 return ErrorCode::NOT_FOUND;
1405 }
1406
1407 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWJ_SEQUENCE);
1408 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1409 out_len = 2u;
1410
1411 if (!req || req_len < 2u)
1412 {
1413 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1414 return ErrorCode::ARG_ERR;
1415 }
1416
1417 uint32_t bit_count = req[1];
1418 if (bit_count == 0u)
1419 {
1420 bit_count = 256u;
1421 }
1422
1423 const uint32_t BYTE_COUNT = (bit_count + 7u) / 8u;
1424 if (req_len < (2u + BYTE_COUNT))
1425 {
1426 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1427 return ErrorCode::ARG_ERR;
1428 }
1429
1430 const uint8_t* data = &req[2];
1431 const ErrorCode EC = swd_.SeqWriteBits(bit_count, data);
1432 if (EC != ErrorCode::OK)
1433 {
1434 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::ERROR);
1435 return ErrorCode::OK;
1436 }
1437
1438 swj_shadow_ = static_cast<uint8_t>(
1439 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWCLK_TCK));
1440
1441 bool last_swdio = false;
1442 if (bit_count != 0u)
1443 {
1444 const uint32_t LAST_I = bit_count - 1u;
1445 last_swdio = (((data[LAST_I / 8u] >> (LAST_I & 7u)) & 0x01u) != 0u);
1446 }
1447
1448 if (last_swdio)
1449 {
1450 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS;
1451 }
1452 else
1453 {
1454 swj_shadow_ = static_cast<uint8_t>(
1455 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_SWDIO_TMS));
1456 }
1457
1458 return ErrorCode::OK;
1459}
1460
1461template <typename SwdPort>
1462ErrorCode DapLinkV1Class<SwdPort>::HandleSWDConfigure(bool /*in_isr*/,
1463 const uint8_t* /*req*/,
1464 uint16_t /*req_len*/, uint8_t* resp,
1465 uint16_t resp_cap,
1466 uint16_t& out_len)
1467{
1468 if (resp_cap < 2u)
1469 {
1470 out_len = 0u;
1471 return ErrorCode::NOT_FOUND;
1472 }
1473
1474 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_CONFIGURE);
1475 resp[1] = ToU8(LibXR::USB::DapLinkV1Def::Status::OK);
1476 out_len = 2u;
1477 return ErrorCode::OK;
1478}
1479
1480template <typename SwdPort>
1481ErrorCode DapLinkV1Class<SwdPort>::HandleSWDSequence(bool /*in_isr*/, const uint8_t* req,
1482 uint16_t req_len, uint8_t* resp,
1483 uint16_t resp_cap, uint16_t& out_len)
1484{
1485 if (!req || !resp || resp_cap < 2u)
1486 {
1487 out_len = 0u;
1488 return ErrorCode::ARG_ERR;
1489 }
1490
1491 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::SWD_SEQUENCE);
1492 resp[1] = DAP_OK;
1493 out_len = 2u;
1494
1495 if (req_len < 2u)
1496 {
1497 resp[1] = DAP_ERROR;
1498 out_len = 2u;
1499 return ErrorCode::ARG_ERR;
1500 }
1501
1502 const uint8_t SEQ_CNT = req[1];
1503 uint16_t req_off = 2u;
1504 uint16_t resp_off = 2u;
1505
1506 for (uint32_t s = 0; s < SEQ_CNT; ++s)
1507 {
1508 if (req_off >= req_len)
1509 {
1510 resp[1] = DAP_ERROR;
1511 out_len = 2u;
1512 return ErrorCode::ARG_ERR;
1513 }
1514
1515 const uint8_t INFO = req[req_off++];
1516 uint32_t cycles = static_cast<uint32_t>(INFO & 0x3Fu);
1517 if (cycles == 0u)
1518 {
1519 cycles = 64u;
1520 }
1521
1522 const bool MODE_IN = ((INFO & 0x80u) != 0u);
1523 const uint16_t BYTES = static_cast<uint16_t>((cycles + 7u) / 8u);
1524
1525 if (!MODE_IN)
1526 {
1527 if (req_off + BYTES > req_len)
1528 {
1529 resp[1] = DAP_ERROR;
1530 out_len = 2u;
1531 return ErrorCode::ARG_ERR;
1532 }
1533
1534 const uint8_t* data = &req[req_off];
1535 req_off = static_cast<uint16_t>(req_off + BYTES);
1536
1537 const ErrorCode EC = swd_.SeqWriteBits(cycles, data);
1538 if (EC != ErrorCode::OK)
1539 {
1540 resp[1] = DAP_ERROR;
1541 out_len = 2u;
1542 return ErrorCode::OK;
1543 }
1544 }
1545 else
1546 {
1547 if (resp_off + BYTES > resp_cap)
1548 {
1549 resp[1] = DAP_ERROR;
1550 out_len = 2u;
1551 return ErrorCode::NOT_FOUND;
1552 }
1553
1554 Memory::FastSet(&resp[resp_off], 0, BYTES);
1555 const ErrorCode EC = swd_.SeqReadBits(cycles, &resp[resp_off]);
1556 if (EC != ErrorCode::OK)
1557 {
1558 resp[1] = DAP_ERROR;
1559 out_len = 2u;
1560 return ErrorCode::OK;
1561 }
1562
1563 resp_off = static_cast<uint16_t>(resp_off + BYTES);
1564 }
1565 }
1566
1567 out_len = resp_off;
1568 return ErrorCode::OK;
1569}
1570
1571template <typename SwdPort>
1572uint8_t DapLinkV1Class<SwdPort>::MapAckToDapResp(LibXR::Debug::SwdProtocol::Ack ack) const
1573{
1574 switch (ack)
1575 {
1576 case LibXR::Debug::SwdProtocol::Ack::OK:
1577 return 1u;
1578 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1579 return 2u;
1580 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1581 return 4u;
1582 case LibXR::Debug::SwdProtocol::Ack::NO_ACK:
1583 case LibXR::Debug::SwdProtocol::Ack::PROTOCOL:
1584 default:
1585 return 7u;
1586 }
1587}
1588
1589template <typename SwdPort>
1590void DapLinkV1Class<SwdPort>::SetTransferAbortFlag(bool on)
1591{
1592 dap_state_.transfer_abort = on;
1593}
1594
1595template <typename SwdPort>
1596ErrorCode DapLinkV1Class<SwdPort>::HandleTransfer(bool /*in_isr*/, const uint8_t* req,
1597 uint16_t req_len, uint8_t* resp,
1598 uint16_t resp_cap, uint16_t& out_len)
1599{
1600 out_len = 0u;
1601 if (!req || !resp || resp_cap < 3u)
1602 {
1603 return ErrorCode::ARG_ERR;
1604 }
1605
1606 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER);
1607 resp[1] = 0u;
1608 resp[2] = 0u;
1609 uint16_t resp_off = 3u;
1610
1611 if (req_len < 3u)
1612 {
1613 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1614 out_len = 3u;
1615 return ErrorCode::ARG_ERR;
1616 }
1617
1618 if (dap_state_.transfer_abort)
1619 {
1620 dap_state_.transfer_abort = false;
1621 resp[2] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1622 out_len = 3u;
1623 return ErrorCode::OK;
1624 }
1625
1626 const uint8_t COUNT = req[2];
1627 uint16_t req_off = 3u;
1628
1629 auto ack_to_dap = [&](LibXR::Debug::SwdProtocol::Ack ack) -> uint8_t
1630 {
1631 switch (ack)
1632 {
1633 case LibXR::Debug::SwdProtocol::Ack::OK:
1634 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1635 case LibXR::Debug::SwdProtocol::Ack::WAIT:
1636 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_WAIT;
1637 case LibXR::Debug::SwdProtocol::Ack::FAULT:
1638 return LibXR::USB::DapLinkV1Def::DAP_TRANSFER_FAULT;
1639 default:
1640 return 0x07u;
1641 }
1642 };
1643
1644 auto push_u32 = [&](uint32_t VALUE) -> bool
1645 {
1646 if (resp_off + 4u > resp_cap)
1647 {
1648 return false;
1649 }
1650 Memory::FastCopy(&resp[resp_off], &VALUE, sizeof(VALUE));
1651 resp_off = static_cast<uint16_t>(resp_off + 4u);
1652 return true;
1653 };
1654
1655 auto push_timestamp = [&]() -> bool
1656 {
1657 const uint32_t T = static_cast<uint32_t>(LibXR::Timebase::GetMicroseconds());
1658 return push_u32(T);
1659 };
1660
1661 auto ensure_space = [&](uint16_t bytes) -> bool
1662 { return (resp_off + bytes) <= resp_cap; };
1663
1664 auto bytes_for_read = [&](bool need_ts) -> uint16_t
1665 { return static_cast<uint16_t>(need_ts ? 8u : 4u); };
1666
1667 uint8_t response_count = 0u;
1668 uint8_t response_value = 0u;
1669 bool check_write = false;
1670
1671 struct PendingApRead
1672 {
1673 bool valid = false;
1674 bool need_ts = false;
1675 } pending;
1676
1677 auto emit_read_with_ts = [&](bool need_ts, uint32_t data) -> bool
1678 {
1679 if (need_ts)
1680 {
1681 if (!push_timestamp())
1682 {
1683 return false;
1684 }
1685 }
1686 if (!push_u32(data))
1687 {
1688 return false;
1689 }
1690 response_count++;
1691 return true;
1692 };
1693
1694 auto complete_pending_by_rdbuff = [&]() -> bool
1695 {
1696 if (!pending.valid)
1697 {
1698 return true;
1699 }
1700
1701 if (!ensure_space(bytes_for_read(pending.need_ts)))
1702 {
1703 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1704 return false;
1705 }
1706
1707 uint32_t rdata = 0u;
1708 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1709 const ErrorCode EC = swd_.DpReadRdbuffTxn(rdata, ack);
1710
1711 const uint8_t V = ack_to_dap(ack);
1712 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1713 {
1714 response_value = V;
1715 return false;
1716 }
1717 if (EC != ErrorCode::OK)
1718 {
1719 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1720 return false;
1721 }
1722
1723 if (!emit_read_with_ts(pending.need_ts, rdata))
1724 {
1725 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1726 return false;
1727 }
1728
1729 pending.valid = false;
1730 pending.need_ts = false;
1731 check_write = false;
1732 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1733 return true;
1734 };
1735
1736 auto flush_pending_if_any = [&]() -> bool
1737 { return pending.valid ? complete_pending_by_rdbuff() : true; };
1738
1739 for (uint32_t i = 0; i < COUNT; ++i)
1740 {
1741 if (req_off >= req_len)
1742 {
1743 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1744 break;
1745 }
1746
1747 const uint8_t RQ = req[req_off++];
1748
1749 const bool AP = LibXR::USB::DapLinkV1Def::req_is_ap(RQ);
1750 const bool RNW = LibXR::USB::DapLinkV1Def::req_is_read(RQ);
1751 const uint8_t ADDR2B = LibXR::USB::DapLinkV1Def::req_addr2b(RQ);
1752
1754 const bool MATCH_VALUE =
1755 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE) != 0u);
1756 const bool MATCH_MASK =
1757 ((RQ & LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK) != 0u);
1758
1759 if (TS && (MATCH_VALUE || MATCH_MASK))
1760 {
1761 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1762 break;
1763 }
1764
1765 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
1767
1768 if (!RNW)
1769 {
1770 if (!flush_pending_if_any())
1771 {
1772 break;
1773 }
1774
1775 if (req_off + 4u > req_len)
1776 {
1777 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1778 break;
1779 }
1780
1781 uint32_t wdata = 0u;
1782 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
1783 req_off = static_cast<uint16_t>(req_off + 4u);
1784
1785 if (MATCH_MASK)
1786 {
1787 match_mask_ = wdata;
1788 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1789 response_count++;
1790 continue;
1791 }
1792
1793 if (AP)
1794 {
1795 ec = swd_.ApWriteTxn(ADDR2B, wdata, ack);
1796 }
1797 else
1798 {
1799 ec = swd_.DpWriteTxn(static_cast<LibXR::Debug::SwdProtocol::DpWriteReg>(ADDR2B),
1800 wdata, ack);
1801 }
1802
1803 response_value = ack_to_dap(ack);
1804 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1805 {
1806 break;
1807 }
1808 if (ec != ErrorCode::OK)
1809 {
1810 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1811 break;
1812 }
1813
1814 if (TS)
1815 {
1816 if (!push_timestamp())
1817 {
1818 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1819 break;
1820 }
1821 }
1822
1823 response_count++;
1824 check_write = true;
1825 }
1826 else
1827 {
1828 if (MATCH_VALUE)
1829 {
1830 if (!flush_pending_if_any())
1831 {
1832 break;
1833 }
1834
1835 if (req_off + 4u > req_len)
1836 {
1837 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1838 break;
1839 }
1840
1841 uint32_t match_val = 0u;
1842 Memory::FastCopy(&match_val, &req[req_off], sizeof(match_val));
1843 req_off = static_cast<uint16_t>(req_off + 4u);
1844
1845 uint32_t rdata = 0u;
1846 uint32_t retry = dap_state_.transfer_cfg.match_retry;
1847 bool matched = false;
1848
1849 while (true)
1850 {
1851 if (AP)
1852 {
1853 ec = swd_.ApReadTxn(ADDR2B, rdata, ack);
1854 if (ec == ErrorCode::OK && ack == LibXR::Debug::SwdProtocol::Ack::OK)
1855 {
1856 check_write = false;
1857 }
1858 }
1859 else
1860 {
1861 ec = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
1862 rdata, ack);
1863 }
1864
1865 response_value = ack_to_dap(ack);
1866 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1867 {
1868 break;
1869 }
1870 if (ec != ErrorCode::OK)
1871 {
1872 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1873 break;
1874 }
1875
1876 if ((rdata & match_mask_) == (match_val & match_mask_))
1877 {
1878 matched = true;
1879 break;
1880 }
1881
1882 if (retry == 0u)
1883 {
1884 break;
1885 }
1886 --retry;
1887 }
1888
1889 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1890 {
1891 break;
1892 }
1893
1894 if (!matched)
1895 {
1896 response_value =
1897 static_cast<uint8_t>(LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK |
1898 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MISMATCH);
1899 break;
1900 }
1901
1902 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1903 response_count++;
1904 continue;
1905 }
1906
1907 if (!AP)
1908 {
1909 if (!flush_pending_if_any())
1910 {
1911 break;
1912 }
1913
1914 uint32_t rdata = 0u;
1915 ec = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
1916 rdata, ack);
1917
1918 response_value = ack_to_dap(ack);
1919 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1920 {
1921 break;
1922 }
1923 if (ec != ErrorCode::OK)
1924 {
1925 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1926 break;
1927 }
1928
1929 if (!ensure_space(bytes_for_read(TS)))
1930 {
1931 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1932 break;
1933 }
1934
1935 if (!emit_read_with_ts(TS, rdata))
1936 {
1937 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1938 break;
1939 }
1940
1941 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1942 continue;
1943 }
1944
1945 if (!pending.valid)
1946 {
1947 uint32_t dummy_posted = 0u;
1948 ec = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
1949
1950 response_value = ack_to_dap(ack);
1951 if (response_value != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1952 {
1953 break;
1954 }
1955 if (ec != ErrorCode::OK)
1956 {
1957 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1958 break;
1959 }
1960
1961 pending.valid = true;
1962 pending.need_ts = TS;
1963 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
1964 }
1965 else
1966 {
1967 if (!ensure_space(bytes_for_read(pending.need_ts)))
1968 {
1969 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1970 break;
1971 }
1972
1973 uint32_t posted_prev = 0u;
1974 ec = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
1975
1976 const uint8_t CUR_V = ack_to_dap(ack);
1977 if (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK || ec != ErrorCode::OK)
1978 {
1979 const uint8_t PRIOR_FAIL = (CUR_V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
1980 ? CUR_V
1981 : LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1982
1983 if (!complete_pending_by_rdbuff())
1984 {
1985 break;
1986 }
1987
1988 response_value = PRIOR_FAIL;
1989 break;
1990 }
1991
1992 if (!emit_read_with_ts(pending.need_ts, posted_prev))
1993 {
1994 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
1995 break;
1996 }
1997
1998 pending.valid = true;
1999 pending.need_ts = TS;
2000 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2001 }
2002 }
2003
2004 if (dap_state_.transfer_abort)
2005 {
2006 dap_state_.transfer_abort = false;
2007 break;
2008 }
2009 }
2010
2011 if (pending.valid)
2012 {
2013 const uint8_t PRIOR_FAIL = response_value;
2014
2015 if (!complete_pending_by_rdbuff())
2016 {
2017 }
2018 else
2019 {
2020 if (PRIOR_FAIL != 0u && PRIOR_FAIL != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2021 {
2022 response_value = PRIOR_FAIL;
2023 }
2024 }
2025 }
2026
2027 if (response_value == LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK && check_write)
2028 {
2029 uint32_t dummy = 0u;
2030 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2031 const ErrorCode EC = swd_.DpReadRdbuffTxn(dummy, ack);
2032 const uint8_t V = ack_to_dap(ack);
2033
2034 if (V != LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK)
2035 {
2036 response_value = V;
2037 }
2038 else if (EC != ErrorCode::OK)
2039 {
2040 response_value = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2041 }
2042 }
2043
2044 resp[1] = response_count;
2045 resp[2] = response_value;
2046 out_len = resp_off;
2047 return ErrorCode::OK;
2048}
2049
2050template <typename SwdPort>
2051ErrorCode DapLinkV1Class<SwdPort>::HandleTransferBlock(bool /*in_isr*/,
2052 const uint8_t* req,
2053 uint16_t req_len, uint8_t* resp,
2054 uint16_t resp_cap,
2055 uint16_t& out_len)
2056{
2057 if (!resp || resp_cap < 4u)
2058 {
2059 out_len = 0u;
2060 return ErrorCode::NOT_FOUND;
2061 }
2062
2063 resp[0] = ToU8(LibXR::USB::DapLinkV1Def::CommandId::TRANSFER_BLOCK);
2064 resp[1] = 0u;
2065 resp[2] = 0u;
2066 resp[3] = 0u;
2067 out_len = 4u;
2068
2069 if (!req || req_len < 5u)
2070 {
2071 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2072 return ErrorCode::ARG_ERR;
2073 }
2074
2075 if (dap_state_.transfer_abort)
2076 {
2077 dap_state_.transfer_abort = false;
2078 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2079 return ErrorCode::OK;
2080 }
2081
2082 uint16_t count = 0u;
2083 Memory::FastCopy(&count, &req[2], sizeof(count));
2084
2085 const uint8_t DAP_RQ = req[4];
2086
2087 if ((DAP_RQ & (LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_VALUE |
2088 LibXR::USB::DapLinkV1Def::DAP_TRANSFER_MATCH_MASK)) != 0u)
2089 {
2090 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2092 }
2094 {
2095 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2097 }
2098
2099 if (count == 0u)
2100 {
2101 const uint16_t DONE0 = 0u;
2102 Memory::FastCopy(&resp[1], &DONE0, sizeof(DONE0));
2103 resp[3] = LibXR::USB::DapLinkV1Def::DAP_TRANSFER_OK;
2104 out_len = 4u;
2105 return ErrorCode::OK;
2106 }
2107
2108 const bool AP = LibXR::USB::DapLinkV1Def::req_is_ap(DAP_RQ);
2109 const bool RNW = LibXR::USB::DapLinkV1Def::req_is_read(DAP_RQ);
2110 const uint8_t ADDR2B = LibXR::USB::DapLinkV1Def::req_addr2b(DAP_RQ);
2111
2112 uint16_t done = 0u;
2113 uint8_t xresp = 0u;
2114
2115 uint16_t req_off = 5u;
2116 uint16_t resp_off = 4u;
2117
2118 if (!RNW)
2119 {
2120 for (uint32_t i = 0; i < count; ++i)
2121 {
2122 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2124
2125 if (req_off + 4u > req_len)
2126 {
2127 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2128 break;
2129 }
2130
2131 uint32_t wdata = 0u;
2132 Memory::FastCopy(&wdata, &req[req_off], sizeof(wdata));
2133 req_off = static_cast<uint16_t>(req_off + 4u);
2134
2135 if (AP)
2136 {
2137 ec = swd_.ApWriteTxn(ADDR2B, wdata, ack);
2138 }
2139 else
2140 {
2141 ec = swd_.DpWriteTxn(static_cast<LibXR::Debug::SwdProtocol::DpWriteReg>(ADDR2B),
2142 wdata, ack);
2143 }
2144
2145 xresp = MapAckToDapResp(ack);
2146 if (xresp == 0u)
2147 {
2148 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2149 break;
2150 }
2151
2152 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2153 {
2154 break;
2155 }
2156
2157 if (ec != ErrorCode::OK)
2158 {
2159 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2160 break;
2161 }
2162
2163 done = static_cast<uint16_t>(i + 1u);
2164 }
2165
2166 Memory::FastCopy(&resp[1], &done, sizeof(done));
2167 resp[3] = xresp;
2168 out_len = resp_off;
2169 return ErrorCode::OK;
2170 }
2171
2172 if (!AP)
2173 {
2174 for (uint32_t i = 0; i < count; ++i)
2175 {
2176 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2178 uint32_t rdata = 0u;
2179
2180 if (resp_off + 4u > resp_cap)
2181 {
2182 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2183 break;
2184 }
2185
2186 ec = swd_.DpReadTxn(static_cast<LibXR::Debug::SwdProtocol::DpReadReg>(ADDR2B),
2187 rdata, ack);
2188
2189 xresp = MapAckToDapResp(ack);
2190 if (xresp == 0u)
2191 {
2192 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2193 break;
2194 }
2195
2196 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2197 {
2198 break;
2199 }
2200
2201 if (ec != ErrorCode::OK)
2202 {
2203 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2204 break;
2205 }
2206
2207 Memory::FastCopy(&resp[resp_off], &rdata, sizeof(rdata));
2208 resp_off = static_cast<uint16_t>(resp_off + 4u);
2209 done = static_cast<uint16_t>(i + 1u);
2210 }
2211
2212 Memory::FastCopy(&resp[1], &done, sizeof(done));
2213 resp[3] = xresp;
2214 out_len = resp_off;
2215 return ErrorCode::OK;
2216 }
2217
2218 {
2219 LibXR::Debug::SwdProtocol::Ack ack = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2221
2222 uint32_t dummy_posted = 0u;
2223 ec = swd_.ApReadPostedTxn(ADDR2B, dummy_posted, ack);
2224 xresp = MapAckToDapResp(ack);
2225
2226 if (xresp == 0u)
2227 {
2228 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2229 goto out_ap_read; // NOLINT
2230 }
2231 if (ack != LibXR::Debug::SwdProtocol::Ack::OK)
2232 {
2233 goto out_ap_read; // NOLINT
2234 }
2235 if (ec != ErrorCode::OK)
2236 {
2237 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2238 goto out_ap_read; // NOLINT
2239 }
2240
2241 for (uint32_t i = 1; i < count; ++i)
2242 {
2243 if (resp_off + 4u > resp_cap)
2244 {
2245 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2246 goto out_ap_read; // NOLINT
2247 }
2248
2249 uint32_t posted_prev = 0u;
2250 ec = swd_.ApReadPostedTxn(ADDR2B, posted_prev, ack);
2251 const uint8_t CUR = MapAckToDapResp(ack);
2252
2253 if (CUR == 0u)
2254 {
2255 xresp = CUR | LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2256 goto out_ap_read; // NOLINT
2257 }
2258
2259 if (ack != LibXR::Debug::SwdProtocol::Ack::OK || ec != ErrorCode::OK)
2260 {
2261 if (resp_off + 4u <= resp_cap)
2262 {
2263 uint32_t last = 0u;
2264 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2265 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2266 const uint8_t V2 = MapAckToDapResp(ack2);
2267
2268 if (V2 == 1u && EC2 == ErrorCode::OK)
2269 {
2270 Memory::FastCopy(&resp[resp_off], &last, sizeof(last));
2271 resp_off = static_cast<uint16_t>(resp_off + 4u);
2272 done = static_cast<uint16_t>(i);
2273 }
2274 else
2275 {
2276 xresp = V2;
2277 if (EC2 != ErrorCode::OK)
2278 {
2279 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2280 }
2281 goto out_ap_read; // NOLINT
2282 }
2283 }
2284
2285 xresp = CUR;
2286 if (ec != ErrorCode::OK)
2287 {
2288 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2289 }
2290 goto out_ap_read; // NOLINT
2291 }
2292
2293 Memory::FastCopy(&resp[resp_off], &posted_prev, sizeof(posted_prev));
2294 resp_off = static_cast<uint16_t>(resp_off + 4u);
2295 done = static_cast<uint16_t>(i);
2296 xresp = CUR;
2297 }
2298
2299 if (resp_off + 4u > resp_cap)
2300 {
2301 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2302 goto out_ap_read; // NOLINT
2303 }
2304
2305 {
2306 uint32_t last = 0u;
2307 LibXR::Debug::SwdProtocol::Ack ack2 = LibXR::Debug::SwdProtocol::Ack::PROTOCOL;
2308 const ErrorCode EC2 = swd_.DpReadRdbuffTxn(last, ack2);
2309 const uint8_t V2 = MapAckToDapResp(ack2);
2310
2311 xresp = V2;
2312 if (V2 != 1u)
2313 {
2314 goto out_ap_read; // NOLINT
2315 }
2316 if (EC2 != ErrorCode::OK)
2317 {
2318 xresp |= LibXR::USB::DapLinkV1Def::DAP_TRANSFER_ERROR;
2319 goto out_ap_read; // NOLINT
2320 }
2321
2322 Memory::FastCopy(&resp[resp_off], &last, sizeof(last));
2323 resp_off = static_cast<uint16_t>(resp_off + 4u);
2324 done = count;
2325 }
2326
2327 out_ap_read:
2328 Memory::FastCopy(&resp[1], &done, sizeof(done));
2329 resp[3] = xresp;
2330 out_len = resp_off;
2331 return ErrorCode::OK;
2332 }
2333}
2334
2335template <typename SwdPort>
2336void DapLinkV1Class<SwdPort>::DriveReset(bool release)
2337{
2338 last_nreset_level_high_ = release;
2339
2340 if (release)
2341 {
2342 swj_shadow_ |= LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET;
2343 }
2344 else
2345 {
2346 swj_shadow_ = static_cast<uint8_t>(
2347 swj_shadow_ & static_cast<uint8_t>(~LibXR::USB::DapLinkV1Def::DAP_SWJ_NRESET));
2348 }
2349
2350 if (nreset_gpio_ != nullptr)
2351 {
2352 (void)nreset_gpio_->Write(release);
2353 }
2354}
2355
2356template <typename SwdPort>
2357void DapLinkV1Class<SwdPort>::DelayUsIfAllowed(bool /*in_isr*/, uint32_t us)
2358{
2360}
2361
2362} // namespace LibXR::USB
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:142
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:159
常量原始数据封装类。 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).
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
Definition gpio.hpp:13
virtual bool Read()=0
读取 GPIO 引脚状态。Reads the GPIO pin state.
virtual void Write(bool value)=0
写入 GPIO 引脚状态。Writes the GPIO pin state.
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:5
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
Definition timebase.hpp:49
static void DelayMicroseconds(uint32_t us)
微秒级延时 / Delay in microseconds
Definition timebase.hpp:69
USB描述符基类 USB descriptor base class.
Definition desc_dev.hpp:40
Data data_
设备描述符数据实例 / Internal data instance
Definition desc_dev.hpp:109
@ PER_INTERFACE
每个接口自定义类 / Per-interface
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
@ EP_AUTO
自动分配端点号 / Auto allocate
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
void SetActiveLength(uint16_t len)
设置当前活动缓冲区有效长度 / Set active buffer valid length
Definition ep.hpp:271
virtual size_t MaxTransferSize() const
返回当前最大可传输字节数 / Return maximum transferable size at this time
Definition ep.hpp:283
void SetOnTransferCompleteCallback(Callback< ConstRawData & > cb)
设置传输完成回调 / Set transfer complete callback
Definition ep.hpp:262
virtual void Configure(const Config &cfg)=0
配置端点协议参数 / Configure endpoint protocol parameters
@ INTERRUPT
中断端点 / Interrupt
uint16_t MaxPacketSize() const
获取最大包长 / Get max packet size
Definition ep.hpp:226
State GetState() const
获取端点状态 / Get endpoint state
Definition ep.hpp:208
virtual ErrorCode Transfer(size_t size)=0
启动一次传输 / Start a transfer
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
Definition ep.hpp:246
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
USB HID(Human Interface Device)基类,支持可选 OUT 端点、自动生成描述符,适合键盘、鼠标、手柄等扩展。 USB HID (Human Interface Device)...
Definition hid.hpp:24
void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化 HID 设备 Deinitialize HID device.
Definition hid.hpp:267
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool) override
初始化 HID 设备,自动选择端点与描述符块 Initialize HID device and select descriptor block (IN or IN+OUT).
Definition hid.hpp:145
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
传输策略(WAIT 重试与空闲周期插入)。Transfer policy (WAIT retry & idle insertion).
Definition swd.hpp:31
uint8_t idle_cycles
空闲周期数。Idle cycles.
Definition swd.hpp:32
uint16_t wait_retry
WAIT 最大重试次数。Maximum WAIT retries.
Definition swd.hpp:33
控制请求(Class/Vendor)处理结果 / Control request (Class/Vendor) handling result
ClassID bDeviceClass
设备类代码 / Device class code
Definition desc_dev.hpp:93
uint8_t bDeviceSubClass
设备子类代码 / Device subclass code
Definition desc_dev.hpp:94
uint8_t bDeviceProtocol
协议代码 / Protocol code
Definition desc_dev.hpp:95