Open FFBoard
Open source force feedback firmware
hcd_pio_usb.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2021 Ha Thach (tinyusb.org)
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_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && CFG_TUH_RPI_PIO_USB
30
31#include "pico.h"
32#include "pio_usb.h"
33#include "pio_usb_ll.h"
34
35//--------------------------------------------------------------------+
36// INCLUDE
37//--------------------------------------------------------------------+
38#include "osal/osal.h"
39
40#include "host/hcd.h"
41#include "host/usbh.h"
42
43#define RHPORT_OFFSET 1
44#define RHPORT_PIO(_x) ((_x)-RHPORT_OFFSET)
45
46static pio_usb_configuration_t pio_host_cfg = PIO_USB_DEFAULT_CONFIG;
47
48//--------------------------------------------------------------------+
49// HCD API
50//--------------------------------------------------------------------+
51bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) {
52 (void) rhport;
53 TU_VERIFY(cfg_id == TUH_CFGID_RPI_PIO_USB_CONFIGURATION);
54 memcpy(&pio_host_cfg, cfg_param, sizeof(pio_usb_configuration_t));
55 return true;
56}
57
58bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
59 (void) rhport;
60 (void) rh_init;
61
62 // To run USB SOF interrupt in core1, call this init in core1
63 pio_usb_host_init(&pio_host_cfg);
64
65 return true;
66}
67
68void hcd_port_reset(uint8_t rhport) {
69 uint8_t const pio_rhport = RHPORT_PIO(rhport);
70 pio_usb_host_port_reset_start(pio_rhport);
71}
72
73void hcd_port_reset_end(uint8_t rhport) {
74 uint8_t const pio_rhport = RHPORT_PIO(rhport);
75 pio_usb_host_port_reset_end(pio_rhport);
76}
77
78bool hcd_port_connect_status(uint8_t rhport) {
79 uint8_t const pio_rhport = RHPORT_PIO(rhport);
80
81 root_port_t *root = PIO_USB_ROOT_PORT(pio_rhport);
82 port_pin_status_t line_state = pio_usb_bus_get_line_state(root);
83
84 return line_state != PORT_PIN_SE0;
85}
86
88 // TODO determine link speed
89 uint8_t const pio_rhport = RHPORT_PIO(rhport);
90 return PIO_USB_ROOT_PORT(pio_rhport)->is_fullspeed ? TUSB_SPEED_FULL : TUSB_SPEED_LOW;
91}
92
93// Close all opened endpoint belong to this device
94void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
95 uint8_t const pio_rhport = RHPORT_PIO(rhport);
96 pio_usb_host_close_device(pio_rhport, dev_addr);
97}
98
99uint32_t hcd_frame_number(uint8_t rhport) {
100 (void) rhport;
101 return pio_usb_host_get_frame_number();
102}
103
104void hcd_int_enable(uint8_t rhport) {
105 (void) rhport;
106}
107
108void hcd_int_disable(uint8_t rhport) {
109 (void) rhport;
110}
111
112//--------------------------------------------------------------------+
113// Endpoint API
114//--------------------------------------------------------------------+
115
116bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep) {
117 hcd_devtree_info_t dev_tree;
118 hcd_devtree_get_info(dev_addr, &dev_tree);
119 bool const need_pre = (dev_tree.hub_addr && dev_tree.speed == TUSB_SPEED_LOW);
120
121 uint8_t const pio_rhport = RHPORT_PIO(rhport);
122 return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const *) desc_ep, need_pre);
123}
124
125bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) {
126 uint8_t const pio_rhport = RHPORT_PIO(rhport);
127 return pio_usb_host_endpoint_transfer(pio_rhport, dev_addr, ep_addr, buffer, buflen);
128}
129
130bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
131 uint8_t const pio_rhport = RHPORT_PIO(rhport);
132 return pio_usb_host_endpoint_abort_transfer(pio_rhport, dev_addr, ep_addr);
133}
134
135bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
136 uint8_t const pio_rhport = RHPORT_PIO(rhport);
137 return pio_usb_host_send_setup(pio_rhport, dev_addr, setup_packet);
138}
139
140//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
141//{
142// // EPX is shared, so multiple device addresses and endpoint addresses share that
143// // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own
144// // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint
145// // on that device
146// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\r\n", dev_addr, ep_addr);
147// struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
148// assert(ep);
149// bool busy = ep->active;
150// pico_trace("busy == %d\r\n", busy);
151// return busy;
152//}
153
154bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
155 (void) rhport;
156 (void) dev_addr;
157 (void) ep_addr;
158
159 return true;
160}
161
162static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t *rport, xfer_result_t result,
163 volatile uint32_t *ep_reg) {
164 (void) rport;
165 const uint32_t ep_all = *ep_reg;
166
167 for ( uint8_t ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++ ) {
168 uint32_t const mask = (1u << ep_idx);
169
170 if ( ep_all & mask ) {
171 endpoint_t * ep = PIO_USB_ENDPOINT(ep_idx);
172 hcd_event_xfer_complete(ep->dev_addr, ep->ep_num, ep->actual_len, result, true);
173 }
174 }
175
176 // clear all
177 (*ep_reg) &= ~ep_all;
178}
179
180// IRQ Handler
181void __no_inline_not_in_flash_func(pio_usb_host_irq_handler)(uint8_t root_id) {
182 uint8_t const tu_rhport = root_id + 1;
183 root_port_t *rport = PIO_USB_ROOT_PORT(root_id);
184 uint32_t const ints = rport->ints;
185
186 if ( ints & PIO_USB_INTS_ENDPOINT_COMPLETE_BITS ) {
187 handle_endpoint_irq(rport, XFER_RESULT_SUCCESS, &rport->ep_complete);
188 }
189
190 if ( ints & PIO_USB_INTS_ENDPOINT_STALLED_BITS ) {
191 handle_endpoint_irq(rport, XFER_RESULT_STALLED, &rport->ep_stalled);
192 }
193
194 if ( ints & PIO_USB_INTS_ENDPOINT_ERROR_BITS ) {
195 handle_endpoint_irq(rport, XFER_RESULT_FAILED, &rport->ep_error);
196 }
197
198 if ( ints & PIO_USB_INTS_CONNECT_BITS ) {
199 hcd_event_device_attach(tu_rhport, true);
200 }
201
202 if ( ints & PIO_USB_INTS_DISCONNECT_BITS ) {
203 hcd_event_device_remove(tu_rhport, true);
204 }
205
206 // clear all
207 rport->ints &= ~ints;
208}
209
210#endif
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
void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t *devtree_info)
Definition: usbh.c:949
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
Definition: hcd_pio_usb.c:135
void __no_inline_not_in_flash_func() pio_usb_host_irq_handler(uint8_t root_id)
Definition: hcd_pio_usb.c:181
static void __no_inline_not_in_flash_func() handle_endpoint_irq(root_port_t *rport, xfer_result_t result, volatile uint32_t *ep_reg)
Definition: hcd_pio_usb.c:162
void hcd_int_disable(uint8_t rhport)
Definition: hcd_pio_usb.c:108
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param)
Definition: hcd_pio_usb.c:51
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_pio_usb.c:154
void hcd_int_enable(uint8_t rhport)
Definition: hcd_pio_usb.c:104
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
Definition: hcd_pio_usb.c:125
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
Definition: hcd_pio_usb.c:94
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_pio_usb.c:130
void hcd_port_reset_end(uint8_t rhport)
Definition: hcd_pio_usb.c:73
void hcd_port_reset(uint8_t rhport)
Definition: hcd_pio_usb.c:68
bool hcd_port_connect_status(uint8_t rhport)
Definition: hcd_pio_usb.c:78
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep)
Definition: hcd_pio_usb.c:116
uint32_t hcd_frame_number(uint8_t rhport)
Definition: hcd_pio_usb.c:99
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
Definition: hcd_pio_usb.c:87
static pio_usb_configuration_t pio_host_cfg
Definition: hcd_pio_usb.c:46
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: hcd_pio_usb.c:58
static TU_ATTR_ALWAYS_INLINE bool need_pre(uint8_t dev_addr)
Definition: hcd_rp2040.c:84
uint8_t const * buffer
Definition: midi_device.h:100
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint8_t hub_addr
Definition: hcd.h:95
uint8_t speed
Definition: hcd.h:97
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
xfer_result_t
Definition: tusb_types.h:236
@ XFER_RESULT_FAILED
Definition: tusb_types.h:238
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
@ XFER_RESULT_STALLED
Definition: tusb_types.h:239
@ TUH_CFGID_RPI_PIO_USB_CONFIGURATION
Definition: usbh.h:79