fix(native-usb): isolate two-pair transport and hand off read status in IRQ
This commit is contained in:
parent
c26ea25f93
commit
9f8678af96
51 changed files with 8159 additions and 815 deletions
|
|
@ -1,4 +1,7 @@
|
|||
#include "hardware_stub.h"
|
||||
#include <stdlib.h>
|
||||
static uint32_t native_test_time_us = 1000000u;
|
||||
#define time_us_32() native_test_time_us
|
||||
#include "usb/native_hub/native_hub.c"
|
||||
|
||||
usb_hw_t native_test_usb;
|
||||
|
|
@ -6,6 +9,10 @@ usb_device_dpram_t native_test_dpram;
|
|||
sio_hw_t native_test_sio;
|
||||
bool native_test_abort_stuck;
|
||||
uint32_t native_test_interrupt_mask;
|
||||
uint32_t native_test_hid_completions[CHILDREN], native_test_bulk_completions[CHILDREN];
|
||||
uint32_t native_test_received_count[CHILDREN][2];
|
||||
uint16_t native_test_received_length[CHILDREN][2];
|
||||
uint8_t native_test_received_data[CHILDREN][2][PACKET];
|
||||
static bool servicing_interrupt;
|
||||
|
||||
void native_test_service_interrupt(void) {
|
||||
|
|
@ -22,7 +29,9 @@ void probe_router_publish(const uint8_t values[PROBE_ROUTER_SLOTS], uint8_t slot
|
|||
void probe_router_enable(bool enabled) { (void)enabled; }
|
||||
bool probe_router_set_phase(uint32_t phase) { (void)phase; return true; }
|
||||
void probe_router_snapshot(probe_router_stats* snapshot) { memset(snapshot,0,sizeof(*snapshot)); snapshot->ready = 1; }
|
||||
#ifndef NATIVE_TEST_EXTERNAL_LOG
|
||||
int probe_debug_printf(const char* format, ...) { (void)format; return 0; }
|
||||
#endif
|
||||
|
||||
const uint8_t* native_joycon_device_descriptor(uint8_t instance) { (void)instance; return hub_device; }
|
||||
const uint8_t* native_joycon_configuration_descriptor(uint8_t instance) { (void)instance; return hub_configuration; }
|
||||
|
|
@ -35,32 +44,66 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t id, hid_report_type_t t
|
|||
(void)instance; (void)id; (void)type; (void)data; (void)length; return 0;
|
||||
}
|
||||
void tud_hid_set_report_cb(uint8_t instance, uint8_t id, hid_report_type_t type, const uint8_t* data, uint16_t length) {
|
||||
(void)instance; (void)id; (void)type; (void)data; (void)length;
|
||||
(void)id; (void)type;
|
||||
if (instance >= CHILDREN || length > PACKET) abort();
|
||||
++native_test_received_count[instance][0];
|
||||
native_test_received_length[instance][0] = length;
|
||||
if (length) memcpy(native_test_received_data[instance][0],data,length);
|
||||
}
|
||||
void tud_hid_report_complete_cb(uint8_t instance, const uint8_t* data, uint16_t length) {
|
||||
(void)data; (void)length;
|
||||
if (instance >= CHILDREN) abort();
|
||||
++native_test_hid_completions[instance];
|
||||
}
|
||||
void tud_vendor_rx_cb(uint8_t instance, const uint8_t* data, uint16_t length) {
|
||||
if (instance >= CHILDREN || length > PACKET) abort();
|
||||
++native_test_received_count[instance][1];
|
||||
native_test_received_length[instance][1] = length;
|
||||
if (length) memcpy(native_test_received_data[instance][1],data,length);
|
||||
}
|
||||
void tud_vendor_tx_cb(uint8_t instance, uint32_t length) {
|
||||
(void)length;
|
||||
if (instance >= CHILDREN) abort();
|
||||
++native_test_bulk_completions[instance];
|
||||
}
|
||||
void tud_hid_report_complete_cb(uint8_t instance, const uint8_t* data, uint16_t length) { (void)instance; (void)data; (void)length; }
|
||||
void tud_vendor_rx_cb(uint8_t instance, const uint8_t* data, uint16_t length) { (void)instance; (void)data; (void)length; }
|
||||
void tud_vendor_tx_cb(uint8_t instance, uint32_t length) { (void)instance; (void)length; }
|
||||
|
||||
void native_test_initialize(void) {
|
||||
memset(devices,0,sizeof(devices));
|
||||
memset(ports,0,sizeof(ports));
|
||||
memset(usb_hw,0,sizeof(*usb_hw));
|
||||
memset(usb_dpram,0,sizeof(*usb_dpram));
|
||||
memset(native_test_hid_completions,0,sizeof(native_test_hid_completions));
|
||||
memset(native_test_bulk_completions,0,sizeof(native_test_bulk_completions));
|
||||
memset(native_test_received_count,0,sizeof(native_test_received_count));
|
||||
memset(native_test_received_length,0,sizeof(native_test_received_length));
|
||||
memset(native_test_received_data,0,sizeof(native_test_received_data));
|
||||
native_test_time_us = 1000000u;
|
||||
event_head = event_tail = 0;
|
||||
native_test_abort_stuck = false;
|
||||
native_test_interrupt_mask = 0;
|
||||
servicing_interrupt = false;
|
||||
failed = bus_suspended = bank_restore_pending = false;
|
||||
failed = bus_suspended = false;
|
||||
bank_lock = spin_lock_instance(0);
|
||||
active_device = default_device = 0;
|
||||
addresses[0] = 0; addresses[1] = 1; addresses[2] = 2;
|
||||
addresses[0] = 0;
|
||||
for (unsigned slot = 1; slot < DEVICES; ++slot) addresses[slot] = slot * 17u;
|
||||
started = root_configured_once = true;
|
||||
}
|
||||
|
||||
bool native_test_startup(void) {
|
||||
native_test_initialize();
|
||||
started = root_configured_once = false;
|
||||
return native_hub_init();
|
||||
}
|
||||
|
||||
void native_test_advance(uint32_t microseconds) {
|
||||
native_test_time_us += microseconds;
|
||||
native_hub_task();
|
||||
}
|
||||
|
||||
static bool select_slot(uint8_t slot) {
|
||||
if (!native_hub_select_device(addresses[slot],slot,UINT32_MAX / 2)) return false;
|
||||
restore_selected_bank();
|
||||
return true;
|
||||
if (slot >= DEVICES || addresses[slot] == NONE) return false;
|
||||
return native_hub_select_device(addresses[slot],slot,UINT32_MAX / 2);
|
||||
}
|
||||
|
||||
bool native_test_select(uint8_t slot) { return select_slot(slot); }
|
||||
|
|
@ -111,22 +154,42 @@ bool native_test_in(uint8_t slot, uint8_t* data, uint16_t* length, bool drain) {
|
|||
}
|
||||
|
||||
bool native_test_private_in(uint8_t slot, uint8_t endpoint, uint8_t* data, uint16_t* length) {
|
||||
if (slot < 1 || slot > 2 || (endpoint != 0x81 && endpoint != 0x82)) return false;
|
||||
if (slot >= DEVICES || addresses[slot] == NONE || (slot == 0 ? endpoint != 0x8f :
|
||||
(endpoint != 0x81 && endpoint != 0x82))) return false;
|
||||
// A host token selects the bank, but cannot wait for a foreground task.
|
||||
if (!native_hub_select_device(addresses[slot],slot,UINT32_MAX / 2)) return false;
|
||||
unsigned channel = (endpoint & 15u) * 2u;
|
||||
uint32_t control = endpoint_regs()[channel - 2u];
|
||||
uint32_t value = buffer_regs()[channel];
|
||||
unsigned channel = logical_channel(slot,endpoint);
|
||||
unsigned physical = physical_channel(slot,channel);
|
||||
uint32_t control = slot == 0 ? usb_dpram->ep_ctrl[14].in : endpoint_regs()[channel - 2u];
|
||||
uint32_t value = buffer_regs()[physical];
|
||||
if (!(control & EP_CTRL_ENABLE_BITS) || !(value & USB_BUF_CTRL_AVAIL) ||
|
||||
!(value & USB_BUF_CTRL_FULL) || (value & USB_BUF_CTRL_STALL)) return false;
|
||||
*length = value & USB_BUF_CTRL_LEN_MASK;
|
||||
if (*length > PACKET) return false;
|
||||
if (*length) copy_from_usb(data,
|
||||
(const volatile uint8_t*)USBCTRL_DPRAM_BASE + (control & 0xffffu), *length);
|
||||
buffer_regs()[channel] = value & ~USB_BUF_CTRL_AVAIL;
|
||||
buffer_regs()[physical] = value & ~USB_BUF_CTRL_AVAIL;
|
||||
usb_hw->buf_status |= 1u << physical;
|
||||
usb_hw->ints |= USB_INTS_BUFF_STATUS_BITS;
|
||||
native_test_service_interrupt();
|
||||
return !failed;
|
||||
}
|
||||
|
||||
bool native_test_private_out(uint8_t slot, uint8_t endpoint, const uint8_t* data, uint16_t length, bool drain) {
|
||||
if (slot < 1 || slot >= DEVICES || addresses[slot] == NONE ||
|
||||
(endpoint != 0x01 && endpoint != 0x02) || length > PACKET) return false;
|
||||
if (!native_hub_select_device(addresses[slot],slot,UINT32_MAX / 2)) return false;
|
||||
unsigned channel = logical_channel(slot,endpoint);
|
||||
uint32_t control = endpoint_regs()[channel - 2u];
|
||||
uint32_t value = buffer_regs()[channel];
|
||||
if (!(control & EP_CTRL_ENABLE_BITS) || !(value & USB_BUF_CTRL_AVAIL) ||
|
||||
(value & USB_BUF_CTRL_STALL)) return false;
|
||||
if (length) copy_to_usb((volatile uint8_t*)USBCTRL_DPRAM_BASE + (control & 0xffffu),data,length);
|
||||
buffer_regs()[channel] = (value & ~(USB_BUF_CTRL_AVAIL | USB_BUF_CTRL_LEN_MASK)) | length;
|
||||
usb_hw->buf_status |= 1u << channel;
|
||||
usb_hw->ints |= USB_INTS_BUFF_STATUS_BITS;
|
||||
native_test_service_interrupt();
|
||||
if (drain) native_hub_task();
|
||||
return !failed;
|
||||
}
|
||||
|
||||
|
|
@ -136,5 +199,6 @@ void native_test_bus_reset(bool drain) {
|
|||
native_test_service_interrupt();
|
||||
if (drain) native_hub_task();
|
||||
// Assign fixture addresses after reset, independently of EP0 state.
|
||||
addresses[0] = 0; addresses[1] = 1; addresses[2] = 2;
|
||||
addresses[0] = 0;
|
||||
for (unsigned slot = 1; slot < DEVICES; ++slot) addresses[slot] = slot * 17u;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue