Open FFBoard
Open source force feedback firmware
dcd_ft9xx.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright 2021 Bridgetek Pte Ltd
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/*
28 * Contains code adapted from Bridgetek Pte Ltd via license terms stated
29 * in https://brtchip.com/BRTSourceCodeLicenseAgreement
30 */
31
32#include "tusb_option.h"
33
34#if CFG_TUD_ENABLED && \
35 (CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X)
36
37#include <stdint.h>
38#include <ft900.h>
39#include <registers/ft900_registers.h>
40
41#define USBD_USE_STREAMS
42
43#include "device/dcd.h"
44
45//--------------------------------------------------------------------+
46// MACRO TYPEDEF CONSTANT ENUM DECLARATION
47//--------------------------------------------------------------------+
48
49// Board code will determine the state of VBUS from USB host.
50extern int8_t board_ft9xx_vbus(void);
51extern int board_uart_write(void const *buf, int len);
52
53// Static array to store an incoming SETUP request for processing by tinyusb.
54CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN
55static uint8_t _ft9xx_setup_packet[8];
56
58{
59 volatile uint8_t ready; // OUT Transfer has been received and waiting for transfer.
60 volatile uint8_t valid; // Transfer is pending and total_size, remain_size, and buff_ptr are valid.
61
62 int16_t total_size; // Total transfer size in bytes for this transfer.
63 int16_t remain_size; // Total remaining in transfer.
64 uint8_t *buff_ptr; // Pointer to buffer to transmit from or receive to.
65
66 uint8_t type; // Endpoint type. Of type USBD_ENDPOINT_TYPE from endpoint descriptor.
67 uint8_t dir; // Endpoint direction. TUSB_DIR_OUT or TUSB_DIR_IN. For control endpoint this is the current direction.
68 uint16_t buff_size; // Actual size of buffer RAM used by endpoint.
69 uint16_t size; // Max packet size for endpoint from endpoint descriptor.
70};
71// Endpoint description array for each endpoint.
72static struct ft9xx_xfer_state ep_xfer[USBD_MAX_ENDPOINT_COUNT];
73// USB speed.
75
76// Interrupt handlers.
77void _ft9xx_usbd_ISR(void); // Interrupt handler for USB device.
78void ft9xx_usbd_pm_ISR(void); // Interrupt handler for USB device for power management (called by board).
79
80// Internal functions forward declarations.
81static uint16_t _ft9xx_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes);
82static uint16_t _ft9xx_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes);
83static void _ft9xx_reset_edpts(void);
84static inline void _ft9xx_phy_enable(bool en);
85static void _ft9xx_usb_speed(void);
86static void _dcd_ft9xx_attach(void);
87static void _dcd_ft9xx_detach(void) __attribute__((unused));
88static uint16_t _ft9xx_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length);
89static uint16_t _ft9xx_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length);
90
91// Internal functions.
92
93// Manage an OUT transfer from the host.
94// This can be up-to the maximum packet size of the endpoint.
95// Continuation of a transfer beyond the maximum packet size is performed
96// by the interrupt handler.
97static uint16_t _ft9xx_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes)
98{
99 //Note: this is called from only the interrupt handler when an OUT transfer is called.
100 uint16_t ep_size = ep_xfer[ep_number].size;
101 (void)ep_size;
102 if (xfer_bytes > ep_size)
103 {
104 xfer_bytes = ep_size;
105 }
106
107 // Wait until the endpoint has finished - it should be complete!
108 //while (!(USBD_EP_SR_REG(ep_number) & MASK_USBD_EPxSR_OPRDY))
109 //;
110
111 // Send the first packet of max packet size
112 xfer_bytes = _ft9xx_dusb_out(ep_number, (uint8_t *)buffer, xfer_bytes);
113 if (ep_number == USBD_EP_0)
114 {
115 // Set flags to indicate data ready.
116 USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_OPRDY);
117 }
118 else
119 {
120 USBD_EP_SR_REG(ep_number) = (MASK_USBD_EPxSR_OPRDY);
121 }
122
123 return xfer_bytes;
124}
125
126// Manage an IN transfer to the host.
127// This can be up-to the maximum packet size of the endpoint.
128// Continuation of a transfer beyond the maximum packet size is performed
129// by the interrupt handler.
130static uint16_t _ft9xx_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes)
131{
132 //Note: this may be called from the interrupt handler or from normal code.
133 uint8_t end = 0;
134 uint16_t ep_size = ep_xfer[ep_number].size;
135 (void)ep_size;
136
137 if ((xfer_bytes == 0) || (xfer_bytes < ep_size))
138 {
139 end = 1;
140 }
141 else
142 {
143 xfer_bytes = ep_size;
144 }
145
146 if (ep_number == USBD_EP_0)
147 {
148 // An IN direction SETUP can be interrupted by an OUT packet.
149 // This will result in a STALL generated by the silicon.
150 while (USBD_EP_SR_REG(USBD_EP_0) & MASK_USBD_EP0SR_STALL)
151 {
152 // Clear the STALL and finish the transaction.
153 USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_STALL);
154 }
155 }
156 else
157 {
158 // If there is data to transmit then wait until the IN buffer
159 // for the endpoint is empty.
160 // This does not apply to interrupt endpoints.
161 if (ep_xfer[ep_number].type != TUSB_XFER_INTERRUPT)
162 {
163 uint8_t sr_reg;
164 do
165 {
166 sr_reg = USBD_EP_SR_REG(ep_number);
167 } while (sr_reg & MASK_USBD_EPxSR_INPRDY);
168 }
169 }
170
171 // Do not send a ZLP for interrupt endpoints.
172 if ((ep_xfer[ep_number].type != TUSB_XFER_INTERRUPT) || (xfer_bytes > 0))
173 {
174 xfer_bytes = _ft9xx_dusb_in(ep_number, (uint8_t *)buffer, xfer_bytes);
175 }
176
177 if (ep_number == USBD_EP_0)
178 {
179 if (end)
180 {
181 // Set flags to indicate data ready and transfer complete.
182 USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_INPRDY | MASK_USBD_EP0SR_DATAEND;
183 }
184 else
185 {
186 // Set flags to indicate data ready.
187 USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_INPRDY);
188 }
189 }
190 else
191 {
192 // Set flags to indicate data ready.
193 USBD_EP_SR_REG(ep_number) = (MASK_USBD_EPxSR_INPRDY);
194 }
195
196 return xfer_bytes;
197}
198
199// Reset all non-control endpoints to a default state.
200// Control endpoint is always enabled and ready. All others disabled.
201static void _ft9xx_reset_edpts(void)
202{
203 // Disable all endpoints and remove configuration values.
204 for (int i = 1; i < USBD_MAX_ENDPOINT_COUNT; i++)
205 {
206 // Clear settings.
207 tu_memclr(&ep_xfer[i], sizeof(struct ft9xx_xfer_state));
208 // Disable hardware.
209 USBD_EP_CR_REG(i) = 0;
210 }
211
212 // Enable interrupts from USB device control.
213 USBD_REG(cmie) = MASK_USBD_CMIE_ALL;
214}
215
216// Enable or disable the USB PHY.
217static inline void _ft9xx_phy_enable(bool en)
218{
219 if (en)
220 SYS->PMCFG_L |= MASK_SYS_PMCFG_DEV_PHY_EN;
221 else
222 SYS->PMCFG_L &= ~MASK_SYS_PMCFG_DEV_PHY_EN;
223}
224
225// Safely connect to the USB.
226static void _dcd_ft9xx_attach(void)
227{
228 uint8_t reg;
229
230 CRITICAL_SECTION_BEGIN
231 // Disable device responses.
232 USBD_REG(faddr) = 0;
233
234 // Reset USB Device.
235 SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RESET_ALL;
236 // Disable device connect/disconnect/host reset detection.
237 SYS->PMCFG_H = MASK_SYS_PMCFG_DEV_DIS_DEV;
238 SYS->PMCFG_H = MASK_SYS_PMCFG_DEV_CONN_DEV;
239 SYS->PMCFG_L = SYS->PMCFG_L & (~MASK_SYS_PMCFG_DEV_DETECT_EN);
240
241 // Enable Chip USB device clock/PM configuration.
242 sys_enable(sys_device_usb_device);
243 CRITICAL_SECTION_END;
244
245 // Wait a short time to get started.
246 delayms(1);
247
248 CRITICAL_SECTION_BEGIN
249 // Turn off the device enable bit.
250#if BOARD_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED
251 USBD_REG(fctrl) = 0;
252#else // BOARD_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED
253 //Set the full speed only bit if required.
254 USBD_REG(fctrl) = MASK_USBD_FCTRL_MODE_FS_ONLY;
255#endif // BOARD_TUD_MAX_SPEED
256
257 // Clear first reset and suspend interrupts.
258 do
259 {
260 reg = USBD_REG(cmif);
261 USBD_REG(cmif) = reg;
262 } while (reg);
263 // Clear any endpoint interrupts.
264 reg = USBD_REG(epif);
265 USBD_REG(epif) = reg;
266
267 // Disable all interrupts from USB device control before attaching interrupt.
268 USBD_REG(cmie) = 0;
269 CRITICAL_SECTION_END;
270
271 // Enable device connect/disconnect/host reset detection.
272 // Set device detect and remote wakeup enable interrupt enables.
273 SYS->PMCFG_L = SYS->PMCFG_L | MASK_SYS_PMCFG_DEV_DETECT_EN;
274
275#if defined(__FT930__)
276 // Setup VBUS detect
277 SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_USB_VBUS_EN;
278#endif
279}
280
281// Gracefully disconnect from the USB.
282static void _dcd_ft9xx_detach(void)
283{
284 // Disable device connect/disconnect/host reset detection.
285 SYS->PMCFG_L = SYS->PMCFG_L & (~MASK_SYS_PMCFG_DEV_DETECT_EN);
286
287#if defined(__FT930__)
288 // Disable VBUS detection.
289 SYS->MSC0CFG = SYS->MSC0CFG & (~MASK_SYS_MSC0CFG_USB_VBUS_EN);
290#endif
291 CRITICAL_SECTION_BEGIN
292 // Disable interrupts from USB.
293 USBD_REG(epie) = 0;
294 USBD_REG(cmie) = 0;
295 // Turn off the device enable bit.
296 USBD_REG(fctrl) = 0;
297 CRITICAL_SECTION_END;
298
299 delayms(1);
300
301 // Disable USB PHY
302 dcd_disconnect(BOARD_TUD_RHPORT);
303 delayms(1);
304
305 // Disable Chip USB device clock/PM configuration.
306 sys_disable(sys_device_usb_device);
307
308 // Reset USB Device... Needed for Back voltage D+ to be <400mV
309 SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RESET_ALL;
310
311 delayms(1);
312 // Set device detect and remote wakeup enable interrupt enables.
313 SYS->PMCFG_L = SYS->PMCFG_L | MASK_SYS_PMCFG_DEV_DETECT_EN;
314
315#if defined(__FT930__)
316 // Setup VBUS detect
317 SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_USB_VBUS_EN;
318#endif
319}
320
321// Determine the speed of the USB to which we are connected.
322// Set the speed of the PHY accordingly.
323// High speed can be disabled through CFG_TUSB_RHPORT0_MODE or CFG_TUD_MAX_SPEED settings.
324static void _ft9xx_usb_speed(void)
325{
326 uint8_t fctrl_val;
327
328 // If USB device function is already enabled then disable it.
329 if (USBD_REG(fctrl) & MASK_USBD_FCTRL_USB_DEV_EN) {
330 USBD_REG(fctrl) = (USBD_REG(fctrl) & (~MASK_USBD_FCTRL_USB_DEV_EN));
331 delayus(200);
332 }
333
334#if BOARD_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED
335
336 /* Detect high or full speed */
337 fctrl_val = MASK_USBD_FCTRL_USB_DEV_EN;
338#if defined(__FT900__)
339 if (!sys_check_ft900_revB())//if 90x series is rev C
340 {
341 fctrl_val |= MASK_USBD_FCTRL_IMP_PERF;
342 }
343#endif
344 USBD_REG(fctrl) = fctrl_val;
345
346#if defined(__FT930__)
347 delayus(200);
348
349 _speed = (SYS->MSC0CFG & MASK_SYS_MSC0CFG_HIGH_SPED_MODE) ?
351#else /* __FT930__ */
352 /* Detection by SOF */
353 while (!(USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ));
354 USBD_REG(cmif) = MASK_USBD_CMIF_SOFIRQ;
355 delayus(125 + 5);
356 _speed = (USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ) ?
358 dcd_event_bus_reset(BOARD_TUD_RHPORT, _speed, true);
359
360#endif /* !__FT930__ */
361
362#else // BOARD_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED
363
364 /* User force set to full speed */
366 fctrl_val =
367 MASK_USBD_FCTRL_USB_DEV_EN | MASK_USBD_FCTRL_MODE_FS_ONLY;
368#if defined(__FT900__)
369 if (!sys_check_ft900_revB())//if 90x series is rev C
370 {
371 fctrl_val |= MASK_USBD_FCTRL_IMP_PERF;
372 }
373#endif
374 USBD_REG(fctrl) = fctrl_val;
375 dcd_event_bus_reset(BOARD_TUD_RHPORT, _speed, true);
376 return;
377
378#endif // BOARD_TUD_MAX_SPEED
379}
380
381// Send a buffer to the USB IN FIFO.
382// When the macro USBD_USE_STREAMS is defined this will stream a buffer of data
383// to the FIFO using the most efficient MCU streamout combination.
384// If streaming is disabled then it will send each byte of the buffer in turn
385// to the FIFO. The is no reason to not stream.
386// The total number of bytes sent to the FIFO is returned.
387static uint16_t _ft9xx_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length)
388{
389 uint16_t bytes_read = 0;
390 uint16_t buff_size = length;
391
392#ifdef USBD_USE_STREAMS
393 volatile uint8_t *data_reg;
394
395 data_reg = (volatile uint8_t *)&(USBD->ep[ep_number].epxfifo);
396 if (buff_size)
397 {
398 if (((uint32_t)buffer) % 4 == 0)
399 {
400 uint16_t aligned = buff_size & (~3);
401 uint16_t left = buff_size & 3;
402
403 if (aligned)
404 {
405 __asm__ volatile("streamout.l %0,%1,%2"
406 :
407 : "r"(data_reg), "r"(buffer), "r"(aligned));
408 buffer += aligned;
409 }
410 if (left)
411 {
412 __asm__ volatile("streamout.b %0,%1,%2"
413 :
414 : "r"(data_reg), "r"(buffer), "r"(left));
415 }
416 }
417 else
418 {
419 __asm__ volatile("streamout.b %0,%1,%2"
420 :
421 : "r"(data_reg), "r"(buffer), "r"(buff_size));
422 }
423 bytes_read = buff_size;
424 }
425#else // USBD_USE_STREAMS
426
427 bytes_read = buff_size;
428 while (buff_size--)
429 {
430 USBD_EP_FIFO_REG(ep_number) = *buffer++;
431 };
432
433#endif // USBD_USE_STREAMS
434
435 return bytes_read;
436}
437
438// Receive a buffer from the USB OUT FIFO.
439// When the macro USBD_USE_STREAMS is defined this will stream from the FIFO
440// to a buffer of data using the most efficient MCU streamin combination.
441// If streaming is disabled then it will receive each byte from the FIFO in turn
442// to the buffer. The is no reason to not stream.
443// The total number of bytes received from the FIFO is returned.
444static uint16_t _ft9xx_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length)
445{
446#ifdef USBD_USE_STREAMS
447 volatile uint8_t *data_reg;
448#endif // USBD_USE_STREAMS
449 uint16_t bytes_read = 0;
450 uint16_t buff_size = length;
451
452 if (length > 0)
453 {
454 if (ep_number == USBD_EP_0)
455 {
456 buff_size = USBD_EP_CNT_REG(USBD_EP_0);
457 }
458 else
459 {
460 if (USBD_EP_SR_REG(ep_number) & (MASK_USBD_EPxSR_OPRDY))
461 {
462 buff_size = USBD_EP_CNT_REG(ep_number);
463 }
464 }
465 }
466
467 // Only read as many bytes as we have space for.
468 if (buff_size > length)
469 buff_size = length;
470
471#ifdef USBD_USE_STREAMS
472 data_reg = (volatile uint8_t *)&(USBD->ep[ep_number].epxfifo);
473 if (buff_size)
474 {
475 if ((uint32_t)buffer % 4 == 0)
476 {
477 uint16_t aligned = buff_size & (~3);
478 uint16_t left = buff_size & 3;
479
480 if (aligned)
481 {
482 __asm__ volatile("streamin.l %0,%1,%2"
483 :
484 : "r"(buffer), "r"(data_reg), "r"(aligned));
485 buffer += aligned;
486 }
487 if (left)
488 {
489 __asm__ volatile("streamin.b %0,%1,%2"
490 :
491 : "r"(buffer), "r"(data_reg), "r"(left));
492 }
493 }
494 else
495 {
496 __asm__ volatile("streamin.b %0,%1,%2"
497 :
498 : "r"(buffer), "r"(data_reg), "r"(buff_size));
499 }
500 bytes_read = buff_size;
501 }
502#else // USBD_USE_STREAMS
503
504 bytes_read = buff_size;
505 while (buff_size--)
506 {
507 *buffer++ = USBD_EP_FIFO_REG(ep_number);
508 }
509
510#endif // USBD_USE_STREAMS
511
512 return bytes_read;
513}
514
515/*------------------------------------------------------------------*/
516/* Device API
517 *------------------------------------------------------------------*/
518
519// Initialize controller to device mode
520bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
521 (void) rh_init;
522 TU_LOG2("FT9xx initialisation\r\n");
523
525
526 interrupt_attach(interrupt_usb_device, (int8_t)interrupt_usb_device, _ft9xx_usbd_ISR);
527
528 dcd_connect(rhport);
529 return true;
530}
531
532// Enable device interrupt
533void dcd_int_enable(uint8_t rhport)
534{
535 (void)rhport;
536 TU_LOG3("FT9xx int enable\r\n");
537
538 // Peripheral devices interrupt enable.
539 interrupt_enable_globally();
540}
541
542// Disable device interrupt
543void dcd_int_disable(uint8_t rhport)
544{
545 (void)rhport;
546 TU_LOG3("FT9xx int disable\r\n");
547
548 // Peripheral devices interrupt disable.
549 interrupt_disable_globally();
550}
551
552// Receive Set Address request, mcu port must also include status IN response
553void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
554{
555 (void)rhport;
556 (void)dev_addr;
557
558 // Respond with status. There is no checking that the address is in range.
559 dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0);
560
561 // Set the update bit for the address register.
562 dev_addr |= 0x80;
563
564 // Modify the address register within a critical section.
565 CRITICAL_SECTION_BEGIN
566 {
567 USBD_REG(faddr) = dev_addr;
568 }
569 CRITICAL_SECTION_END;
570}
571
572// Invoked when a control transfer's status stage is complete.
573// May help DCD to prepare for next control transfer, this API is optional.
574#if 0 // never called
576{
577 (void) rhport;
578
581 {
583 {
584 }
586 {
587 }
588 }
589}
590#endif // 0
591
592// Wake up host
593void dcd_remote_wakeup(uint8_t rhport)
594{
595 (void)rhport;
596
597 SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RMWAKEUP;
598
599 // At least 2 ms of delay needed for RESUME Data K state.
600 delayms(2);
601
602 SYS->MSC0CFG &= ~MASK_SYS_MSC0CFG_DEV_RMWAKEUP;
603
604 // Enable USB PHY and determine current bus speed.
605 dcd_connect(rhport);
606}
607
608// Connect by enabling internal pull-up resistor on D+/D-
609void dcd_connect(uint8_t rhport)
610{
611 (void)rhport;
612 TU_LOG2("FT9xx connect\r\n");
613
614 CRITICAL_SECTION_BEGIN
615 // Is device connected?
616 if (board_ft9xx_vbus())
617 {
618 // Clear/disable address register.
619 USBD_REG(faddr) = 0;
620 _ft9xx_phy_enable(true);
621
622 // Determine bus speed and signal speed to tusb.
624 }
625
626 // Setup the control endpoint only.
627#if CFG_TUD_ENDPOINT0_SIZE == 64
628 USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_64 << BIT_USBD_EP0_MAX_SIZE);
629#elif CFG_TUD_ENDPOINT0_SIZE == 32
630 USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_32 << BIT_USBD_EP0_MAX_SIZE);
631#elif CFG_TUD_ENDPOINT0_SIZE == 16
632 USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_16 << BIT_USBD_EP0_MAX_SIZE);
633#elif CFG_TUD_ENDPOINT0_SIZE == 8
634 USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_8 << BIT_USBD_EP0_MAX_SIZE);
635#else
636#error "CFG_TUD_ENDPOINT0_SIZE must be defined with a value of 8, 16, 32 or 64."
637#endif
638 CRITICAL_SECTION_END;
639
640 // Configure the control endpoint.
641 ep_xfer[USBD_EP_0].size = CFG_TUD_ENDPOINT0_SIZE;
642 ep_xfer[USBD_EP_0].type = TUSB_XFER_CONTROL;
643
644 // Enable interrupts on EP0.
645 USBD_REG(epie) = (MASK_USBD_EPIE_EP0IE);
646
647 // Restore default endpoint state.
649}
650
651// Disconnect by disabling internal pull-up resistor on D+/D-
652void dcd_disconnect(uint8_t rhport)
653{
654 (void)rhport;
655 TU_LOG2("FT9xx disconnect\r\n");
656
657 // Disable the USB PHY.
658 _ft9xx_phy_enable(false);
659}
660
661void dcd_sof_enable(uint8_t rhport, bool en)
662{
663 (void) rhport;
664 (void) en;
665
666 // TODO implement later
667}
668
669//--------------------------------------------------------------------+
670// Endpoint API
671//--------------------------------------------------------------------+
672
673// Configure endpoint's registers according to descriptor
674bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
675{
676 (void)rhport;
677 uint8_t const ep_number = tu_edpt_number(ep_desc->bEndpointAddress);
678 uint8_t const ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress);
679 uint8_t const ep_type = ep_desc->bmAttributes.xfer;
680 uint16_t const ep_size = tu_edpt_packet_size(ep_desc); // Mask size per packet, bits 10..0.
681 uint16_t ep_buff_size;
682 uint8_t ep_reg_size = USBD_EP_MAX_SIZE_8;
683 uint8_t ep_reg_data = 0;
684 int16_t total_ram;
685
686 TU_LOG2("FT9xx endpoint open %d %c\r\n", ep_number, ep_dir?'I':'O');
687
688 // Check that the requested endpoint number is allowable.
689 if (ep_number >= USBD_MAX_ENDPOINT_COUNT)
690 {
691 TU_LOG1("FT9xx endpoint not valid: requested %d max %d\r\n", ep_number, USBD_MAX_ENDPOINT_COUNT);
692 return false;
693 }
694
695 // Calculate the physical size of the endpoint as a power of 2. This may be more than
696 // the requested size.
697 while (ep_size > (8 * (1 << ep_reg_size)))
698 {
699 ep_reg_size++;
700 }
701 if (ep_reg_size > USBD_EP_MAX_SIZE_1024)
702 {
703 TU_LOG1("FT9xx endpoint size not valid: requested %d max 1024\r\n", ep_size);
704 return false;
705 }
706 // Calculate actual amount of buffer RAM used by this endpoint. This may be more than the
707 // requested size.
708 ep_buff_size = 8 << ep_reg_size;
709
710 if (ep_number > 0)
711 {
712 // Set EP cmd parameters...
713 ep_reg_data |= (ep_reg_size << BIT_USBD_EP_MAX_SIZE);
714
715 if (ep_xfer[ep_number].type != USBD_EP_TYPE_DISABLED)
716 {
717 // This could be because an endpoint has been assigned with the same number.
718 // On FT9xx, IN and OUT endpoints may not have the same number. e.g. There
719 // cannot been an 0x81 and 0x01 endpoint.
720 TU_LOG1("FT9xx endpoint %d already assigned\r\n", ep_number);
721 return false;
722 }
723
724 // Check that there is enough buffer RAM to allocate to this new endpoint.
725 // Available buffer RAM depends on the device revision.
726 // The IN and OUT buffer RAM should be the same size.
727 if (ep_dir == USBD_DIR_IN)
728 total_ram = USBD_RAMTOTAL_IN;
729 else
730 total_ram = USBD_RAMTOTAL_OUT;
731 // Work out how much has been allocated to existing endpoints.
732 // The total RAM allocated should always be a positive number as this
733 // algorithm should not let it go below zero.
734 for (int i = 1; i < USBD_MAX_ENDPOINT_COUNT; i++)
735 {
736 if (ep_xfer[i].type != USBD_EP_TYPE_DISABLED)
737 {
738 if (ep_xfer[i].dir == ep_dir)
739 {
740 total_ram -= ep_xfer[i].buff_size;
741 }
742 }
743 }
744
745 if (sys_check_ft900_revB())
746 {
747 // The control endpoint is taken into account as well on RevB silicon.
748 total_ram -= ep_xfer[0].buff_size;
749 }
750
751 // Make sure we have enough space. The corner case is having zero bytes
752 // free which means that total_ram must be signed as zero bytes free is
753 // allowable.
754 if (total_ram < ep_buff_size)
755 {
756 TU_LOG1("FT9xx insufficient buffer RAM for endpoint %d\r\n", ep_number);
757 return false;
758 }
759
760 // Set the type of this endpoint in the control register.
761 if (ep_type == TUSB_XFER_BULK)
762 ep_reg_data |= (USBD_EP_DIS_BULK << BIT_USBD_EP_CONTROL_DIS);
763 else if (ep_type == TUSB_XFER_INTERRUPT)
764 ep_reg_data |= (USBD_EP_DIS_INT << BIT_USBD_EP_CONTROL_DIS);
765 else if (ep_type == TUSB_XFER_ISOCHRONOUS)
766 ep_reg_data |= (USBD_EP_DIS_ISO << BIT_USBD_EP_CONTROL_DIS);
767 // Set the direction of this endpoint in the control register.
768 if (ep_dir == USBD_DIR_IN)
769 ep_reg_data |= MASK_USBD_EPxCR_DIR;
770 // Do not perform double buffering.
771 //if (<double buffering flag> != USBD_DB_OFF)
772 //ep_reg_data |= MASK_USBD_EPxCR_DB;
773 // Set the control register for this endpoint.
774 USBD_EP_CR_REG(ep_number) = ep_reg_data;
775 TU_LOG2("FT9xx endpoint setting %x\r\n", ep_reg_data);
776 }
777 else
778 {
779 // Set the control register for endpoint zero.
780 USBD_EP_CR_REG(USBD_EP_0) = (ep_reg_size << BIT_USBD_EP0_MAX_SIZE);
781 }
782
783 CRITICAL_SECTION_BEGIN
784 // Store the endpoint characteristics for later reference.
785 ep_xfer[ep_number].dir = ep_dir;
786 ep_xfer[ep_number].type = ep_type;
787 ep_xfer[ep_number].size = ep_size;
788 ep_xfer[ep_number].buff_size = ep_buff_size;
789
790 // Clear register transaction continuation and signalling state.
791 ep_xfer[ep_number].ready = 0;
792 ep_xfer[ep_number].valid = 0;
793 ep_xfer[ep_number].buff_ptr = NULL;
794 ep_xfer[ep_number].total_size = 0;
795 ep_xfer[ep_number].remain_size = 0;
796 CRITICAL_SECTION_END
797
798 return true;
799}
800
801// Close all endpoints.
802void dcd_edpt_close_all(uint8_t rhport)
803{
804 (void)rhport;
805 // Reset the endpoint configurations.
807}
808
809// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
810bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
811{
812 (void)rhport;
813 uint8_t ep_number = tu_edpt_number(ep_addr);
814 uint8_t ep_dir = tu_edpt_dir(ep_addr);
815 uint16_t xfer_bytes;
816 bool status = false;
817
818 // We will attempt to transfer the buffer. If it is less than or equal to the endpoint
819 // maximum packet size then the whole buffer will be transferred. If it is larger then
820 // the interrupt handler will transfer the remainder.
821 // ep_xfer is used to tell the interrupt handler what to do.
822 // ep_xfer can be used at interrupt level to continue transfers.
823 CRITICAL_SECTION_BEGIN
824
825 // Transfer currently in progress.
826 if (ep_xfer[ep_number].valid == 0)
827 {
828 ep_xfer[ep_number].total_size = total_bytes;
829 ep_xfer[ep_number].remain_size = total_bytes;
830 ep_xfer[ep_number].buff_ptr = buffer;
831
832 if (ep_number == USBD_EP_0)
833 {
834 ep_xfer[USBD_EP_0].dir = ep_dir;
835 }
836 else
837 {
838 // Enable the interrupt for this endpoint allowing the interrupt handler to report
839 // continue the transfer and signal completion.
840 USBD_REG(epie) = USBD_REG(epie) | (1 << ep_number);
841 }
842
843 if (ep_dir == TUSB_DIR_IN)
844 {
845 // For IN transfers send the first packet as a starter. Interrupt handler to complete
846 // this if it is larger than one packet.
847 xfer_bytes = _ft9xx_edpt_xfer_in(ep_number, buffer, total_bytes);
848
849 ep_xfer[ep_number].buff_ptr += xfer_bytes;
850 ep_xfer[ep_number].remain_size -= xfer_bytes;
851
852 // Tell the interrupt handler to signal dcd_event_xfer_complete on completion.
853 ep_xfer[ep_number].valid = 1;
854 }
855 else // (dir == TUSB_DIR_OUT)
856 {
857 // For OUT transfers on the control endpoint.
858 // The host may already have performed the first data transfer after the SETUP packet
859 // before the transfer is setup for it.
860 if (ep_xfer[ep_number].ready)
861 {
862 // We have received a data packet on the endpoint without a transfer
863 // being initialised. This can be because the host has sent this packet before
864 // a new transfer has been initiated on the endpoint.
865 // We will now stream the data from the FIFO.
866 ep_xfer[ep_number].ready = 0;
867
868 // Transfer incoming data from an OUT packet to the buffer.
869 xfer_bytes = _ft9xx_edpt_xfer_out(ep_number, buffer, total_bytes);
870
871 // Report completion of the transfer.
872 dcd_event_xfer_complete(BOARD_TUD_RHPORT, ep_number /*| TUSB_DIR_OUT_MASK */, xfer_bytes, XFER_RESULT_SUCCESS, false);
873 }
874 else
875 {
876 // Tell the interrupt handler to wait for the packet to be received and
877 // then report the transfer complete with dcd_event_xfer_complete.
878 ep_xfer[ep_number].valid = 1;
879 }
880 }
881 status = true;
882 }
883 else
884 {
885 // Note: should not arrive here.
886 }
887
888 CRITICAL_SECTION_END
889
890 return status;
891}
892
893// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c
894bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
895{
896 (void)rhport;
897 (void)ep_addr;
898 (void)ff;
899 (void)total_bytes;
900 bool status = false;
901 return status;
902}
903
904// Stall endpoint (non-control endpoint)
905void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
906{
907 uint8_t ep_number = tu_edpt_number(ep_addr);
908 (void)rhport;
909
910 CRITICAL_SECTION_BEGIN
911 if (ep_number == USBD_EP_0)
912 {
913 USBD_EP_CR_REG(USBD_EP_0) = USBD_EP_CR_REG(USBD_EP_0) |
914 MASK_USBD_EP0CR_SDSTL;
915 }
916 else
917 {
918 USBD_EP_CR_REG(ep_number) = USBD_EP_CR_REG(ep_number) |
919 MASK_USBD_EPxCR_SDSTL;
920 USBD_EP_SR_REG(ep_number) = MASK_USBD_EPxSR_CLR_TOGGLE |
921 MASK_USBD_EPxSR_FIFO_FLUSH;
922 }
923 CRITICAL_SECTION_END
924}
925
926// Clear stall (non-control endpoint), data toggle is also reset to DATA0
927void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
928{
929 uint8_t ep_number = tu_edpt_number(ep_addr);
930 (void)rhport;
931
932 if (ep_number > USBD_EP_0)
933 {
934 CRITICAL_SECTION_BEGIN
935 USBD_EP_CR_REG(ep_number) = USBD_EP_CR_REG(ep_number) &
936 (~MASK_USBD_EPxCR_SDSTL);
937 USBD_EP_SR_REG(ep_number) = MASK_USBD_EPxSR_CLR_TOGGLE;
938
939 // Allow transfers to restart.
940 ep_xfer[ep_number].ready = 0;
941 ep_xfer[ep_number].valid = 0;
942 ep_xfer[ep_number].remain_size = 0;
943 CRITICAL_SECTION_END
944 }
945}
946
947// Interrupt handling.
948
950{
951 dcd_int_handler(BOARD_TUD_RHPORT);
952}
953
954void dcd_int_handler(uint8_t rhport)
955{
956 (void)rhport;
957
958 // Read the Common Interrupt Flag Register.
959 uint8_t cmif = USBD_REG(cmif);
960 // Read the Endpoint Interrupt Flag Register.
961#if defined(__FT930__)
962 // This is 16 bits on FT93x.
963 uint16_t epif = USBD_REG(epif);
964#else
965 // This is 8 bits on FT90x.
966 uint8_t epif = USBD_REG(epif);
967#endif
968
969 if (cmif & MASK_USBD_CMIF_ALL)
970 {
971 // Clear all CMIF bits.
972 USBD_REG(cmif) = MASK_USBD_CMIF_ALL;
973 if (cmif & MASK_USBD_CMIF_PHYIRQ) //Handle PHY interrupt
974 {
975 }
976 if (cmif & MASK_USBD_CMIF_PIDIRQ) //Handle PIDIRQ interrupt
977 {
978 }
979 if (cmif & MASK_USBD_CMIF_CRC16IRQ) //Handle CRC16IRQ interrupt
980 {
981 }
982 if (cmif & MASK_USBD_CMIF_CRC5IRQ) //Handle CRC5 interrupt
983 {
984 }
985 if (cmif & MASK_USBD_CMIF_RSTIRQ) //Handle Reset interrupt
986 {
987 // Reset endpoints to default state.
989 dcd_event_bus_reset(BOARD_TUD_RHPORT, _speed, true);
990 }
991 if (cmif & MASK_USBD_CMIF_SUSIRQ) //Handle Suspend interrupt
992 {
993 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_SUSPEND, true);
994 }
995 if (cmif & MASK_USBD_CMIF_RESIRQ) //Handle Resume interrupt
996 {
997 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_RESUME, true);
998 }
999 if (cmif & MASK_USBD_CMIF_SOFIRQ) //Handle SOF interrupt
1000 {
1001 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_SOF, true);
1002 }
1003 }
1004 // Handle endpoint interrupts.
1005 if (epif)
1006 {
1007 uint16_t xfer_bytes;
1008
1009 // Check for EP0 interrupts pending.
1010 if (epif & MASK_USBD_EPIF_EP0IRQ)
1011 {
1012 // Clear interrupt register.
1013 USBD_REG(epif) = MASK_USBD_EPIF_EP0IRQ;
1014 // Test for an incoming SETUP request on the control endpoint.
1015 if (USBD_EP_SR_REG(USBD_EP_0) & MASK_USBD_EP0SR_SETUP)
1016 {
1017 // If protocol STALL, End the STALL signalling.
1018 if (USBD_EP_CR_REG(USBD_EP_0) & MASK_USBD_EP0CR_SDSTL)
1019 {
1020 // STALL end.
1021 USBD_EP_CR_REG(USBD_EP_0) = USBD_EP_CR_REG(USBD_EP_0) &
1022 (~MASK_USBD_EP0CR_SDSTL);
1023 // Clear STALL send.
1024 USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_STALL;
1025 }
1026
1027 // Host has sent a SETUP packet. Receive this into the SETUP packet store.
1028 _ft9xx_dusb_out(USBD_EP_0, (uint8_t *)_ft9xx_setup_packet, sizeof(USB_device_request));
1029
1030 // Send the packet to tinyusb.
1031 dcd_event_setup_received(BOARD_TUD_RHPORT, _ft9xx_setup_packet, true);
1032
1033 // Clear the interrupt that signals a SETUP packet is received.
1034 USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_SETUP);
1035
1036 // Any SETUP packet will clear the incoming FIFO.
1037 ep_xfer[USBD_EP_0].ready = 0;
1038
1039 // Allow new DATA and ACK transfers on the control endpoint.
1040 ep_xfer[USBD_EP_0].valid = 0;
1041 return;
1042 }
1043 else
1044 {
1045 // Check for a complete or partially complete transfers on EP0.
1046 if (ep_xfer[USBD_EP_0].valid)
1047 {
1048 xfer_bytes = (uint16_t)ep_xfer[USBD_EP_0].total_size;
1049
1050 // Transfer incoming data from an OUT packet to the buffer supplied.
1051 if (ep_xfer[USBD_EP_0].dir == TUSB_DIR_OUT)
1052 {
1053 xfer_bytes = _ft9xx_edpt_xfer_out(USBD_EP_0, ep_xfer[USBD_EP_0].buff_ptr, xfer_bytes);
1054 }
1055 // Now signal completion of data packet.
1056 dcd_event_xfer_complete(BOARD_TUD_RHPORT, USBD_EP_0 | (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0),
1057 xfer_bytes, XFER_RESULT_SUCCESS, true);
1058
1059 // Incoming FIFO has been cleared.
1060 ep_xfer[USBD_EP_0].ready = 0;
1061
1062 // Allow new transfers on the control endpoint.
1063 ep_xfer[USBD_EP_0].valid = 0;
1064 }
1065 // No transfer is in flight for EP0.
1066 else
1067 {
1068 // We have received a data packet on the control endpoint without a transfer
1069 // being initialised. This can be because the host has sent this packet before
1070 // a new transfer has been initiated on the control endpoint.
1071 // We will record that there is data in the FIFO for dcd_edpt_xfer to obtain
1072 // once the transfer is initiated.
1073 ep_xfer[USBD_EP_0].ready = 1;
1074 }
1075 }
1076 }
1077 else // !(epif & MASK_USBD_EPIF_EP0IRQ)
1078 {
1079 // Mask out currently disabled endpoints.
1080 epif &= USBD_REG(epie);
1081
1082 // Handle complete and partially complete transfers for each endpoint.
1083 for (uint8_t ep_number = 1; ep_number < USBD_MAX_ENDPOINT_COUNT; ep_number++)
1084 {
1085 if ((epif & MASK_USBD_EPIF_IRQ(ep_number)) == 0)
1086 {
1087 // No pending interrupt for this endpoint.
1088 continue;
1089 }
1090
1091 if (ep_xfer[ep_number].valid)
1092 {
1093 xfer_bytes = 0;
1094
1095 // Clear interrupt register for this endpoint.
1096 USBD_REG(epif) = MASK_USBD_EPIF_IRQ(ep_number);
1097
1098 // Start or continue an OUT transfer.
1099 if (ep_xfer[ep_number].dir == TUSB_DIR_OUT)
1100 {
1101 xfer_bytes = _ft9xx_edpt_xfer_out(ep_number,
1102 ep_xfer[ep_number].buff_ptr,
1103 (uint16_t)ep_xfer[ep_number].remain_size);
1104
1105 // Report each OUT packet received to the stack.
1106 dcd_event_xfer_complete(BOARD_TUD_RHPORT,
1107 ep_number /* | TUSB_DIR_OUT_MASK */,
1108 xfer_bytes, XFER_RESULT_SUCCESS, true);
1109
1110 ep_xfer[ep_number].buff_ptr += xfer_bytes;
1111 ep_xfer[ep_number].remain_size -= xfer_bytes;
1112 }
1113 // continue an IN transfer
1114 else // if (ep_xfer[ep_number].dir == TUSB_DIR_IN)
1115 {
1116 if (ep_xfer[ep_number].remain_size > 0)
1117 {
1118 xfer_bytes = _ft9xx_edpt_xfer_in(ep_number,
1119 ep_xfer[ep_number].buff_ptr,
1120 (uint16_t)ep_xfer[ep_number].remain_size);
1121
1122 ep_xfer[ep_number].buff_ptr += xfer_bytes;
1123 ep_xfer[ep_number].remain_size -= xfer_bytes;
1124 }
1125
1126 if (ep_xfer[ep_number].remain_size == 0)
1127 {
1128 dcd_event_xfer_complete(BOARD_TUD_RHPORT,
1129 ep_number | TUSB_DIR_IN_MASK,
1130 ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true);
1131 }
1132 }
1133
1134 // When the transfer is complete...
1135 if (ep_xfer[ep_number].remain_size == 0)
1136 {
1137 // Finish this transfer and allow new transfers on this endpoint.
1138 ep_xfer[ep_number].valid = 0;
1139
1140 // Disable the interrupt for this endpoint now it is complete.
1141 USBD_REG(epie) = USBD_REG(epie) & (~(1 << ep_number));
1142 }
1143
1144 ep_xfer[ep_number].ready = 0;
1145 }
1146 // No OUT transfer is in flight for this endpoint.
1147 else
1148 {
1149 if (ep_xfer[ep_number].dir == TUSB_DIR_OUT)
1150 {
1151 // We will record that there is data in the FIFO for dcd_edpt_xfer to obtain
1152 // once the transfer is initiated.
1153 // Strictly this should not happen for a non-control endpoint. Interrupts
1154 // are disabled when there are no transfers setup for an endpoint.
1155 ep_xfer[ep_number].ready = 1;
1156 }
1157 }
1158 }
1159 }
1160 }
1161}
1162
1163// Power management interrupt handler.
1164// This handles USB device related power management interrupts only.
1166{
1167 uint16_t pmcfg = SYS->PMCFG_H;
1168
1169 // Main interrupt handler is responible for
1170 if (pmcfg & MASK_SYS_PMCFG_DEV_CONN_DEV)
1171 {
1172 // Signal connection interrupt
1173 SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
1174 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_RESUME, true);
1175 }
1176
1177 if (pmcfg & MASK_SYS_PMCFG_DEV_DIS_DEV)
1178 {
1179 // Signal disconnection interrupt
1180 SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
1181 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_UNPLUGGED, true);
1182 }
1183
1184 if (pmcfg & MASK_SYS_PMCFG_HOST_RST_DEV)
1185 {
1186 // Signal Host Reset interrupt
1187 SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
1188 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_BUS_RESET, true);
1189 }
1190
1191 if (pmcfg & MASK_SYS_PMCFG_HOST_RESUME_DEV)
1192 {
1193 // Signal Host Resume interrupt
1194 SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
1195 if (!(SYS->MSC0CFG & MASK_SYS_MSC0CFG_DEV_RMWAKEUP))
1196 {
1197 // If we are driving K-state on Device USB port;
1198 // We must maintain the 1ms requirement before resuming the phy
1199 dcd_event_bus_signal(BOARD_TUD_RHPORT, DCD_EVENT_RESUME, true);
1200 }
1201 }
1202}
1203
1204#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 void _ft9xx_usb_speed(void)
Definition: dcd_ft9xx.c:324
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
Definition: dcd_ft9xx.c:894
static uint16_t _ft9xx_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length)
Definition: dcd_ft9xx.c:444
static tusb_speed_t _speed
Definition: dcd_ft9xx.c:74
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_ft9xx.c:905
void _ft9xx_usbd_ISR(void)
Definition: dcd_ft9xx.c:949
static uint16_t _ft9xx_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes)
void dcd_int_handler(uint8_t rhport)
Definition: dcd_ft9xx.c:954
void dcd_disconnect(uint8_t rhport)
Definition: dcd_ft9xx.c:652
static uint16_t _ft9xx_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes)
Definition: dcd_ft9xx.c:130
static void _dcd_ft9xx_attach(void)
Definition: dcd_ft9xx.c:226
int8_t board_ft9xx_vbus(void)
void dcd_edpt_close_all(uint8_t rhport)
Definition: dcd_ft9xx.c:802
void dcd_int_disable(uint8_t rhport)
Definition: dcd_ft9xx.c:543
CFG_TUD_MEM_SECTION static CFG_TUSB_MEM_ALIGN uint8_t _ft9xx_setup_packet[8]
Definition: dcd_ft9xx.c:55
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
Definition: dcd_ft9xx.c:674
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_ft9xx.c:927
static void _dcd_ft9xx_detach(void)
Definition: dcd_ft9xx.c:87
static uint16_t _ft9xx_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length)
Definition: dcd_ft9xx.c:387
void dcd_connect(uint8_t rhport)
Definition: dcd_ft9xx.c:609
void ft9xx_usbd_pm_ISR(void)
Definition: dcd_ft9xx.c:1165
static void _ft9xx_reset_edpts(void)
Definition: dcd_ft9xx.c:201
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_ft9xx.c:810
int board_uart_write(void const *buf, int len)
static struct ft9xx_xfer_state ep_xfer[USBD_MAX_ENDPOINT_COUNT]
Definition: dcd_ft9xx.c:72
static void _ft9xx_phy_enable(bool en)
Definition: dcd_ft9xx.c:217
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request)
Definition: dcd_ft9xx.c:575
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
Definition: dcd_ft9xx.c:553
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: dcd_ft9xx.c:520
void dcd_int_enable(uint8_t rhport)
Definition: dcd_ft9xx.c:533
void dcd_remote_wakeup(uint8_t rhport)
Definition: dcd_ft9xx.c:593
void dcd_sof_enable(uint8_t rhport, bool en)
Definition: dcd_ft9xx.c:661
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
struct __attribute__((__packed__)) reportHID_t
Definition: ffb_defs.h:102
uint8_t const * buffer
Definition: midi_device.h:100
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
struct TU_ATTR_PACKED::@16::TU_ATTR_PACKED bmRequestType_bit
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint8_t bEndpointAddress
Definition: video.h:306
uint8_t bRequest
Request type audio_cs_req_t.
Definition: audio.h:831
uint16_t buff_size
Definition: dcd_ft9xx.c:68
volatile uint8_t valid
Definition: dcd_ft9xx.c:60
uint8_t type
Definition: dcd_ft9xx.c:66
volatile uint8_t ready
Definition: dcd_ft9xx.c:59
uint16_t size
Definition: dcd_ft9xx.c:69
int16_t remain_size
Definition: dcd_ft9xx.c:63
int16_t total_size
Definition: dcd_ft9xx.c:62
uint8_t * buff_ptr
Definition: dcd_ft9xx.c:64
@ 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_REQ_SET_ADDRESS
Definition: tusb_types.h:127
@ TUSB_REQ_SET_CONFIGURATION
Definition: tusb_types.h:131
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
Definition: tusb_types.h:49
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
@ TUSB_SPEED_HIGH
Definition: tusb_types.h:52
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
Definition: tusb_types.h:507
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
@ TUSB_REQ_RCPT_DEVICE
Definition: tusb_types.h:151
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
@ TUSB_XFER_INTERRUPT
Definition: tusb_types.h:62
@ TUSB_XFER_BULK
Definition: tusb_types.h:61
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
Definition: tusb_types.h:502
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)
Definition: tusb_types.h:511
@ TUSB_REQ_TYPE_STANDARD
Definition: tusb_types.h:144
CFG_TUH_MEM_ALIGN tusb_control_request_t request
Definition: usbh.c:259