Open FFBoard
Open source force feedback firmware
dcd_rp2040.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2020 Raspberry Pi (Trading) 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#include "tusb_option.h"
28
29#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUD_RPI_PIO_USB
30
31#include "pico.h"
32#include "hardware/sync.h"
33#include "rp2040_usb.h"
34
35#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
36#include "pico/fix/rp2040_usb_device_enumeration.h"
37#endif
38
39#include "device/dcd.h"
40
41// Current implementation force vbus detection as always present, causing device think it is always plugged into host.
42// Therefore it cannot detect disconnect event, mistaken it as suspend.
43// Note: won't work if change to 0 (for now)
44#define FORCE_VBUS_DETECT 1
45
46/*------------------------------------------------------------------*/
47/* Low level controller
48 *------------------------------------------------------------------*/
49
50// Init these in dcd_init
51static uint8_t* next_buffer_ptr;
52
53// USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in.
54static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2];
55
56// SOF may be used by remote wakeup as RESUME, this indicate whether SOF is actually used by usbd
57static bool _sof_enable = false;
58
59TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) {
60 return &hw_endpoints[num][dir];
61}
62
63TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(uint8_t ep_addr) {
64 uint8_t num = tu_edpt_number(ep_addr);
66 return hw_endpoint_get_by_num(num, dir);
67}
68
69static void _hw_endpoint_alloc(struct hw_endpoint* ep, uint8_t transfer_type) {
70 // size must be multiple of 64
71 uint size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u;
72
73 // double buffered Bulk endpoint
75 size *= 2u;
76 }
77
79 next_buffer_ptr += size;
80
81 assert(((uintptr_t) next_buffer_ptr & 0b111111u) == 0);
82 uint dpram_offset = hw_data_offset(ep->hw_data_buf);
83 hard_assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
84
85 pico_info(" Allocated %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf);
86
87 // Fill in endpoint control register with buffer offset
88 uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint) transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
89
90 *ep->endpoint_control = reg;
91}
92
93static void _hw_endpoint_close(struct hw_endpoint* ep) {
94 // Clear hardware registers and then zero the struct
95 // Clears endpoint enable
96 *ep->endpoint_control = 0;
97 // Clears buffer available, etc
98 *ep->buffer_control = 0;
99 // Clear any endpoint state
100 memset(ep, 0, sizeof(struct hw_endpoint));
101
102 // Reclaim buffer space if all endpoints are closed
103 bool reclaim_buffers = true;
104 for (uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++) {
107 reclaim_buffers = false;
108 break;
109 }
110 }
111 if (reclaim_buffers) {
112 next_buffer_ptr = &usb_dpram->epx_data[0];
113 }
114}
115
116static void hw_endpoint_close(uint8_t ep_addr) {
119}
120
121static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) {
123
124 const uint8_t num = tu_edpt_number(ep_addr);
125 const tusb_dir_t dir = tu_edpt_dir(ep_addr);
126
127 ep->ep_addr = ep_addr;
128
129 // For device, IN is a tx transfer and OUT is an rx transfer
130 ep->rx = (dir == TUSB_DIR_OUT);
131
132 ep->next_pid = 0u;
135
136 // Every endpoint has a buffer control register in dpram
137 if (dir == TUSB_DIR_IN) {
138 ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in;
139 } else {
140 ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out;
141 }
142
143 // Clear existing buffer control state
144 *ep->buffer_control = 0;
145
146 if (num == 0) {
147 // EP0 has no endpoint control register because the buffer offsets are fixed
148 ep->endpoint_control = NULL;
149
150 // Buffer offset is fixed (also double buffered)
151 ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0];
152 } else {
153 // Set the endpoint control register (starts at EP1, hence num-1)
154 if (dir == TUSB_DIR_IN) {
155 ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in;
156 } else {
157 ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out;
158 }
159
160 // alloc a buffer and fill in endpoint control register
162 }
163}
164
165static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
168}
169
170static void __tusb_irq_path_func(hw_handle_buff_status)(void) {
171 uint32_t remaining_buffers = usb_hw->buf_status;
172 pico_trace("buf_status = 0x%08lx\r\n", remaining_buffers);
173 uint bit = 1u;
174 for (uint8_t i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) {
175 if (remaining_buffers & bit) {
176 // clear this in advance
177 usb_hw_clear->buf_status = bit;
178
179 // IN transfer for even i, OUT transfer for odd i
180 struct hw_endpoint* ep = hw_endpoint_get_by_num(i >> 1u, (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN);
181
182 // Continue xfer
183 bool done = hw_endpoint_xfer_continue(ep);
184 if (done) {
185 // Notify
188 }
189 remaining_buffers &= ~bit;
190 }
191 bit <<= 1u;
192 }
193}
194
195TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) {
196 // If we have finished this transfer on EP0 set pid back to 1 for next
197 // setup transfer. Also clear a stall in case
198 for (uint8_t dir = 0; dir < 2; dir++) {
199 struct hw_endpoint* ep = hw_endpoint_get_by_num(0, dir);
200 if (ep->active) {
201 // Abort any pending transfer from a prior control transfer per USB specs
202 // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1).
203 // Which means we are not guaranteed to safely abort pending transfer on B0 and B1.
204 uint32_t const abort_mask = (dir ? USB_EP_ABORT_EP0_IN_BITS : USB_EP_ABORT_EP0_OUT_BITS);
205 if (rp2040_chip_version() >= 2) {
206 usb_hw_set->abort = abort_mask;
207 while ((usb_hw->abort_done & abort_mask) != abort_mask) {}
208 }
209
210 _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_DATA1_PID | USB_BUF_CTRL_SEL);
212
213 if (rp2040_chip_version() >= 2) {
214 usb_hw_clear->abort_done = abort_mask;
215 usb_hw_clear->abort = abort_mask;
216 }
217 }
218 ep->next_pid = 1u;
219 }
220}
221
222static void __tusb_irq_path_func(reset_non_control_endpoints)(void) {
223 // Disable all non-control
224 for (uint8_t i = 0; i < USB_MAX_ENDPOINTS - 1; i++) {
225 usb_dpram->ep_ctrl[i].in = 0;
226 usb_dpram->ep_ctrl[i].out = 0;
227 }
228
229 // clear non-control hw endpoints
230 tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2 * sizeof(hw_endpoint_t));
231
232 // reclaim buffer space
233 next_buffer_ptr = &usb_dpram->epx_data[0];
234}
235
236static void __tusb_irq_path_func(dcd_rp2040_irq)(void) {
237 uint32_t const status = usb_hw->ints;
238 uint32_t handled = 0;
239
240 if (status & USB_INTF_DEV_SOF_BITS) {
241 bool keep_sof_alive = false;
242
243 handled |= USB_INTF_DEV_SOF_BITS;
244
245#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
246 // Errata 15 workaround for Device Bulk-In endpoint
247 e15_last_sof = time_us_32();
248
249 for (uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++) {
251
252 // Active Bulk IN endpoint requires SOF
253 if ((ep->transfer_type == TUSB_XFER_BULK) && ep->active) {
254 keep_sof_alive = true;
255
257
258 // Deferred enable?
259 if (ep->pending) {
260 ep->pending = 0;
262 }
263
265 }
266 }
267#endif
268
269 // disable SOF interrupt if it is used for RESUME in remote wakeup
270 if (!keep_sof_alive && !_sof_enable) usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS;
271
272 dcd_event_sof(0, usb_hw->sof_rd & USB_SOF_RD_BITS, true);
273 }
274
275 // xfer events are handled before setup req. So if a transfer completes immediately
276 // before closing the EP, the events will be delivered in same order.
277 if (status & USB_INTS_BUFF_STATUS_BITS) {
278 handled |= USB_INTS_BUFF_STATUS_BITS;
280 }
281
282 if (status & USB_INTS_SETUP_REQ_BITS) {
283 handled |= USB_INTS_SETUP_REQ_BITS;
284 uint8_t const* setup = remove_volatile_cast(uint8_t const*, &usb_dpram->setup_packet);
285
286 // reset pid to both 1 (data and ack)
287 reset_ep0();
288
289 // Pass setup packet to tiny usb
290 dcd_event_setup_received(0, setup, true);
291 usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
292 }
293
294#if FORCE_VBUS_DETECT == 0
295 // Since we force VBUS detect On, device will always think it is connected and
296 // couldn't distinguish between disconnect and suspend
297 if (status & USB_INTS_DEV_CONN_DIS_BITS)
298 {
299 handled |= USB_INTS_DEV_CONN_DIS_BITS;
300
301 if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS )
302 {
303 // Connected: nothing to do
304 }else
305 {
306 // Disconnected
307 dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
308 }
309
310 usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
311 }
312#endif
313
314 // SE0 for 2.5 us or more (will last at least 10ms)
315 if (status & USB_INTS_BUS_RESET_BITS) {
316 pico_trace("BUS RESET\r\n");
317
318 handled |= USB_INTS_BUS_RESET_BITS;
319
320 usb_hw->dev_addr_ctrl = 0;
323 usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
324
325#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
326 // Only run enumeration workaround if pull up is enabled
327 if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) rp2040_usb_device_enumeration_fix();
328#endif
329 }
330
331 /* Note from pico datasheet 4.1.2.6.4 (v1.2)
332 * If you enable the suspend interrupt, it is likely you will see a suspend interrupt when
333 * the device is first connected but the bus is idle. The bus can be idle for a few ms before
334 * the host begins sending start of frame packets. You will also see a suspend interrupt
335 * when the device is disconnected if you do not have a VBUS detect circuit connected. This is
336 * because without VBUS detection, it is impossible to tell the difference between
337 * being disconnected and suspended.
338 */
339 if (status & USB_INTS_DEV_SUSPEND_BITS) {
340 handled |= USB_INTS_DEV_SUSPEND_BITS;
341 dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
342 usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
343 }
344
345 if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) {
346 handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
347 dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
348 usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
349 }
350
351 if (status ^ handled) {
352 panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled));
353 }
354}
355
356#define USB_INTS_ERROR_BITS ( \
357 USB_INTS_ERROR_DATA_SEQ_BITS | \
358 USB_INTS_ERROR_BIT_STUFF_BITS | \
359 USB_INTS_ERROR_CRC_BITS | \
360 USB_INTS_ERROR_RX_OVERFLOW_BITS | \
361 USB_INTS_ERROR_RX_TIMEOUT_BITS)
362
363/*------------------------------------------------------------------*/
364/* Controller API
365 *------------------------------------------------------------------*/
366
367// older SDK
368#ifndef PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY
369#define PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY 0xff
370#endif
371
372bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
373 (void) rh_init;
374 assert(rhport == 0);
375
376 TU_LOG(2, "Chip Version B%u\r\n", rp2040_chip_version());
377
378 // Reset hardware to default state
380
381#if FORCE_VBUS_DETECT
382 // Force VBUS detect so the device thinks it is plugged into a host
383 usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
384#endif
385
386 irq_add_shared_handler(USBCTRL_IRQ, dcd_rp2040_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
387
388 // Init control endpoints
389 tu_memclr(hw_endpoints[0], 2 * sizeof(hw_endpoint_t));
392
393 // Init non-control endpoints
395
396 // Initializes the USB peripheral for device mode and enables it.
397 // Don't need to enable the pull up here. Force VBUS
398 usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
399
400 // Enable individual controller IRQS here. Processor interrupt enable will be used
401 // for the global interrupt enable...
402 // Note: Force VBUS detect cause disconnection not detectable
403 usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
404 usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
405 USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
406 (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
407
408 dcd_connect(rhport);
409 return true;
410}
411
412bool dcd_deinit(uint8_t rhport) {
413 (void) rhport;
414
416 irq_remove_handler(USBCTRL_IRQ, dcd_rp2040_irq);
417
418 // reset usb hardware into initial state
419 reset_block(RESETS_RESET_USBCTRL_BITS);
420 unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
421
422 return true;
423}
424
425void dcd_int_enable(__unused uint8_t rhport) {
426 assert(rhport == 0);
427 irq_set_enabled(USBCTRL_IRQ, true);
428}
429
430void dcd_int_disable(__unused uint8_t rhport) {
431 assert(rhport == 0);
432 irq_set_enabled(USBCTRL_IRQ, false);
433}
434
435void dcd_set_address(__unused uint8_t rhport, __unused uint8_t dev_addr) {
436 assert(rhport == 0);
437
438 // Can't set device address in hardware until status xfer has complete
439 // Send 0len complete response on EP0 IN
440 hw_endpoint_xfer(0x80, NULL, 0);
441}
442
443void dcd_remote_wakeup(__unused uint8_t rhport) {
444 pico_info("dcd_remote_wakeup %d\n", rhport);
445 assert(rhport == 0);
446
447 // since RESUME interrupt is not triggered if we are the one initiate
448 // briefly enable SOF to notify usbd when bus is ready
449 usb_hw_set->inte = USB_INTS_DEV_SOF_BITS;
450 usb_hw_set->sie_ctrl = USB_SIE_CTRL_RESUME_BITS;
451}
452
453// disconnect by disabling internal pull-up resistor on D+/D-
454void dcd_disconnect(__unused uint8_t rhport) {
455 (void) rhport;
456 usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
457}
458
459// connect by enabling internal pull-up resistor on D+/D-
460void dcd_connect(__unused uint8_t rhport) {
461 (void) rhport;
462 usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
463}
464
465void dcd_sof_enable(uint8_t rhport, bool en) {
466 (void) rhport;
467
468 _sof_enable = en;
469
470 if (en) {
471 usb_hw_set->inte = USB_INTS_DEV_SOF_BITS;
472 }
473#if !TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
474 else {
475 // Don't clear immediately if the SOF workaround is in use.
476 // The SOF handler will conditionally disable the interrupt.
477 usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS;
478 }
479#endif
480}
481
482/*------------------------------------------------------------------*/
483/* DCD Endpoint port
484 *------------------------------------------------------------------*/
485
487 (void) rhport;
488
492 usb_hw->dev_addr_ctrl = (uint8_t) request->wValue;
493 }
494}
495
496bool dcd_edpt_open(__unused uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
497 assert(rhport == 0);
498 hw_endpoint_init(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), desc_edpt->bmAttributes.xfer);
499 return true;
500}
501
502void dcd_edpt_close_all(uint8_t rhport) {
503 (void) rhport;
504
505 // may need to use EP Abort
507}
508
509bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
510 assert(rhport == 0);
512 return true;
513}
514
515void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
516 (void) rhport;
517
518 if (tu_edpt_number(ep_addr) == 0) {
519 // A stall on EP0 has to be armed so it can be cleared on the next setup packet
520 usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS
521 : USB_EP_STALL_ARM_EP0_OUT_BITS;
522 }
523
525
526 // stall and clear current pending buffer
527 // may need to use EP_ABORT
528 _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_STALL);
529}
530
531void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
532 (void) rhport;
533
534 if (tu_edpt_number(ep_addr)) {
536
537 // clear stall also reset toggle to DATA0, ready for next transfer
538 ep->next_pid = 0;
539 _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL);
540 }
541}
542
543void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
544 (void) rhport;
545 pico_trace("dcd_edpt_close %02x\r\n", ep_addr);
547}
548
549void __tusb_irq_path_func(dcd_int_handler)(uint8_t rhport) {
550 (void) rhport;
552}
553
554#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_sof(uint8_t rhport, uint32_t frame_count, bool in_isr)
Definition: dcd.h:232
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
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
bool dcd_edpt_open(__unused uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
Definition: dcd_rp2040.c:496
static void hw_endpoint_close(uint8_t ep_addr)
Definition: dcd_rp2040.c:116
static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2]
Definition: dcd_rp2040.c:54
static uint8_t * next_buffer_ptr
Definition: dcd_rp2040.c:51
static bool _sof_enable
Definition: dcd_rp2040.c:57
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_rp2040.c:515
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_rp2040.c:543
void dcd_int_enable(__unused uint8_t rhport)
Definition: dcd_rp2040.c:425
bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_rp2040.c:509
static void __tusb_irq_path_func() hw_handle_buff_status(void)
Definition: dcd_rp2040.c:170
static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
Definition: dcd_rp2040.c:69
void dcd_edpt_close_all(uint8_t rhport)
Definition: dcd_rp2040.c:502
static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_rp2040.c:165
void dcd_remote_wakeup(__unused uint8_t rhport)
Definition: dcd_rp2040.c:443
void dcd_int_disable(__unused uint8_t rhport)
Definition: dcd_rp2040.c:430
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_rp2040.c:531
static TU_ATTR_ALWAYS_INLINE struct hw_endpoint * hw_endpoint_get_by_addr(uint8_t ep_addr)
Definition: dcd_rp2040.c:63
void dcd_disconnect(__unused uint8_t rhport)
Definition: dcd_rp2040.c:454
bool dcd_deinit(uint8_t rhport)
Definition: dcd_rp2040.c:412
static void __tusb_irq_path_func() reset_non_control_endpoints(void)
Definition: dcd_rp2040.c:222
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request)
Definition: dcd_rp2040.c:486
void __tusb_irq_path_func() dcd_int_handler(uint8_t rhport)
Definition: dcd_rp2040.c:549
void dcd_set_address(__unused uint8_t rhport, __unused uint8_t dev_addr)
Definition: dcd_rp2040.c:435
static TU_ATTR_ALWAYS_INLINE void reset_ep0(void)
Definition: dcd_rp2040.c:195
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: dcd_rp2040.c:372
static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
Definition: dcd_rp2040.c:121
static void _hw_endpoint_close(struct hw_endpoint *ep)
Definition: dcd_rp2040.c:93
static TU_ATTR_ALWAYS_INLINE struct hw_endpoint * hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir)
Definition: dcd_rp2040.c:59
void dcd_connect(__unused uint8_t rhport)
Definition: dcd_rp2040.c:460
static void __tusb_irq_path_func() dcd_rp2040_irq(void)
Definition: dcd_rp2040.c:236
void dcd_sof_enable(uint8_t rhport, bool en)
Definition: dcd_rp2040.c:465
uint8_t const * buffer
Definition: midi_device.h:100
void __tusb_irq_path_func() hw_endpoint_reset_transfer(struct hw_endpoint *ep)
Definition: rp2040_usb.c:89
void __tusb_irq_path_func() hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
Definition: rp2040_usb.c:155
volatile uint32_t e15_last_sof
Definition: rp2040_usb.c:355
void rp2040_usb_init(void)
Definition: rp2040_usb.c:65
bool __tusb_irq_path_func() hw_endpoint_xfer_continue(struct hw_endpoint *ep)
Definition: rp2040_usb.c:302
void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len)
Definition: rp2040_usb.c:194
static TU_ATTR_ALWAYS_INLINE void _hw_endpoint_buffer_control_set_value32(struct hw_endpoint *ep, uint32_t value)
Definition: rp2040_usb.h:120
static uintptr_t hw_data_offset(uint8_t *buf)
Definition: rp2040_usb.h:135
static TU_ATTR_ALWAYS_INLINE void hw_endpoint_lock_update(__unused struct hw_endpoint *ep, __unused int delta)
Definition: rp2040_usb.h:107
static TU_ATTR_ALWAYS_INLINE void _hw_endpoint_buffer_control_clear_mask32(struct hw_endpoint *ep, uint32_t value)
Definition: rp2040_usb.h:130
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint16_t wValue
Definition: audio.h:934
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
uint8_t pending
Definition: rp2040_usb.h:84
io_rw_32 * endpoint_control
Definition: rp2040_usb.h:59
uint8_t transfer_type
Definition: rp2040_usb.h:81
uint8_t * hw_data_buf
Definition: rp2040_usb.h:65
uint8_t next_pid
Definition: rp2040_usb.h:56
uint16_t xferred_len
Definition: rp2040_usb.h:72
uint16_t wMaxPacketSize
Definition: rp2040_usb.h:75
uint8_t ep_addr
Definition: rp2040_usb.h:55
io_rw_32 * buffer_control
Definition: rp2040_usb.h:62
bool active
Definition: rp2040_usb.h:78
static TU_ATTR_ALWAYS_INLINE uint32_t tu_div_ceil(uint32_t v, uint32_t d)
Definition: tusb_common.h:179
tusb_dir_t
Definition: tusb_types.h:65
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ TUSB_DIR_OUT
Definition: tusb_types.h:66
@ TUSB_REQ_SET_ADDRESS
Definition: tusb_types.h:127
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
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_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
@ TUSB_REQ_TYPE_STANDARD
Definition: tusb_types.h:144
CFG_TUH_MEM_ALIGN tusb_control_request_t request
Definition: usbh.c:259