Open FFBoard
Open source force feedback firmware
hcd_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 * Copyright (c) 2021 Ha Thach (tinyusb.org) for Double Buffered
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 * This file is part of the TinyUSB stack.
26 */
27
28#include "tusb_option.h"
29
30#if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUH_RPI_PIO_USB && !CFG_TUH_MAX3421
31
32#include "pico.h"
33#include "rp2040_usb.h"
34
35//--------------------------------------------------------------------+
36// INCLUDE
37//--------------------------------------------------------------------+
38#include "osal/osal.h"
39
40#include "host/hcd.h"
41#include "host/usbh.h"
42
43// port 0 is native USB port, other is counted as software PIO
44#define RHPORT_NATIVE 0
45
46//--------------------------------------------------------------------+
47// Low level rp2040 controller functions
48//--------------------------------------------------------------------+
49
50#ifndef PICO_USB_HOST_INTERRUPT_ENDPOINTS
51#define PICO_USB_HOST_INTERRUPT_ENDPOINTS (USB_MAX_ENDPOINTS - 1)
52#endif
53static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, "");
54
55// Host mode uses one shared endpoint register for non-interrupt endpoint
56static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS];
57#define epx (ep_pool[0])
58
59// Flags we set by default in sie_ctrl (we add other bits on top)
60enum {
61 SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
62 USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS
63};
64
65static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr)
66{
67 uint8_t num = tu_edpt_number(ep_addr);
68 if ( num == 0 ) return &epx;
69
70 for ( uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ )
71 {
72 struct hw_endpoint *ep = &ep_pool[i];
73 if ( ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr) ) return ep;
74 }
75
76 return NULL;
77}
78
79TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void)
80{
81 return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB;
82}
83
84TU_ATTR_ALWAYS_INLINE static inline bool need_pre(uint8_t dev_addr)
85{
86 // If this device is different to the speed of the root device
87 // (i.e. is a low speed device on a full speed hub) then need pre
89}
90
91static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_result_t xfer_result)
92{
93 // Mark transfer as done before we tell the tinyusb stack
94 uint8_t dev_addr = ep->dev_addr;
95 uint8_t ep_addr = ep->ep_addr;
96 uint xferred_len = ep->xferred_len;
99}
100
101static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_endpoint *ep)
102{
103 usb_hw_clear->buf_status = bit;
104 // EP may have been stalled?
105 assert(ep->active);
106 bool done = hw_endpoint_xfer_continue(ep);
107 if ( done )
108 {
110 }
111}
112
113static void __tusb_irq_path_func(hw_handle_buff_status)(void)
114{
115 uint32_t remaining_buffers = usb_hw->buf_status;
116 pico_trace("buf_status 0x%08lx\n", remaining_buffers);
117
118 // Check EPX first
119 uint bit = 0b1;
120 if ( remaining_buffers & bit )
121 {
122 remaining_buffers &= ~bit;
123 struct hw_endpoint * ep = &epx;
124
125 uint32_t ep_ctrl = *ep->endpoint_control;
126 if ( ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS )
127 {
128 TU_LOG(3, "Double Buffered: ");
129 }
130 else
131 {
132 TU_LOG(3, "Single Buffered: ");
133 }
134 TU_LOG_HEX(3, ep_ctrl);
135
137 }
138
139 // Check "interrupt" (asynchronous) endpoints for both IN and OUT
140 for ( uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++ )
141 {
142 // EPX is bit 0 & 1
143 // IEP1 IN is bit 2
144 // IEP1 OUT is bit 3
145 // IEP2 IN is bit 4
146 // IEP2 OUT is bit 5
147 // IEP3 IN is bit 6
148 // IEP3 OUT is bit 7
149 // etc
150 for ( uint j = 0; j < 2; j++ )
151 {
152 bit = 1 << (i * 2 + j);
153 if ( remaining_buffers & bit )
154 {
155 remaining_buffers &= ~bit;
157 }
158 }
159 }
160
161 if ( remaining_buffers )
162 {
163 panic("Unhandled buffer %d\n", remaining_buffers);
164 }
165}
166
167static void __tusb_irq_path_func(hw_trans_complete)(void)
168{
169 if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS)
170 {
171 pico_trace("Sent setup packet\n");
172 struct hw_endpoint *ep = &epx;
173 assert(ep->active);
174 // Set transferred length to 8 for a setup packet
175 ep->xferred_len = 8;
177 }
178 else
179 {
180 // Don't care. Will handle this in buff status
181 return;
182 }
183}
184
185static void __tusb_irq_path_func(hcd_rp2040_irq)(void)
186{
187 uint32_t status = usb_hw->ints;
188 uint32_t handled = 0;
189
190 if ( status & USB_INTS_HOST_CONN_DIS_BITS )
191 {
192 handled |= USB_INTS_HOST_CONN_DIS_BITS;
193
194 if ( dev_speed() )
195 {
196 hcd_event_device_attach(RHPORT_NATIVE, true);
197 }
198 else
199 {
200 hcd_event_device_remove(RHPORT_NATIVE, true);
201 }
202
203 // Clear speed change interrupt
204 usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS;
205 }
206
207 if ( status & USB_INTS_STALL_BITS )
208 {
209 // We have rx'd a stall from the device
210 // NOTE THIS SHOULD HAVE PRIORITY OVER BUFF_STATUS
211 // AND TRANS_COMPLETE as the stall is an alternative response
212 // to one of those events
213 pico_trace("Stall REC\n");
214 handled |= USB_INTS_STALL_BITS;
215 usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS;
217 }
218
219 if ( status & USB_INTS_BUFF_STATUS_BITS )
220 {
221 handled |= USB_INTS_BUFF_STATUS_BITS;
222 TU_LOG(2, "Buffer complete\r\n");
224 }
225
226 if ( status & USB_INTS_TRANS_COMPLETE_BITS )
227 {
228 handled |= USB_INTS_TRANS_COMPLETE_BITS;
229 usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
230 TU_LOG(2, "Transfer complete\r\n");
232 }
233
234 if ( status & USB_INTS_ERROR_RX_TIMEOUT_BITS )
235 {
236 handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS;
237 usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS;
238 }
239
240 if ( status & USB_INTS_ERROR_DATA_SEQ_BITS )
241 {
242 usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
243 TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n",
244 tu_u32_low16(*epx.buffer_control),
245 tu_u32_high16(*epx.buffer_control));
246 panic("Data Seq Error \n");
247 }
248
249 if ( status ^ handled )
250 {
251 panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled));
252 }
253}
254
255void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) {
256 (void) rhport;
257 (void) in_isr;
259}
260
262{
263 struct hw_endpoint * ep = NULL;
264 for ( uint i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ )
265 {
266 ep = &ep_pool[i];
267 if ( !ep->configured )
268 {
269 // Will be configured by _hw_endpoint_init / _hw_endpoint_allocate
270 ep->interrupt_num = (uint8_t) (i - 1);
271 return ep;
272 }
273 }
274 return ep;
275}
276
278{
279 struct hw_endpoint * ep = NULL;
280
282 {
283 // Note: even though datasheet name these "Interrupt" endpoints. These are actually
284 // "Asynchronous" endpoints and can be used for other type such as: Bulk (ISO need confirmation)
286 pico_info("Allocate %s ep %d\n", tu_edpt_type_str(transfer_type), ep->interrupt_num);
287 assert(ep);
288 ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl;
289 ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl;
290 // 0 for epx (double buffered): TODO increase to 1024 for ISO
291 // 2x64 for intep0
292 // 3x64 for intep1
293 // etc
294 ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 2)];
295 }
296 else
297 {
298 ep = &epx;
299 ep->buffer_control = &usbh_dpram->epx_buf_ctrl;
300 ep->endpoint_control = &usbh_dpram->epx_ctrl;
301 ep->hw_data_buf = &usbh_dpram->epx_data[0];
302 }
303
304 return ep;
305}
306
307static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval)
308{
309 // Already has data buffer, endpoint control, and buffer control allocated at this point
310 assert(ep->endpoint_control);
311 assert(ep->buffer_control);
312 assert(ep->hw_data_buf);
313
314 uint8_t const num = tu_edpt_number(ep_addr);
315 tusb_dir_t const dir = tu_edpt_dir(ep_addr);
316
317 ep->ep_addr = ep_addr;
318 ep->dev_addr = dev_addr;
319
320 // For host, IN to host == RX, anything else rx == false
321 ep->rx = (dir == TUSB_DIR_IN);
322
323 // Response to a setup packet on EP0 starts with pid of 1
324 ep->next_pid = (num == 0 ? 1u : 0u);
327
328 pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, ep->transfer_type);
329 pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf);
330 uint dpram_offset = hw_data_offset(ep->hw_data_buf);
331 // Bits 0-5 should be 0
332 assert(!(dpram_offset & 0b111111));
333
334 // Fill in endpoint control register with buffer offset
335 uint32_t ep_reg = EP_CTRL_ENABLE_BITS
336 | EP_CTRL_INTERRUPT_PER_BUFFER
337 | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB)
338 | dpram_offset;
339 if ( bmInterval )
340 {
341 ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB);
342 }
343 *ep->endpoint_control = ep_reg;
344 pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg);
345 ep->configured = true;
346
347 if ( ep != &epx )
348 {
349 // Endpoint has its own addr_endp and interrupt bits to be setup!
350 // This is an interrupt/async endpoint. so need to set up ADDR_ENDP register with:
351 // - device address
352 // - endpoint number / direction
353 // - preamble
354 uint32_t reg = (uint32_t) (dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB));
355
356 if ( dir == TUSB_DIR_OUT )
357 {
358 reg |= USB_ADDR_ENDP1_INTEP_DIR_BITS;
359 }
360
361 if ( need_pre(dev_addr) )
362 {
363 reg |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS;
364 }
365 usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = reg;
366
367 // Finally, enable interrupt that endpoint
368 usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1);
369
370 // If it's an interrupt endpoint we need to set up the buffer control
371 // register
372 }
373}
374
375//--------------------------------------------------------------------+
376// HCD API
377//--------------------------------------------------------------------+
378bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
379 (void) rhport;
380 (void) rh_init;
381 pico_trace("hcd_init %d\n", rhport);
382 assert(rhport == 0);
383
384 // Reset any previous state
386
387 // Force VBUS detect to always present, for now we assume vbus is always provided (without using VBUS En)
388 usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
389
390 // Remove shared irq if it was previously added so as not to fill up shared irq slots
391 irq_remove_handler(USBCTRL_IRQ, hcd_rp2040_irq);
392
393 irq_add_shared_handler(USBCTRL_IRQ, hcd_rp2040_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
394
395 // clear epx and interrupt eps
396 memset(&ep_pool, 0, sizeof(ep_pool));
397
398 // Enable in host mode with SOF / Keep alive on
399 usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS;
400 usb_hw->sie_ctrl = SIE_CTRL_BASE;
401 usb_hw->inte = USB_INTE_BUFF_STATUS_BITS |
402 USB_INTE_HOST_CONN_DIS_BITS |
403 USB_INTE_HOST_RESUME_BITS |
404 USB_INTE_STALL_BITS |
405 USB_INTE_TRANS_COMPLETE_BITS |
406 USB_INTE_ERROR_RX_TIMEOUT_BITS |
407 USB_INTE_ERROR_DATA_SEQ_BITS ;
408
409 return true;
410}
411
412bool hcd_deinit(uint8_t rhport) {
413 (void) rhport;
414
415 irq_remove_handler(USBCTRL_IRQ, hcd_rp2040_irq);
416 reset_block(RESETS_RESET_USBCTRL_BITS);
417 unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
418
419 return true;
420}
421
422void hcd_port_reset(uint8_t rhport)
423{
424 (void) rhport;
425 pico_trace("hcd_port_reset\n");
426 assert(rhport == 0);
427 // TODO: Nothing to do here yet. Perhaps need to reset some state?
428}
429
430void hcd_port_reset_end(uint8_t rhport)
431{
432 (void) rhport;
433}
434
435bool hcd_port_connect_status(uint8_t rhport)
436{
437 (void) rhport;
438 pico_trace("hcd_port_connect_status\n");
439 assert(rhport == 0);
440 return usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS;
441}
442
444{
445 (void) rhport;
446 assert(rhport == 0);
447
448 // TODO: Should enumval this register
449 switch ( dev_speed() )
450 {
451 case 1:
452 return TUSB_SPEED_LOW;
453 case 2:
454 return TUSB_SPEED_FULL;
455 default:
456 panic("Invalid speed\n");
457 // return TUSB_SPEED_INVALID;
458 }
459}
460
461// Close all opened endpoint belong to this device
462void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
463{
464 pico_trace("hcd_device_close %d\n", dev_addr);
465 (void) rhport;
466
467 if (dev_addr == 0) return;
468
469 for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++)
470 {
471 hw_endpoint_t* ep = &ep_pool[i];
472
473 if (ep->dev_addr == dev_addr && ep->configured)
474 {
475 // in case it is an interrupt endpoint, disable it
476 usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
477 usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
478
479 // unconfigure the endpoint
480 ep->configured = false;
481 *ep->endpoint_control = 0;
482 *ep->buffer_control = 0;
484 }
485 }
486}
487
488uint32_t hcd_frame_number(uint8_t rhport)
489{
490 (void) rhport;
491 return usb_hw->sof_rd;
492}
493
494void hcd_int_enable(uint8_t rhport)
495{
496 (void) rhport;
497 assert(rhport == 0);
498 irq_set_enabled(USBCTRL_IRQ, true);
499}
500
501void hcd_int_disable(uint8_t rhport)
502{
503 (void) rhport;
504 // todo we should check this is disabling from the correct core; note currently this is never called
505 assert(rhport == 0);
506 irq_set_enabled(USBCTRL_IRQ, false);
507}
508
509//--------------------------------------------------------------------+
510// Endpoint API
511//--------------------------------------------------------------------+
512
513bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
514{
515 (void) rhport;
516
517 pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress);
518
519 // Allocated differently based on if it's an interrupt endpoint or not
520 struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer);
521 TU_ASSERT(ep);
522
524 dev_addr,
525 ep_desc->bEndpointAddress,
526 tu_edpt_packet_size(ep_desc),
527 ep_desc->bmAttributes.xfer,
528 ep_desc->bInterval);
529
530 return true;
531}
532
533bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
534{
535 (void) rhport;
536
537 pico_trace("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen);
538
539 uint8_t const ep_num = tu_edpt_number(ep_addr);
540 tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr);
541
542 // Get appropriate ep. Either EPX or interrupt endpoint
543 struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
544
545 TU_ASSERT(ep);
546
547 // EP should be inactive
548 assert(!ep->active);
549
550 // Control endpoint can change direction 0x00 <-> 0x80
551 if ( ep_addr != ep->ep_addr )
552 {
553 assert(ep_num == 0);
554
555 // Direction has flipped on endpoint control so re init it but with same properties
557 }
558
559 // If a normal transfer (non-interrupt) then initiate using
560 // sie ctrl registers. Otherwise interrupt ep registers should
561 // already be configured
562 if ( ep == &epx )
563 {
564 hw_endpoint_xfer_start(ep, buffer, buflen);
565
566 // That has set up buffer control, endpoint control etc
567 // for host we have to initiate the transfer
568 usb_hw->dev_addr_ctrl = (uint32_t) (dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB));
569
570 uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE |
571 (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) |
572 (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0);
573 // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit
574 // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access".
575 // We write everything except the START_TRANS bit first, then wait some cycles.
576 usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS;
577 busy_wait_at_least_cycles(12);
578 usb_hw->sie_ctrl = flags;
579 }else
580 {
581 hw_endpoint_xfer_start(ep, buffer, buflen);
582 }
583
584 return true;
585}
586
587bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
588 (void) rhport;
589 (void) dev_addr;
590 (void) ep_addr;
591 // TODO not implemented yet
592 return false;
593}
594
595bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
596{
597 (void) rhport;
598
599 // Copy data into setup packet buffer
600 for ( uint8_t i = 0; i < 8; i++ )
601 {
602 usbh_dpram->setup_packet[i] = setup_packet[i];
603 }
604
605 // Configure EP0 struct with setup info for the trans complete
606 struct hw_endpoint * ep = _hw_endpoint_allocate(0);
607 TU_ASSERT(ep);
608
609 // EPX should be inactive
610 assert(!ep->active);
611
612 // EP0 out
613 _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0);
614 assert(ep->configured);
615
616 ep->remaining_len = 8;
617 ep->active = true;
618
619 // Set device address
620 usb_hw->dev_addr_ctrl = dev_addr;
621
622 // Set pre if we are a low speed device on full speed hub
623 uint32_t const flags = SIE_CTRL_BASE | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS |
624 (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0);
625
626 // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit
627 // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access".
628 // We write everything except the START_TRANS bit first, then wait some cycles.
629 usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS;
630 busy_wait_at_least_cycles(12);
631 usb_hw->sie_ctrl = flags;
632
633 return true;
634}
635
636bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
637 (void) rhport;
638 (void) dev_addr;
639 (void) ep_addr;
640
641 panic("hcd_clear_stall");
642 // return true;
643}
644
645#endif
static bool in_isr
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_remove(uint8_t rhport, bool in_isr)
Definition: hcd.h:209
static TU_ATTR_ALWAYS_INLINE void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
Definition: hcd.h:221
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_attach(uint8_t rhport, bool in_isr)
Definition: hcd.h:197
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
Definition: hcd_rp2040.c:595
static struct hw_endpoint * get_dev_ep(uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_rp2040.c:65
void hcd_int_disable(uint8_t rhport)
Definition: hcd_rp2040.c:501
void __tusb_irq_path_func() hcd_int_handler(uint8_t rhport, bool in_isr)
Definition: hcd_rp2040.c:255
static struct hw_endpoint ep_pool[1+PICO_USB_HOST_INTERRUPT_ENDPOINTS]
Definition: hcd_rp2040.c:56
static TU_ATTR_ALWAYS_INLINE uint8_t dev_speed(void)
Definition: hcd_rp2040.c:79
static struct hw_endpoint * _next_free_interrupt_ep(void)
Definition: hcd_rp2040.c:261
static void __tusb_irq_path_func() hw_trans_complete(void)
Definition: hcd_rp2040.c:167
static struct hw_endpoint * _hw_endpoint_allocate(uint8_t transfer_type)
Definition: hcd_rp2040.c:277
static void __tusb_irq_path_func() _handle_buff_status_bit(uint bit, struct hw_endpoint *ep)
Definition: hcd_rp2040.c:101
static TU_ATTR_ALWAYS_INLINE bool need_pre(uint8_t dev_addr)
Definition: hcd_rp2040.c:84
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_rp2040.c:636
bool hcd_deinit(uint8_t rhport)
Definition: hcd_rp2040.c:412
static void __tusb_irq_path_func() hw_handle_buff_status(void)
Definition: hcd_rp2040.c:113
void hcd_int_enable(uint8_t rhport)
Definition: hcd_rp2040.c:494
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
Definition: hcd_rp2040.c:533
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
Definition: hcd_rp2040.c:462
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_rp2040.c:587
void hcd_port_reset_end(uint8_t rhport)
Definition: hcd_rp2040.c:430
void hcd_port_reset(uint8_t rhport)
Definition: hcd_rp2040.c:422
bool hcd_port_connect_status(uint8_t rhport)
Definition: hcd_rp2040.c:435
uint32_t hcd_frame_number(uint8_t rhport)
Definition: hcd_rp2040.c:488
static void __tusb_irq_path_func() hcd_rp2040_irq(void)
Definition: hcd_rp2040.c:185
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
Definition: hcd_rp2040.c:443
@ SIE_CTRL_BASE
Definition: hcd_rp2040.c:61
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: hcd_rp2040.c:378
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc)
Definition: hcd_rp2040.c:513
static void __tusb_irq_path_func() hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result)
Definition: hcd_rp2040.c:91
static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval)
Definition: hcd_rp2040.c:307
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 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 uintptr_t hw_data_offset(uint8_t *buf)
Definition: rp2040_usb.h:135
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint8_t bInterval
Definition: tusb_types.h:372
uint8_t dev_addr
Definition: hcd_khci.c:105
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint8_t bEndpointAddress
Definition: video.h:306
uint16_t remaining_len
Definition: rp2040_usb.h:71
io_rw_32 * endpoint_control
Definition: rp2040_usb.h:59
uint8_t dev_addr
Definition: rp2040_usb.h:88
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
bool configured
Definition: rp2040_usb.h:49
io_rw_32 * buffer_control
Definition: rp2040_usb.h:62
uint8_t interrupt_num
Definition: rp2040_usb.h:91
bool active
Definition: rp2040_usb.h:78
static TU_ATTR_ALWAYS_INLINE uint16_t tu_u32_low16(uint32_t ui32)
Definition: tusb_common.h:143
static TU_ATTR_ALWAYS_INLINE uint16_t tu_u32_high16(uint32_t ui32)
Definition: tusb_common.h:142
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_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_LOW
Definition: tusb_types.h:51
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
Definition: tusb_types.h:507
xfer_result_t
Definition: tusb_types.h:236
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
@ XFER_RESULT_STALLED
Definition: tusb_types.h:239
static TU_ATTR_ALWAYS_INLINE const char * tu_edpt_type_str(tusb_xfer_type_t t)
Definition: tusb_types.h:520
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
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_speed_t tuh_speed_get(uint8_t dev_addr)
Definition: usbh.c:309