Skip to content

Commit

Permalink
Fixed timing issues with tuh_task, keyboard host is now working again…
Browse files Browse the repository at this point in the history
…. Changed the Addon Manager slightly to introduce LoadUSBAddon() for handling add-ons.

There might be one more timing issue as USBHostManager::getInstance().start() could be a race condition? But we can mess with this on PRs.
  • Loading branch information
arntsonl committed Aug 13, 2023
1 parent 32236d1 commit 5388646
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 71 deletions.
5 changes: 3 additions & 2 deletions headers/addonmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
#define _ADDONMANAGER_H_

#include "gpaddon.h"
#include "usbaddon.h"

#include <vector>
#include <pico/mutex.h>

enum ADDON_PROCESS {
CORE0_INPUT,
CORE0_USBREPORT,
CORE0_LOOP,
CORE1_LOOP
};

Expand All @@ -22,7 +22,8 @@ class AddonManager {
public:
AddonManager() {}
~AddonManager() {}
bool LoadAddon(GPAddon*, ADDON_PROCESS);
void LoadAddon(GPAddon*, ADDON_PROCESS);
void LoadUSBAddon(USBAddon*, ADDON_PROCESS);
void PreprocessAddons(ADDON_PROCESS);
void ProcessAddons(ADDON_PROCESS);
GPAddon * GetAddon(std::string); // hack for NeoPicoLED
Expand Down
3 changes: 2 additions & 1 deletion headers/addons/keyboard_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class KeyboardHostAddon : public USBAddon {
public:
virtual bool available();
virtual void setup(); // KeyboardHost Setup
virtual void process() {} // KeyboardHost Process
virtual void process() {} // KeyboardHost Process
virtual void preprocess();
virtual std::string name() { return KeyboardHostName; }
// USB Add-on Features
Expand All @@ -51,6 +51,7 @@ class KeyboardHostAddon : public USBAddon {
virtual void get_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {}
private:
bool _keyboard_host_enabled;
uint8_t getKeycodeFromModifier(uint8_t modifier);
void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report);
GamepadState _keyboard_host_state;
KeyboardButtonMapping _keyboard_host_mapDpadUp;
Expand Down
8 changes: 7 additions & 1 deletion headers/addons/pspassthrough.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ class PSPassthroughAddon : public USBAddon {
virtual void get_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual void report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {}
private:
bool ps_device_mounted = false;
uint8_t ps_dev_addr;
uint8_t ps_instance;
int8_t nonce_page;
PS4State passthrough_state;
int8_t send_nonce_part;
uint8_t report_buffer[64];
bool awaiting_cb;
};

#endif // _PSPassthrough_H_
9 changes: 7 additions & 2 deletions headers/usbhostmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class USBHostManager {
static USBHostManager instance; // Guaranteed to be destroyed. // Instantiated on first use.
return instance;
}
void init(uint8_t);
void setDataPin(uint8_t); // start USB host (change CPU, setup PIO PICO usb pin)
void start();
void pushAddon(USBAddon *); // If anything needs to update in the gpconfig driver
void process();
void hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len);
Expand All @@ -26,9 +27,13 @@ class USBHostManager {
void hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
private:
USBHostManager() {}
USBHostManager() : tuh_ready(false) {

}
std::vector<USBAddon*> addons;
usb_device_t *usb_device;
uint8_t dataPin;
bool tuh_ready;
};

#endif
22 changes: 17 additions & 5 deletions src/addonmanager.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
#include "addonmanager.h"
#include "usbhostmanager.h"

bool AddonManager::LoadAddon(GPAddon* addon, ADDON_PROCESS processAt) {
void AddonManager::LoadAddon(GPAddon* addon, ADDON_PROCESS processAt) {
if (addon->available()) {
AddonBlock * block = new AddonBlock;
addon->setup();
block->ptr = addon;
block->process = processAt;
addons.push_back(block);
return true;
}
delete addon; // Don't use the memory if we don't have to
return false;
} else {
delete addon; // Don't use the memory if we don't have to
}
}

void AddonManager::LoadUSBAddon(USBAddon* addon, ADDON_PROCESS processAt) {
if (addon->available()) {
AddonBlock * block = new AddonBlock;
addon->setup();
block->ptr = addon;
block->process = processAt;
addons.push_back(block);
USBHostManager::getInstance().pushAddon(addon);
} else {
delete addon; // Don't use the memory if we don't have to
}
}

void AddonManager::PreprocessAddons(ADDON_PROCESS processType) {
// Loop through all addons and process any that match our type
Expand Down
19 changes: 6 additions & 13 deletions src/addons/keyboard_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
#include "storagemanager.h"
#include "usbhostmanager.h"

#include "pio_usb.h"

bool KeyboardHostAddon::available() {
const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions;
const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions;
return keyboardHostOptions.enabled &&
isValidPin(keyboardHostOptions.pinDplus) &&
(keyboardHostOptions.pin5V == -1 || isValidPin(keyboardHostOptions.pin5V));
Expand All @@ -16,13 +14,13 @@ void KeyboardHostAddon::setup() {
const KeyboardMapping& keyboardMapping = keyboardHostOptions.mapping;

if (keyboardHostOptions.pin5V != -1) {
const int32_t pin5V = keyboardHostOptions.pin5V;
const int32_t pin5V = keyboardHostOptions.pin5V;
gpio_init(pin5V);
gpio_set_dir(pin5V, GPIO_IN);
gpio_pull_up(pin5V);
}

USBHostManager::getInstance().init((uint8_t)keyboardHostOptions.pinDplus);
USBHostManager::getInstance().setDataPin((uint8_t)keyboardHostOptions.pinDplus);

_keyboard_host_enabled = false;
_keyboard_host_mapDpadUp.setMask(GAMEPAD_MASK_UP);
Expand Down Expand Up @@ -76,14 +74,11 @@ void KeyboardHostAddon::preprocess() {
}

void KeyboardHostAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) {
if ( _keyboard_host_enabled == false )
return; // do nothing if our add-on is not enabled
_keyboard_host_enabled = true;
}

void KeyboardHostAddon::unmount(uint8_t dev_addr) {
if ( _keyboard_host_enabled == true )
_keyboard_host_enabled = false;
_keyboard_host_enabled = false;
}

void KeyboardHostAddon::report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len){
Expand All @@ -100,7 +95,7 @@ void KeyboardHostAddon::report_received(uint8_t dev_addr, uint8_t instance, uint
process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report );
}

uint8_t getKeycodeFromModifier(uint8_t modifier) {
uint8_t KeyboardHostAddon::getKeycodeFromModifier(uint8_t modifier) {
switch (modifier) {
case KEYBOARD_MODIFIER_LEFTCTRL : return HID_KEY_CONTROL_LEFT ;
case KEYBOARD_MODIFIER_LEFTSHIFT : return HID_KEY_SHIFT_LEFT ;
Expand All @@ -118,8 +113,6 @@ uint8_t getKeycodeFromModifier(uint8_t modifier) {
// convert hid keycode to ascii and print via usb device CDC (ignore non-printable)
void KeyboardHostAddon::process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report)
{
(void) dev_addr;

_keyboard_host_state.dpad = 0;
_keyboard_host_state.buttons = 0;
_keyboard_host_state.lx = GAMEPAD_JOYSTICK_MID;
Expand Down Expand Up @@ -168,4 +161,4 @@ void KeyboardHostAddon::process_kbd_report(uint8_t dev_addr, hid_keyboard_report
_keyboard_host_state.rt = 0;
}
}
}
}
25 changes: 1 addition & 24 deletions src/addons/pspassthrough.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,7 @@

#include "CRC32.h"

#include "pio_usb.h"

// Data passed between PS Passthrough and TinyUSB Host callbacks
static uint8_t ps_dev_addr = 0;
static uint8_t ps_instance = 0;
static tusb_desc_device_t desc_device;
static int8_t nonce_page;
static PS4State passthrough_state;
static int8_t send_nonce_part;
static uint8_t report_buffer[64];
static bool awaiting_cb;

bool PSPassthroughAddon::available() {
const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions;
Expand All @@ -32,7 +22,7 @@ void PSPassthroughAddon::setup() {
gpio_pull_up(pin5V);
}

USBHostManager::getInstance().init((uint8_t)psOptions.pinDplus);
USBHostManager::getInstance().setDataPin((uint8_t)psOptions.pinDplus);

nonce_page = 0; // no nonce yet
send_nonce_part = 0; // which part of the nonce are we getting from send?
Expand Down Expand Up @@ -100,7 +90,6 @@ void PSPassthroughAddon::process() {
case PS4State::sending_nonce:
if ( !awaiting_cb ) {
uint8_t nonce_buffer[64];
uint32_t crc32;
nonce_buffer[0] = PS4AuthReport::PS4_GET_SIGNATURE_NONCE;
nonce_buffer[1] = PS4Data::getInstance().nonce_id; // nonce_id
nonce_buffer[2] = send_nonce_part; // next_part
Expand All @@ -119,7 +108,6 @@ void PSPassthroughAddon::process() {
void PSPassthroughAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) {
ps_dev_addr = dev_addr;
ps_instance = instance;
ps_device_mounted = true;

// Reset as soon as its connected
memset(report_buffer, 0, sizeof(report_buffer));
Expand All @@ -131,7 +119,6 @@ void PSPassthroughAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const
}

void PSPassthroughAddon::unmount(uint8_t dev_addr) {
ps_device_mounted = false;
nonce_page = 0; // no nonce yet
send_nonce_part = 0; // which part of the nonce are we getting from send?
awaiting_cb = false; // did we receive the sign state yet
Expand All @@ -141,7 +128,6 @@ void PSPassthroughAddon::unmount(uint8_t dev_addr) {
void PSPassthroughAddon::set_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {
switch(report_id) {
case PS4AuthReport::PS4_SET_AUTH_PAYLOAD:
printf("Set Auth Payload\r\n");
if (nonce_page == 5) {
nonce_page = 0;
passthrough_state = PS4State::signed_nonce_ready;
Expand All @@ -156,25 +142,16 @@ void PSPassthroughAddon::set_report_complete(uint8_t dev_addr, uint8_t instance,
void PSPassthroughAddon::get_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {
switch(report_id) {
case PS4AuthReport::PS4_DEFINITION:
printf("Get Definition: ");
for (uint8_t i = 0; i < 48; i++) {
printf("%02x,", report_buffer[i]); }
printf("\r\n");
if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready)
passthrough_state = PS4State::receiving_nonce;
break;
case PS4AuthReport::PS4_RESET_AUTH:
printf("Reset Auth!\r\n");
if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready)
passthrough_state = PS4State::receiving_nonce;
break;
case PS4AuthReport::PS4_GET_SIGNING_STATE:
printf("Get signing state!\r\n");
if (report_buffer[2] == 0)
passthrough_state = PS4State::sending_nonce;
break;
case PS4AuthReport::PS4_GET_SIGNATURE_NONCE:
printf("Get signature nonce!\r\n");
memcpy(&PS4Data::getInstance().ps4_auth_buffer[(send_nonce_part-1)*56], &report_buffer[4], 56);
if (send_nonce_part == 19) { // 0 = ready, 16 = not ready
send_nonce_part = 0;
Expand Down
12 changes: 3 additions & 9 deletions src/gp2040.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,11 @@ void GP2040::setup() {
break;
}
}

// Initialize our ADC (various add-ons)
adc_init();

// Setup USB Host Add-ons
KeyboardHostAddon * keyboardHostAddon = new KeyboardHostAddon();
if( addons.LoadAddon(keyboardHostAddon, CORE0_INPUT) )
USBHostManager::getInstance().pushAddon(keyboardHostAddon);
// Setup USB add-ons
addons.LoadUSBAddon(new KeyboardHostAddon(), CORE0_INPUT);

// Setup Regular Add-ons
addons.LoadAddon(new AnalogInput(), CORE0_INPUT);
Expand Down Expand Up @@ -146,7 +143,7 @@ void GP2040::run() {

// We can't send faster than USB can poll
if (nextRuntime > getMicro()) { // fix for unsigned
//sleep_us(50); // Give some time back to our CPU (lower power consumption)
sleep_us(50); // Give some time back to our CPU (lower power consumption)
continue;
}

Expand Down Expand Up @@ -179,9 +176,6 @@ void GP2040::run() {

tud_task(); // TinyUSB Task update

// Process Loops
addons.ProcessAddons(ADDON_PROCESS::CORE0_LOOP);

nextRuntime = getMicro() + GAMEPAD_POLL_MICRO;
}
}
Expand Down
10 changes: 6 additions & 4 deletions src/gp2040aux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ GP2040Aux::~GP2040Aux() {
}

void GP2040Aux::setup() {
// Setup USB add-ons
addons.LoadUSBAddon(new PSPassthroughAddon(), CORE1_LOOP);

// Setup Regular Add-ons
addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP);
addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP);
Expand All @@ -33,10 +36,9 @@ void GP2040Aux::setup() {
addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP);
addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP);

// Setup USB add-ons
PSPassthroughAddon * psPassthroughAddon = new PSPassthroughAddon();
if( addons.LoadAddon(psPassthroughAddon, CORE1_LOOP) )
USBHostManager::getInstance().pushAddon(psPassthroughAddon);


USBHostManager::getInstance().start();
}

void GP2040Aux::run() {
Expand Down
27 changes: 17 additions & 10 deletions src/usbhostmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
#include "tusb.h"
#include "host/usbh_classdriver.h"

void USBHostManager::init(uint8_t dataPin) {
set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues

pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.alarm_pool = (void*)alarm_pool_create(2, 1); // Alarms go to Core1
pio_cfg.pin_dp = dataPin;
tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);
tuh_init(BOARD_TUH_RHPORT);
void USBHostManager::setDataPin(uint8_t inPin) {
dataPin = inPin;
}

void USBHostManager::start() {
if ( !addons.empty() ) {
set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues
//stdio_init_all();
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.alarm_pool = (void*)alarm_pool_create(2, 1); // Alarms go to Core1
pio_cfg.pin_dp = dataPin;
tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);
tuh_init(BOARD_TUH_RHPORT);
tuh_ready = true;
}
}

void USBHostManager::pushAddon(USBAddon * usbAddon) { // If anything needs to update in the gpconfig driver
Expand All @@ -20,7 +27,7 @@ void USBHostManager::pushAddon(USBAddon * usbAddon) { // If anything needs to up

// Host manager should call tuh_task as fast as possible
void USBHostManager::process() {
if ( !addons.empty() ){
if ( tuh_ready ){
tuh_task();
}
}
Expand All @@ -33,7 +40,7 @@ void USBHostManager::hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t co

void USBHostManager::hid_umount_cb(uint8_t daddr, uint8_t instance) {
for( std::vector<USBAddon*>::iterator it = addons.begin(); it != addons.end(); it++ ){
(*it)->unmount(daddr);
(*it)->unmount(dev_addr);
}
}

Expand Down

0 comments on commit 5388646

Please sign in to comment.