Open FFBoard
Open source force feedback firmware
dcd_mm32f327x_otg.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2020 SE TEAM
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#include "tusb_option.h"
28
29#if CFG_TUD_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X )
30
31#include "reg_usb_otg_fs.h"
32#include "mm32_device.h"
33#include "hal_conf.h"
34#include "device/dcd.h"
35
36//--------------------------------------------------------------------+
37// MACRO TYPEDEF CONSTANT ENUM DECLARATION
38//--------------------------------------------------------------------+
39
40enum {
42 TOK_PID_IN = 0x9u,
44};
45
46typedef struct TU_ATTR_PACKED
47{
48 union {
49 uint32_t head;
50 struct {
51 union {
52 struct {
53 uint16_t : 2;
54 uint16_t tok_pid : 4;
55 uint16_t data : 1;
56 uint16_t own : 1;
57 uint16_t : 8;
58 };
59 struct {
60 uint16_t : 2;
62 uint16_t dts : 1;
63 uint16_t ninc : 1;
64 uint16_t keep : 1;
65 uint16_t : 10;
66 };
67 };
68 uint16_t bc : 10;
69 uint16_t : 6;
70 };
71 };
72 uint8_t *addr;
74
75TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" );
76
77typedef struct TU_ATTR_PACKED
78{
79 union {
80 uint32_t state;
81 struct {
82 uint32_t max_packet_size :11;
83 uint32_t : 5;
84 uint32_t odd : 1;
85 uint32_t :15;
86 };
87 };
91
92TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" );
93
94typedef struct
95{
96 union {
97 /* [#EP][OUT,IN][EVEN,ODD] */
98 buffer_descriptor_t bdt[16][2][2];
99 uint16_t bda[512];
100 };
102 endpoint_state_t endpoint[16][2];
103 endpoint_state_t endpoint_unified[16 * 2];
104 };
105 uint8_t setup_packet[8];
106 uint8_t addr;
108
109//--------------------------------------------------------------------+
110// INTERNAL OBJECT & FUNCTION DECLARATION
111//--------------------------------------------------------------------+
112// BDT(Buffer Descriptor Table) must be 256-byte aligned
113CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd;
114
115TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" );
116
117static void prepare_next_setup_packet(uint8_t rhport)
118{
119 const unsigned out_odd = _dcd.endpoint[0][0].odd;
120 const unsigned in_odd = _dcd.endpoint[0][1].odd;
121 if (_dcd.bdt[0][0][out_odd].own) {
122 TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd);
123 return;
124 }
125 _dcd.bdt[0][0][out_odd].data = 0;
126 _dcd.bdt[0][0][out_odd ^ 1].data = 1;
127 _dcd.bdt[0][1][in_odd].data = 1;
128 _dcd.bdt[0][1][in_odd ^ 1].data = 0;
130 _dcd.setup_packet, sizeof(_dcd.setup_packet));
131}
132
133static void process_stall(uint8_t rhport)
134{
135 if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) {
136 /* clear stall condition of the control pipe */
138 USB_OTG_FS->EP_CTL[0] &= ~USB_ENDPT_EPSTALL_MASK;
139 }
140}
141
142static void process_tokdne(uint8_t rhport)
143{
144 const unsigned s = USB_OTG_FS->STAT;
145 USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */
147 endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3];
148 unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0;
149
150 /* fetch pid before discarded by the next steps */
151 const unsigned pid = bd->tok_pid;
152 /* reset values for a next transfer */
153 bd->bdt_stall = 0;
154 bd->dts = 1;
155 bd->ninc = 0;
156 bd->keep = 0;
157 /* update the odd variable to prepare for the next transfer */
158 ep->odd = odd ^ 1;
159 if (pid == TOK_PID_SETUP) {
160 dcd_event_setup_received(rhport, bd->addr, true);
161 USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
162 return;
163 }
164 if (s >> 4) {
165 TU_LOG1("TKDNE %x\r\n", s);
166 }
167
168 const unsigned bc = bd->bc;
169 const unsigned remaining = ep->remaining - bc;
170 if (remaining && bc == ep->max_packet_size) {
171 /* continue the transferring consecutive data */
172 ep->remaining = remaining;
173 const int next_remaining = remaining - ep->max_packet_size;
174 if (next_remaining > 0) {
175 /* prepare to the after next transfer */
176 bd->addr += ep->max_packet_size * 2;
177 bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining;
178 __DSB();
179 bd->own = 1; /* the own bit must set after addr */
180 }
181 return;
182 }
183 const unsigned length = ep->length;
185 ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT),
186 length - remaining, XFER_RESULT_SUCCESS, true);
187 if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) {
188 /* After completion a ZLP of control transfer,
189 * it prepares for the next steup transfer. */
190 if (_dcd.addr) {
191 /* When the transfer was the SetAddress,
192 * the device address should be updated here. */
193 USB_OTG_FS->ADDR = _dcd.addr;
194 _dcd.addr = 0;
195 }
197 }
198}
199
200static void process_bus_reset(uint8_t rhport)
201{
202 USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK;
203 USB_OTG_FS->ADDR = 0;
204 USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK;
205
206 USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK;
207 for (unsigned i = 1; i < 16; ++i) {
208 USB_OTG_FS->EP_CTL[i] = 0;
209 }
210 buffer_descriptor_t *bd = _dcd.bdt[0][0];
211 for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) {
212 bd->head = 0;
213 }
214 const endpoint_state_t ep0 = {
215 .max_packet_size = CFG_TUD_ENDPOINT0_SIZE,
216 .odd = 0,
217 .length = 0,
218 .remaining = 0,
219 };
220 _dcd.endpoint[0][0] = ep0;
221 _dcd.endpoint[0][1] = ep0;
222 tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0]));
223 _dcd.addr = 0;
225 USB_OTG_FS->CTL &= ~USB_CTL_ODDRST_MASK;
227}
228
229static void process_bus_inactive(uint8_t rhport)
230{
231 (void) rhport;
232 const unsigned inten = USB_OTG_FS->INT_ENB;
233 USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK;
234 dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
235}
236
237static void process_bus_active(uint8_t rhport)
238{
239 (void) rhport;
240 const unsigned inten = USB_OTG_FS->INT_ENB;
241 USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK;
242 dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
243}
244
245/*------------------------------------------------------------------*/
246/* Device API
247 *------------------------------------------------------------------*/
248bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
249 (void) rhport;
250 (void) rh_init;
251
252 tu_memclr(&_dcd, sizeof(_dcd));
253 USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8);
254 USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16);
255 USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24);
256
257 dcd_connect(rhport);
258 NVIC_ClearPendingIRQ(USB_FS_IRQn);
259 return true;
260}
261#define USB_DEVICE_INTERRUPT_PRIORITY (3U)
262void dcd_int_enable(uint8_t rhport)
263{
264 uint8_t irqNumber;
265 irqNumber = USB_FS_IRQn;
266 (void) rhport;
267 USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK |
268 USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK;
269 NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
270 NVIC_EnableIRQ(USB_FS_IRQn);
271}
272
273void dcd_int_disable(uint8_t rhport)
274{
275 (void) rhport;
276 NVIC_DisableIRQ(USB_FS_IRQn);
277 USB_OTG_FS->INT_ENB = 0;
278}
279
280void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
281{
282 (void) rhport;
283 _dcd.addr = dev_addr & 0x7F;
284 /* Response with status first before changing device address */
285 dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
286}
287
288#ifdef __GNUC__ // caused by extra declaration of SystemCoreClock in freeRTOSConfig.h
289#pragma GCC diagnostic push
290#pragma GCC diagnostic ignored "-Wredundant-decls"
291#endif
292
293extern u32 SystemCoreClock;
294
295#ifdef __GNUC__
296#pragma GCC diagnostic pop
297#endif
298
299void dcd_remote_wakeup(uint8_t rhport)
300{
301 (void) rhport;
302 unsigned cnt = SystemCoreClock / 100;
303 USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK;
304 while (cnt--) __NOP();
305 USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK;
306}
307
308void dcd_connect(uint8_t rhport)
309{
310 (void) rhport;
311 USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK;
312}
313
314void dcd_disconnect(uint8_t rhport)
315{
316 (void) rhport;
317 USB_OTG_FS->CTL = 0;
318}
319
320void dcd_sof_enable(uint8_t rhport, bool en)
321{
322 (void) rhport;
323 (void) en;
324
325 // TODO implement later
326}
327
328//--------------------------------------------------------------------+
329// Endpoint API
330//--------------------------------------------------------------------+
331bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
332{
333 (void) rhport;
334
335 const unsigned ep_addr = ep_desc->bEndpointAddress;
336 const unsigned epn = ep_addr & 0xFu;
337 const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
338 const unsigned xfer = ep_desc->bmAttributes.xfer;
339 endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
340 const unsigned odd = ep->odd;
341 buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0];
342
343 /* No support for control transfer */
344 TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL));
345
347 unsigned val = USB_ENDPT_EPCTLDIS_MASK;
348 val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0;
349 val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
350 USB_OTG_FS->EP_CTL[epn] |= val;
351
353 bd[odd].dts = 1;
354 bd[odd].data = 0;
355 bd[odd ^ 1].dts = 1;
356 bd[odd ^ 1].data = 1;
357 }
358
359 return true;
360}
361
362void dcd_edpt_close_all (uint8_t rhport)
363{
364 (void) rhport;
365 // TODO implement dcd_edpt_close_all()
366}
367
368void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
369{
370 (void) rhport;
371
372 const unsigned epn = ep_addr & 0xFu;
373 const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
374 endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
375 buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0];
376 const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
377 USB_OTG_FS->EP_CTL[epn] &= ~msk;
378 ep->max_packet_size = 0;
379 ep->length = 0;
380 ep->remaining = 0;
381 bd->head = 0;
382}
383
384bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
385{
386 (void) rhport;
387 NVIC_DisableIRQ(USB_FS_IRQn);
388 const unsigned epn = ep_addr & 0xFu;
389 const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
390 endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
391 buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd];
392
393 if (bd->own) {
394 TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head);
395 return false; /* The last transfer has not completed */
396 }
397 ep->length = total_bytes;
399
400 const unsigned mps = ep->max_packet_size;
401 if (total_bytes > mps) {
402 buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1;
403 /* When total_bytes is greater than the max packet size,
404 * it prepares to the next transfer to avoid NAK in advance. */
405 next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps;
406 next->addr = buffer + mps;
407 next->own = 1;
408 }
409 bd->bc = total_bytes >= mps ? mps: total_bytes;
410 bd->addr = buffer;
411 __DSB();
412 bd->own = 1; /* the own bit must set after addr */
413 NVIC_EnableIRQ(USB_FS_IRQn);
414 return true;
415}
416
417void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
418{
419 (void) rhport;
420 const unsigned epn = ep_addr & 0xFu;
421 if (0 == epn) {
422 USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK;
423 } else {
424 const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
425 buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
426 bd[0].bdt_stall = 1;
427 bd[1].bdt_stall = 1;
428 }
429}
430
431void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
432{
433 (void) rhport;
434 const unsigned epn = ep_addr & 0xFu;
435 const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
436 const unsigned odd = _dcd.endpoint[epn][dir].odd;
437 buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
438
439 bd[odd ^ 1].own = 0;
440 bd[odd ^ 1].data = 1;
441 bd[odd ^ 1].bdt_stall = 0;
442 bd[odd].own = 0;
443 bd[odd].data = 0;
444 bd[odd].bdt_stall = 0;
445}
446
447//--------------------------------------------------------------------+
448// ISR
449//--------------------------------------------------------------------+
450void dcd_int_handler(uint8_t rhport)
451{
452 (void) rhport;
453
454 uint32_t is = USB_OTG_FS->INT_STAT;
455 uint32_t msk = USB_OTG_FS->INT_ENB;
456 USB_OTG_FS->INT_STAT = is & ~msk;
457 is &= msk;
458 if (is & USB_ISTAT_ERROR_MASK) {
459 /* TODO: */
460 uint32_t es = USB_OTG_FS->ERR_STAT;
461 USB_OTG_FS->ERR_STAT = es;
462 USB_OTG_FS->INT_STAT = is; /* discard any pending events */
463 return;
464 }
465
466 if (is & USB_ISTAT_USBRST_MASK) {
467 USB_OTG_FS->INT_STAT = is; /* discard any pending events */
468 process_bus_reset(rhport);
469 return;
470 }
471 if (is & USB_ISTAT_SLEEP_MASK) {
472 USB_OTG_FS->INT_STAT = USB_ISTAT_SLEEP_MASK;
473 process_bus_inactive(rhport);
474 return;
475 }
476 if (is & USB_ISTAT_RESUME_MASK) {
477 USB_OTG_FS->INT_STAT = USB_ISTAT_RESUME_MASK;
478 process_bus_active(rhport);
479 return;
480 }
481 if (is & USB_ISTAT_SOFTOK_MASK) {
482 USB_OTG_FS->INT_STAT = USB_ISTAT_SOFTOK_MASK;
483 dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
484 return;
485 }
486 if (is & USB_ISTAT_STALL_MASK) {
487 USB_OTG_FS->INT_STAT = USB_ISTAT_STALL_MASK;
488 process_stall(rhport);
489 return;
490 }
491 if (is & USB_ISTAT_TOKDNE_MASK) {
492 process_tokdne(rhport);
493 return;
494 }
495}
496
497#endif
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
Definition: dcd.h:196
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
Definition: dcd.h:222
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
Definition: dcd.h:213
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
Definition: dcd.h:204
static struct @149 _dcd
u32 SystemCoreClock
@ TOK_PID_SETUP
@ TOK_PID_IN
@ TOK_PID_OUT
static void process_bus_reset(uint8_t rhport)
struct TU_ATTR_PACKED endpoint_state_t
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
void dcd_int_handler(uint8_t rhport)
void dcd_disconnect(uint8_t rhport)
static void process_tokdne(uint8_t rhport)
void dcd_edpt_close_all(uint8_t rhport)
void dcd_int_disable(uint8_t rhport)
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
TU_VERIFY_STATIC(sizeof(buffer_descriptor_t)==8, "size is not correct")
static void process_stall(uint8_t rhport)
void dcd_connect(uint8_t rhport)
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512)
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
struct TU_ATTR_PACKED buffer_descriptor_t
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
static void process_bus_active(uint8_t rhport)
void dcd_int_enable(uint8_t rhport)
void dcd_remote_wakeup(uint8_t rhport)
static void process_bus_inactive(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
xfer_td_t xfer[EP_CBI_COUNT+1][2]
Definition: dcd_nrf5x.c:119
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
static void prepare_next_setup_packet(uint8_t rhport)
Definition: dcd_pic.c:312
uint32_t u32
uint8_t const * buffer
Definition: midi_device.h:100
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
__IO uint16_t tok_pid
Definition: dcd_ci_fs.c:60
uint8_t * addr
Definition: dcd_ci_fs.c:78
uint16_t ninc
Definition: dcd_ci_fs.c:69
uint16_t bdt_stall
Definition: dcd_ci_fs.c:67
uint16_t dts
Definition: dcd_ci_fs.c:68
__IO uint16_t bc
Definition: dcd_ci_fs.c:74
uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]
Definition: ncm.h:147
uint32_t max_packet_size
Definition: dcd_ci_fs.c:88
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint16_t length
Definition: dcd_ci_fs.c:94
volatile uint16_t
Definition: hcd_rusb2.c:58
uint32_t odd
Definition: dcd_ci_fs.c:90
uint16_t keep
Definition: dcd_ci_fs.c:70
uint16_t remaining
Definition: dcd_ci_fs.c:95
__IO uint16_t own
Definition: dcd_ci_fs.c:62
uint8_t bEndpointAddress
Definition: video.h:306
uint32_t head
Definition: dcd_ci_fs.c:55
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ TUSB_DIR_OUT
Definition: tusb_types.h:66
@ TUSB_DIR_IN_MASK
Definition: tusb_types.h:69
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
Definition: tusb_types.h:515
@ TUSB_XFER_CONTROL
Definition: tusb_types.h:59
@ TUSB_XFER_ISOCHRONOUS
Definition: tusb_types.h:60
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)
Definition: tusb_types.h:511