libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_usb_endpoint_otghs.cpp
1#include <cstdint>
2
3#include "ch32_usb_endpoint.hpp"
4#include "ep.hpp"
5#include "libxr_time.hpp"
6#include "timebase.hpp"
7
8using namespace LibXR;
9
10#if defined(USBHSD)
11
12// NOLINTBEGIN
13static inline volatile uint8_t* GetTxControlAddr(USB::Endpoint::EPNumber ep_num)
14{
15 return reinterpret_cast<volatile uint8_t*>(
16 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_TX_CTRL) +
17 static_cast<int>(ep_num) * 4);
18}
19
20static inline volatile uint8_t* GetRxControlAddr(USB::Endpoint::EPNumber ep_num)
21{
22 return reinterpret_cast<volatile uint8_t*>(
23 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_TX_CTRL) +
24 static_cast<int>(ep_num) * 4 + 1);
25}
26
27static inline volatile uint16_t* GetTxLenAddr(USB::Endpoint::EPNumber ep_num)
28{
29 return reinterpret_cast<volatile uint16_t*>(
30 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_TX_LEN) +
31 static_cast<int>(ep_num) * 4);
32}
33
34static inline volatile uint16_t* GetRxMaxLenAddr(USB::Endpoint::EPNumber ep_num)
35{
36 return reinterpret_cast<volatile uint16_t*>(
37 reinterpret_cast<volatile uint8_t*>(&USBHSD->UEP0_MAX_LEN) +
38 static_cast<int>(ep_num) * 2);
39}
40
41static inline volatile uint32_t* GetTxDmaAddr(USB::Endpoint::EPNumber ep_num)
42{
43 if (ep_num == USB::Endpoint::EPNumber::EP0) return &USBHSD->UEP0_DMA;
44 return reinterpret_cast<volatile uint32_t*>(
45 reinterpret_cast<volatile uint32_t*>(&USBHSD->UEP1_TX_DMA) +
46 (static_cast<int>(ep_num) - 1));
47}
48
49static inline volatile uint32_t* GetRxDmaAddr(USB::Endpoint::EPNumber ep_num)
50{
51 if (ep_num == USB::Endpoint::EPNumber::EP0) return &USBHSD->UEP0_DMA;
52 return reinterpret_cast<volatile uint32_t*>(
53 reinterpret_cast<volatile uint32_t*>(&USBHSD->UEP1_RX_DMA) +
54 (static_cast<int>(ep_num) - 1));
55}
56
57static void SetTxLen(USB::Endpoint::EPNumber ep_num, uint32_t value)
58{
59 *GetTxLenAddr(ep_num) = value;
60}
61
62static void SetTxDmaBuffer(USB::Endpoint::EPNumber ep_num, void* buffer,
63 uint32_t buffer_size, bool double_buffer)
64{
65 uint8_t* buf_base = reinterpret_cast<uint8_t*>(buffer);
66 uint8_t* buf_alt = buf_base + buffer_size / 2;
67
68 if (ep_num == USB::Endpoint::EPNumber::EP0)
69 {
70 USBHSD->UEP0_DMA = (uint32_t)buf_base;
71 }
72 else
73 {
74 *GetTxDmaAddr(ep_num) = (uint32_t)buf_base;
75 if (double_buffer) *GetRxDmaAddr(ep_num) = (uint32_t)buf_alt;
76 }
77
78 int idx = static_cast<int>(ep_num);
79 if (double_buffer && ep_num != USB::Endpoint::EPNumber::EP0)
80 USBHSD->BUF_MODE |= (1 << idx);
81 else
82 USBHSD->BUF_MODE &= ~(1 << idx);
83}
84
85static void SetRxDmaBuffer(USB::Endpoint::EPNumber ep_num, void* buffer,
86 uint32_t buffer_size, bool double_buffer)
87{
88 uint8_t* buf_base = reinterpret_cast<uint8_t*>(buffer);
89 uint8_t* buf_alt = buf_base + buffer_size / 2;
90
91 if (ep_num == USB::Endpoint::EPNumber::EP0)
92 {
93 USBHSD->UEP0_DMA = (uint32_t)buf_base;
94 }
95 else
96 {
97 *GetRxDmaAddr(ep_num) = (uint32_t)buf_base;
98 if (double_buffer) *GetTxDmaAddr(ep_num) = (uint32_t)buf_alt;
99 }
100
101 int idx = static_cast<int>(ep_num);
102 if (double_buffer && ep_num != USB::Endpoint::EPNumber::EP0)
103 USBHSD->BUF_MODE |= (1 << idx);
104 else
105 USBHSD->BUF_MODE &= ~(1 << idx);
106}
107
108static void EnableTx(USB::Endpoint::EPNumber ep_num)
109{
110 switch (ep_num)
111 {
112 case USB::Endpoint::EPNumber::EP0:
113 USBHSD->ENDP_CONFIG |= USBHS_UEP0_T_EN;
114 break;
115 case USB::Endpoint::EPNumber::EP1:
116 USBHSD->ENDP_CONFIG |= USBHS_UEP1_T_EN;
117 break;
118 case USB::Endpoint::EPNumber::EP2:
119 USBHSD->ENDP_CONFIG |= USBHS_UEP2_T_EN;
120 break;
121 case USB::Endpoint::EPNumber::EP3:
122 USBHSD->ENDP_CONFIG |= USBHS_UEP3_T_EN;
123 break;
124 case USB::Endpoint::EPNumber::EP4:
125 USBHSD->ENDP_CONFIG |= USBHS_UEP4_T_EN;
126 break;
127 case USB::Endpoint::EPNumber::EP5:
128 USBHSD->ENDP_CONFIG |= USBHS_UEP5_T_EN;
129 break;
130 case USB::Endpoint::EPNumber::EP6:
131 USBHSD->ENDP_CONFIG |= USBHS_UEP6_T_EN;
132 break;
133 case USB::Endpoint::EPNumber::EP7:
134 USBHSD->ENDP_CONFIG |= USBHS_UEP7_T_EN;
135 break;
136 case USB::Endpoint::EPNumber::EP8:
137 USBHSD->ENDP_CONFIG |= USBHS_UEP8_T_EN;
138 break;
139 case USB::Endpoint::EPNumber::EP9:
140 USBHSD->ENDP_CONFIG |= USBHS_UEP9_T_EN;
141 break;
142 case USB::Endpoint::EPNumber::EP10:
143 USBHSD->ENDP_CONFIG |= USBHS_UEP10_T_EN;
144 break;
145 case USB::Endpoint::EPNumber::EP11:
146 USBHSD->ENDP_CONFIG |= USBHS_UEP11_T_EN;
147 break;
148 case USB::Endpoint::EPNumber::EP12:
149 USBHSD->ENDP_CONFIG |= USBHS_UEP12_T_EN;
150 break;
151 case USB::Endpoint::EPNumber::EP13:
152 USBHSD->ENDP_CONFIG |= USBHS_UEP13_T_EN;
153 break;
154 case USB::Endpoint::EPNumber::EP14:
155 USBHSD->ENDP_CONFIG |= USBHS_UEP14_T_EN;
156 break;
157 case USB::Endpoint::EPNumber::EP15:
158 USBHSD->ENDP_CONFIG |= USBHS_UEP15_T_EN;
159 break;
160 default:
161 break;
162 }
163}
164
165static void DisableTx(USB::Endpoint::EPNumber ep_num)
166{
167 switch (ep_num)
168 {
169 case USB::Endpoint::EPNumber::EP0:
170 USBHSD->ENDP_CONFIG &= ~USBHS_UEP0_T_EN;
171 break;
172 case USB::Endpoint::EPNumber::EP1:
173 USBHSD->ENDP_CONFIG &= ~USBHS_UEP1_T_EN;
174 break;
175 case USB::Endpoint::EPNumber::EP2:
176 USBHSD->ENDP_CONFIG &= ~USBHS_UEP2_T_EN;
177 break;
178 case USB::Endpoint::EPNumber::EP3:
179 USBHSD->ENDP_CONFIG &= ~USBHS_UEP3_T_EN;
180 break;
181 case USB::Endpoint::EPNumber::EP4:
182 USBHSD->ENDP_CONFIG &= ~USBHS_UEP4_T_EN;
183 break;
184 case USB::Endpoint::EPNumber::EP5:
185 USBHSD->ENDP_CONFIG &= ~USBHS_UEP5_T_EN;
186 break;
187 case USB::Endpoint::EPNumber::EP6:
188 USBHSD->ENDP_CONFIG &= ~USBHS_UEP6_T_EN;
189 break;
190 case USB::Endpoint::EPNumber::EP7:
191 USBHSD->ENDP_CONFIG &= ~USBHS_UEP7_T_EN;
192 break;
193 case USB::Endpoint::EPNumber::EP8:
194 USBHSD->ENDP_CONFIG &= ~USBHS_UEP8_T_EN;
195 break;
196 case USB::Endpoint::EPNumber::EP9:
197 USBHSD->ENDP_CONFIG &= ~USBHS_UEP9_T_EN;
198 break;
199 case USB::Endpoint::EPNumber::EP10:
200 USBHSD->ENDP_CONFIG &= ~USBHS_UEP10_T_EN;
201 break;
202 case USB::Endpoint::EPNumber::EP11:
203 USBHSD->ENDP_CONFIG &= ~USBHS_UEP11_T_EN;
204 break;
205 case USB::Endpoint::EPNumber::EP12:
206 USBHSD->ENDP_CONFIG &= ~USBHS_UEP12_T_EN;
207 break;
208 case USB::Endpoint::EPNumber::EP13:
209 USBHSD->ENDP_CONFIG &= ~USBHS_UEP13_T_EN;
210 break;
211 case USB::Endpoint::EPNumber::EP14:
212 USBHSD->ENDP_CONFIG &= ~USBHS_UEP14_T_EN;
213 break;
214 case USB::Endpoint::EPNumber::EP15:
215 USBHSD->ENDP_CONFIG &= ~USBHS_UEP15_T_EN;
216 break;
217 default:
218 break;
219 }
220}
221
222static void EnableRx(USB::Endpoint::EPNumber ep_num)
223{
224 switch (ep_num)
225 {
226 case USB::Endpoint::EPNumber::EP0:
227 USBHSD->ENDP_CONFIG |= USBHS_UEP0_R_EN;
228 break;
229 case USB::Endpoint::EPNumber::EP1:
230 USBHSD->ENDP_CONFIG |= USBHS_UEP1_R_EN;
231 break;
232 case USB::Endpoint::EPNumber::EP2:
233 USBHSD->ENDP_CONFIG |= USBHS_UEP2_R_EN;
234 break;
235 case USB::Endpoint::EPNumber::EP3:
236 USBHSD->ENDP_CONFIG |= USBHS_UEP3_R_EN;
237 break;
238 case USB::Endpoint::EPNumber::EP4:
239 USBHSD->ENDP_CONFIG |= USBHS_UEP4_R_EN;
240 break;
241 case USB::Endpoint::EPNumber::EP5:
242 USBHSD->ENDP_CONFIG |= USBHS_UEP5_R_EN;
243 break;
244 case USB::Endpoint::EPNumber::EP6:
245 USBHSD->ENDP_CONFIG |= USBHS_UEP6_R_EN;
246 break;
247 case USB::Endpoint::EPNumber::EP7:
248 USBHSD->ENDP_CONFIG |= USBHS_UEP7_R_EN;
249 break;
250 case USB::Endpoint::EPNumber::EP8:
251 USBHSD->ENDP_CONFIG |= USBHS_UEP8_R_EN;
252 break;
253 case USB::Endpoint::EPNumber::EP9:
254 USBHSD->ENDP_CONFIG |= USBHS_UEP9_R_EN;
255 break;
256 case USB::Endpoint::EPNumber::EP10:
257 USBHSD->ENDP_CONFIG |= USBHS_UEP10_R_EN;
258 break;
259 case USB::Endpoint::EPNumber::EP11:
260 USBHSD->ENDP_CONFIG |= USBHS_UEP11_R_EN;
261 break;
262 case USB::Endpoint::EPNumber::EP12:
263 USBHSD->ENDP_CONFIG |= USBHS_UEP12_R_EN;
264 break;
265 case USB::Endpoint::EPNumber::EP13:
266 USBHSD->ENDP_CONFIG |= USBHS_UEP13_R_EN;
267 break;
268 case USB::Endpoint::EPNumber::EP14:
269 USBHSD->ENDP_CONFIG |= USBHS_UEP14_R_EN;
270 break;
271 case USB::Endpoint::EPNumber::EP15:
272 USBHSD->ENDP_CONFIG |= USBHS_UEP15_R_EN;
273 break;
274 default:
275 break;
276 }
277}
278
279static void DisableRx(USB::Endpoint::EPNumber ep_num)
280{
281 switch (ep_num)
282 {
283 case USB::Endpoint::EPNumber::EP0:
284 USBHSD->ENDP_CONFIG &= ~USBHS_UEP0_R_EN;
285 break;
286 case USB::Endpoint::EPNumber::EP1:
287 USBHSD->ENDP_CONFIG &= ~USBHS_UEP1_R_EN;
288 break;
289 case USB::Endpoint::EPNumber::EP2:
290 USBHSD->ENDP_CONFIG &= ~USBHS_UEP2_R_EN;
291 break;
292 case USB::Endpoint::EPNumber::EP3:
293 USBHSD->ENDP_CONFIG &= ~USBHS_UEP3_R_EN;
294 break;
295 case USB::Endpoint::EPNumber::EP4:
296 USBHSD->ENDP_CONFIG &= ~USBHS_UEP4_R_EN;
297 break;
298 case USB::Endpoint::EPNumber::EP5:
299 USBHSD->ENDP_CONFIG &= ~USBHS_UEP5_R_EN;
300 break;
301 case USB::Endpoint::EPNumber::EP6:
302 USBHSD->ENDP_CONFIG &= ~USBHS_UEP6_R_EN;
303 break;
304 case USB::Endpoint::EPNumber::EP7:
305 USBHSD->ENDP_CONFIG &= ~USBHS_UEP7_R_EN;
306 break;
307 case USB::Endpoint::EPNumber::EP8:
308 USBHSD->ENDP_CONFIG &= ~USBHS_UEP8_R_EN;
309 break;
310 case USB::Endpoint::EPNumber::EP9:
311 USBHSD->ENDP_CONFIG &= ~USBHS_UEP9_R_EN;
312 break;
313 case USB::Endpoint::EPNumber::EP10:
314 USBHSD->ENDP_CONFIG &= ~USBHS_UEP10_R_EN;
315 break;
316 case USB::Endpoint::EPNumber::EP11:
317 USBHSD->ENDP_CONFIG &= ~USBHS_UEP11_R_EN;
318 break;
319 case USB::Endpoint::EPNumber::EP12:
320 USBHSD->ENDP_CONFIG &= ~USBHS_UEP12_R_EN;
321 break;
322 case USB::Endpoint::EPNumber::EP13:
323 USBHSD->ENDP_CONFIG &= ~USBHS_UEP13_R_EN;
324 break;
325 case USB::Endpoint::EPNumber::EP14:
326 USBHSD->ENDP_CONFIG &= ~USBHS_UEP14_R_EN;
327 break;
328 case USB::Endpoint::EPNumber::EP15:
329 USBHSD->ENDP_CONFIG &= ~USBHS_UEP15_R_EN;
330 break;
331 default:
332 break;
333 }
334}
335// NOLINTEND
336
337CH32EndpointOtgHs::CH32EndpointOtgHs(EPNumber ep_num, Direction dir,
338 LibXR::RawData buffer, bool double_buffer)
339 : Endpoint(ep_num, dir, buffer), hw_double_buffer_(double_buffer), dma_buffer_(buffer)
340{
341 map_otg_hs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
342
343 if (dir == Direction::IN)
344 {
345 SetTxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, double_buffer);
346 }
347 else
348 {
349 SetRxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, double_buffer);
350 }
351
352 if (dir == Direction::IN)
353 {
354 SetTxLen(GetNumber(), 0);
355 *GetTxControlAddr(GetNumber()) = USBHS_UEP_T_RES_NAK;
356 }
357 else
358 {
359 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_NAK;
360 }
361}
362
363void CH32EndpointOtgHs::Configure(const Config& cfg)
364{
365 auto& ep_cfg = GetConfig();
366 ep_cfg = cfg;
367
368 if (GetNumber() != EPNumber::EP0 && hw_double_buffer_)
369 {
370 ep_cfg.double_buffer = true;
371 }
372 else
373 {
374 if (ep_cfg.double_buffer)
375 {
376 ASSERT(false);
377 }
378 ep_cfg.double_buffer = false;
379 }
380
381 if (ep_cfg.max_packet_size > GetBuffer().size_)
382 {
383 ep_cfg.max_packet_size = GetBuffer().size_;
384 }
385
386 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_NAK;
387 *GetTxControlAddr(GetNumber()) = USBHS_UEP_T_RES_NAK;
388
389 SetTxLen(GetNumber(), 0);
390
391 {
392 const int idx = static_cast<int>(GetNumber());
393 if (GetDirection() == Direction::IN)
394 {
395 if (GetType() == Type::ISOCHRONOUS)
396 USBHSD->ENDP_TYPE |= (USBHS_UEP0_T_TYPE << idx);
397 else
398 USBHSD->ENDP_TYPE &= ~(USBHS_UEP0_T_TYPE << idx);
399 }
400 else
401 {
402 if (GetType() == Type::ISOCHRONOUS)
403 USBHSD->ENDP_TYPE |= (USBHS_UEP0_R_TYPE << idx);
404 else
405 USBHSD->ENDP_TYPE &= ~(USBHS_UEP0_R_TYPE << idx);
406 }
407 }
408
409 if (GetDirection() == Direction::IN)
410 {
411 if (GetType() != Type::ISOCHRONOUS)
412 {
413 EnableTx(GetNumber());
414 }
415 else
416 {
417 DisableTx(GetNumber());
418 }
419 DisableRx(GetNumber());
420 SetTxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, hw_double_buffer_);
421 }
422 else
423 {
424 DisableTx(GetNumber());
425 EnableRx(GetNumber());
426 SetRxDmaBuffer(GetNumber(), dma_buffer_.addr_, dma_buffer_.size_, hw_double_buffer_);
427
428 if (GetType() == Type::ISOCHRONOUS)
429 {
430 *GetRxMaxLenAddr(GetNumber()) = ep_cfg.max_packet_size;
431 }
432 }
433
434 SetState(State::IDLE);
435}
436
437void CH32EndpointOtgHs::Close()
438{
439 DisableTx(GetNumber());
440 DisableRx(GetNumber());
441
442 *GetTxControlAddr(GetNumber()) = USBHS_UEP_T_RES_NAK;
443 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_NAK;
444
445 SetState(State::DISABLED);
446}
447
448ErrorCode CH32EndpointOtgHs::Transfer(size_t size)
449{
450 if (GetState() == State::BUSY)
451 {
452 return ErrorCode::BUSY;
453 }
454
455 auto buffer = GetBuffer();
456 if (buffer.size_ < size)
457 {
458 return ErrorCode::NO_BUFF;
459 }
460
461 bool is_in = (GetDirection() == Direction::IN);
462
463 if (is_in && UseDoubleBuffer() && GetType() != Type::ISOCHRONOUS)
464 {
465 SwitchBuffer();
466 }
467
468 if (GetNumber() == EPNumber::EP0)
469 {
470 if (size == 0)
471 {
472 tog0_ = true;
473 tog1_ = false;
474 }
475 }
476
477 last_transfer_size_ = size;
478 SetState(State::BUSY);
479
480 if (is_in)
481 {
482 if (GetType() == Type::ISOCHRONOUS)
483 {
484 EnableTx(GetNumber());
485 }
486
487 SetTxLen(GetNumber(), size);
488 auto addr = GetTxControlAddr(GetNumber());
489
490 if (GetType() != Type::ISOCHRONOUS)
491 {
492 *addr = USBHS_UEP_T_RES_ACK |
493 (*addr & (~(USBHS_UEP_T_RES_MASK | USBHS_UEP_T_TOG_MDATA))) |
494 (tog0_ ? USBHS_UEP_T_TOG_DATA1 : 0);
495 }
496 else
497 {
498 *addr = (uint8_t)((*addr & ~(USBHS_UEP_T_RES_MASK | USBHS_UEP_T_TOG_MASK)) |
499 USBHS_UEP_T_TOG_AUTO);
500 }
501 }
502 else
503 {
504 auto addr = GetRxControlAddr(GetNumber());
505
506 if (GetType() != Type::ISOCHRONOUS)
507 {
508 *addr = USBHS_UEP_R_RES_ACK |
509 (*addr & (~(USBHS_UEP_R_RES_MASK | USBHS_UEP_R_TOG_MDATA))) |
510 (tog0_ ? USBHS_UEP_R_TOG_DATA1 : 0);
511 }
512 else
513 {
514 *addr = USBHS_UEP_R_RES_ACK |
515 (*addr & (~(USBHS_UEP_R_RES_MASK | USBHS_UEP_R_TOG_MDATA)));
516 }
517 }
518
519 if (GetNumber() == EPNumber::EP0)
520 {
521 tog0_ = !tog0_;
522 }
523
524 return ErrorCode::OK;
525}
526
527ErrorCode CH32EndpointOtgHs::Stall()
528{
529 if (GetState() != State::IDLE)
530 {
531 return ErrorCode::BUSY;
532 }
533
534 bool is_in = (GetDirection() == Direction::IN);
535 if (is_in)
536 {
537 *GetTxControlAddr(GetNumber()) |= USBHS_UEP_T_RES_STALL;
538 }
539 else
540 {
541 *GetRxControlAddr(GetNumber()) |= USBHS_UEP_R_RES_STALL;
542 }
543 SetState(State::STALLED);
544 return ErrorCode::OK;
545}
546
547ErrorCode CH32EndpointOtgHs::ClearStall()
548{
549 if (GetState() != State::STALLED)
550 {
551 return ErrorCode::FAILED;
552 }
553
554 bool is_in = (GetDirection() == Direction::IN);
555 if (is_in)
556 {
557 *GetTxControlAddr(GetNumber()) &= ~USBHS_UEP_T_RES_STALL;
558 }
559 else
560 {
561 *GetRxControlAddr(GetNumber()) &= ~USBHS_UEP_R_RES_STALL;
562 }
563 SetState(State::IDLE);
564 return ErrorCode::OK;
565}
566
567void CH32EndpointOtgHs::TransferComplete(size_t size)
568{
569 if (GetState() == State::BUSY && GetNumber() != EPNumber::EP0 &&
570 GetType() != Type::ISOCHRONOUS)
571 {
572 tog0_ = !tog0_;
573 }
574
575 if (GetDirection() == Direction::IN)
576 {
577 *GetTxControlAddr(GetNumber()) =
578 (*GetTxControlAddr(GetNumber()) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_NAK;
579
580 USBHSD->INT_FG = USBHS_UIF_ISO_ACT | USBHS_UIF_TRANSFER; // NOLINT
581
582 size = last_transfer_size_;
583
584 if (GetType() == Type::ISOCHRONOUS)
585 {
586 SetTxLen(GetNumber(), 0);
587 DisableTx(GetNumber());
588 }
589 }
590
591 if (GetDirection() == Direction::OUT &&
592 (USBHSD->INT_ST & USBHS_UIS_TOG_OK) != USBHS_UIS_TOG_OK) // NOLINT
593 {
594 return;
595 }
596
597 if (GetNumber() == EPNumber::EP0 && GetDirection() == Direction::OUT)
598 {
599 tog0_ = true;
600 tog1_ = false;
601 *GetRxControlAddr(GetNumber()) = USBHS_UEP_R_RES_ACK;
602 }
603
604 OnTransferCompleteCallback(true, size);
605}
606
607void CH32EndpointOtgHs::SwitchBuffer()
608{
609 if (GetDirection() == Direction::IN)
610 {
611 SetActiveBlock(!tog0_);
612 }
613 else
614 {
615 SetActiveBlock(tog0_);
616 }
617}
618
619#endif
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
EPNumber
端点号 / Endpoint number
Definition ep.hpp:39
LibXR 命名空间