From de315f83527c1407dd0a1e8e43c3966f8ec64111 Mon Sep 17 00:00:00 2001 From: Luke A Date: Wed, 9 Aug 2023 11:37:14 -0400 Subject: [PATCH 01/24] Initial working version of PS pass-through. This will require some reworking on our USB Host code. --- CMakeLists.txt | 1 + headers/addons/pspassthrough.h | 37 +++++ lib/TinyUSB_Gamepad/src/ps4_driver.cpp | 9 +- lib/TinyUSB_Gamepad/src/ps4_driver.h | 6 +- proto/config.proto | 8 + src/addons/keyboard_host.cpp | 13 +- src/addons/pspassthrough.cpp | 212 +++++++++++++++++++++++++ src/config_utils.cpp | 6 + src/configs/webconfig.cpp | 10 ++ src/gp2040.cpp | 2 +- src/gp2040aux.cpp | 2 + www/server/app.js | 3 + www/src/Locales/en/AddonsConfig.jsx | 5 + www/src/Pages/AddonsConfigPage.jsx | 53 +++++++ 14 files changed, 357 insertions(+), 10 deletions(-) create mode 100644 headers/addons/pspassthrough.h create mode 100644 src/addons/pspassthrough.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 63b08010d..929b506f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ src/addons/neopicoleds.cpp src/addons/playernum.cpp src/addons/playerleds.cpp src/addons/ps4mode.cpp +src/addons/pspassthrough.cpp src/addons/reverse.cpp src/addons/turbo.cpp src/addons/slider_socd.cpp diff --git a/headers/addons/pspassthrough.h b/headers/addons/pspassthrough.h new file mode 100644 index 000000000..19fff0dba --- /dev/null +++ b/headers/addons/pspassthrough.h @@ -0,0 +1,37 @@ +#ifndef _PSPassthrough_H +#define _PSPassthrough_H + +#include "gpaddon.h" + +#include "ps4_driver.h" + +#ifndef PSPASSTHROUGH_ENABLED +#define PSPASSTHROUGH_ENABLED 1 +#endif + +#ifndef PPSPASSTHROUGH_PIN_DPLUS +#define PSPASSTHROUGH_PIN_DPLUS 16 +#endif + +#ifndef PSPASSTHROUGH_PIN_5V +#define PSPASSTHROUGH_PIN_5V 18 +#endif + +#ifndef PSPASSTHROUGH_DEBUG +#define PSPASSTHROUGH_DEBUG true +#endif + +// KeyboardHost Module Name +#define PSPassthroughName "PSPassthrough" + +class PSPassthroughAddon : public GPAddon { +public: + virtual bool available(); + virtual void setup(); // PSPassthrough Setup + virtual void process(); // PSPassthrough Process + virtual void preprocess() {} + virtual std::string name() { return PSPassthroughName; } +private: +}; + +#endif // _PSPassthrough_H_ \ No newline at end of file diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp index a75235e80..8b7da201f 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp @@ -17,9 +17,9 @@ uint8_t ps4_endpoint_in = 0; uint8_t ps4_endpoint_out = 0; uint8_t ps4_out_buffer[PS4_OUT_SIZE] = {}; -// Alternative version +// Alternative version, do we want to use 0x07 for PS5 mode? static constexpr uint8_t output_0x03[] = { - 0x21, 0x27, 0x04, 0xcf, 0x00, 0x2c, 0x56, + 0x21, 0x27, 0x04, 0xcf, 0x07, 0x2c, 0x56, 0x08, 0x00, 0x3d, 0x00, 0xe8, 0x03, 0x04, 0x00, 0xff, 0x7f, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -63,8 +63,8 @@ ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen) uint32_t crc32; ps4_out_buffer[0] = report_id; switch(report_id) { - // Not sure on 0x03? maybe a controller qualifier - case PS4AuthReport::PS4_UNKNOWN_0X03: + // Controller Definition Report + case PS4AuthReport::PS4_DEFINITION: if (reqlen != sizeof(output_0x03)) { return -1; } @@ -147,6 +147,7 @@ void set_ps4_report(uint8_t report_id, uint8_t const * data, uint16_t reqlen) if ( nonce_page == 4 ) { // Copy/append data from buffer[4:64-28] into our nonce noncelen = 32; // from 4 to 64 - 24 - 4 + PS4Data::getInstance().nonce_id = nonce_id; // for pass-through only } else { // Copy/append data from buffer[4:64-4] into our nonce noncelen = 56; diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.h b/lib/TinyUSB_Gamepad/src/ps4_driver.h index 45064eae0..e39d6d3d9 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.h +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.h @@ -14,7 +14,7 @@ typedef enum { - PS4_UNKNOWN_0X03 = 0x03, // Unknown (PS4 Report 0x03) + PS4_DEFINITION = 0x03, // PS4 Controller Definition PS4_SET_AUTH_PAYLOAD = 0xF0, // Set Auth Payload PS4_GET_SIGNATURE_NONCE = 0xF1, // Get Signature Nonce PS4_GET_SIGNING_STATE = 0xF2, // Get Signing State @@ -34,7 +34,8 @@ typedef enum { no_nonce = 0, receiving_nonce = 1, nonce_ready = 2, - signed_nonce_ready = 3 + signed_nonce_ready = 3, + sending_nonce = 4 } PS4State; // Storage manager for board, LED options, and thread-safe settings @@ -51,6 +52,7 @@ class PS4Data { PS4State ps4State; bool authsent; uint8_t nonce_buffer[256]; + uint8_t nonce_id; // used in pass-through mode // Send back in 56 byte chunks: // 256 byte - nonce signature diff --git a/proto/config.proto b/proto/config.proto index 70b84a7fa..4f12b8287 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -420,6 +420,13 @@ message PS4Options optional bytes rsaRN = 12 [(nanopb).max_size = 256]; } +message PSPassthroughOptions +{ + optional bool enabled = 1; + optional int32 pinDplus = 2; + optional int32 pin5V = 3; +} + message WiiOptions { optional bool enabled = 1; @@ -475,6 +482,7 @@ message AddonOptions optional FocusModeOptions focusModeOptions = 16; optional KeyboardHostOptions keyboardHostOptions = 17; optional TiltOptions tiltOptions = 18; + optional PSPassthroughOptions psPassthroughOptions = 19; } message Config diff --git a/src/addons/keyboard_host.cpp b/src/addons/keyboard_host.cpp index 6fc2c87f7..b0a646ffc 100644 --- a/src/addons/keyboard_host.cpp +++ b/src/addons/keyboard_host.cpp @@ -43,7 +43,7 @@ void KeyboardHostAddon::setup() { if (keyboardHostOptions.pin5V != -1) { const int32_t pin5V = keyboardHostOptions.pin5V; gpio_init(pin5V); - gpio_set_dir(pin5V, GPIO_OUT); + gpio_set_dir(pin5V, GPIO_IN); gpio_pull_up(pin5V); } @@ -90,7 +90,7 @@ void KeyboardHostAddon::preprocess() { tuh_task(); } - +/* // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. @@ -98,6 +98,9 @@ void KeyboardHostAddon::preprocess() { // therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(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 + (void)desc_report; (void)desc_len; @@ -199,6 +202,9 @@ void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report) // Invoked when received report from device via interrupt endpoint void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { + if ( _keyboard_host_enabled == false ) + return; // do nothing if our add-on is not enabled + (void) len; uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); @@ -216,4 +222,5 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons { //Error: cannot request report } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp new file mode 100644 index 000000000..6c5664ffc --- /dev/null +++ b/src/addons/pspassthrough.cpp @@ -0,0 +1,212 @@ +#include "addons/pspassthrough.h" +#include "storagemanager.h" + +#include "pio_usb.h" +#include "tusb.h" +#include "host/usbh_classdriver.h" + +#include "CRC32.h" + +// Data passed between PS Passthrough and TinyUSB Host callbacks +static bool host_device_mounted = false; +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; + return psOptions.enabled && isValidPin(psOptions.pinDplus) && + (psOptions.pin5V == -1 || isValidPin(psOptions.pin5V)); +} + +void PSPassthroughAddon::setup() { + set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + + const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; + + if (psOptions.pin5V != -1) { // Feather USB-A's require this + const int32_t pin5V = psOptions.pin5V; + gpio_init(pin5V); + gpio_set_dir(pin5V, GPIO_IN); + gpio_pull_up(pin5V); + } + + pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; + pio_cfg.pin_dp = (uint8_t)psOptions.pinDplus; + tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); + tuh_init(BOARD_TUH_RHPORT); + + while((to_ms_since_boot(get_absolute_time()) < 2000)) { + if (host_device_mounted) + break; + tuh_task(); + } + + 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 + passthrough_state = PS4State::no_nonce; +} + +void PSPassthroughAddon::process() { + switch ( passthrough_state ) { + case PS4State::no_nonce: + // Did we get the nonce? Let's begin auth + if ( PS4Data::getInstance().ps4State == nonce_ready ) { + if ( !awaiting_cb ) { // Reset the device auth + uint8_t output_0xf3[] = { 0xf3, 0x0, 0x38, 0x38, 0, 0, 0, 0 }; + uint8_t* buf = report_buffer; + uint16_t len = sizeof(output_0xf3); + memcpy(buf, output_0xf3, len); + awaiting_cb = true; + tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_RESET_AUTH, HID_REPORT_TYPE_FEATURE, buf, len); + } + } + break; + case PS4State::receiving_nonce: + if ( !awaiting_cb ) { + uint8_t noncelen; + uint32_t crc32; + uint8_t nonce_buffer[64]; // [0xF0, ID, Page, 0, nonce(54 or 32 with 0 padding), CRC32 of data] + nonce_buffer[0] = PS4AuthReport::PS4_SET_AUTH_PAYLOAD; + nonce_buffer[1] = PS4Data::getInstance().nonce_id; + nonce_buffer[2] = nonce_page; + nonce_buffer[3] = 0; + if ( nonce_page == 4 ) { + noncelen = 32; // from 4 to 64 - 24 - 4 + memcpy(&nonce_buffer[4], &PS4Data::getInstance().nonce_buffer[nonce_page*56], noncelen); + memset(&nonce_buffer[4+noncelen], 0, 24); // zero padding + } else { + noncelen = 56; + memcpy(&nonce_buffer[4], &PS4Data::getInstance().nonce_buffer[nonce_page*56], noncelen); + + } + nonce_page++; + crc32 = CRC32::calculate(nonce_buffer, 60); + memcpy(&nonce_buffer[60], &crc32, sizeof(uint32_t)); + uint8_t* buf = report_buffer; + uint16_t len = sizeof(nonce_buffer); + memcpy(buf, nonce_buffer, len); + awaiting_cb = true; + tuh_hid_set_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_SET_AUTH_PAYLOAD, HID_REPORT_TYPE_FEATURE, buf, len); + } + break; + case PS4State::signed_nonce_ready: + if ( !awaiting_cb ) { // Get Auth State + uint8_t state_buffer[16]; + memset(state_buffer, 0, 16); + state_buffer[0] = PS4AuthReport::PS4_GET_SIGNING_STATE; + state_buffer[1] = PS4Data::getInstance().nonce_id; + memset(&state_buffer[2], 0, 14); + uint8_t* buf = report_buffer; + uint16_t len = sizeof(state_buffer); + memcpy(buf, state_buffer, len); + awaiting_cb = true; + tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_GET_SIGNING_STATE, HID_REPORT_TYPE_FEATURE, buf, len); + } + 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 + memset(&nonce_buffer[3], 0, 61); // zero rest of memory + uint8_t* buf = report_buffer; + uint16_t len = sizeof(nonce_buffer); + memcpy(buf, nonce_buffer, len); + send_nonce_part++; // Nonce Part is reset during callback + awaiting_cb = true; + tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_GET_SIGNATURE_NONCE, HID_REPORT_TYPE_FEATURE, buf, len); + } + break; + }; + + tuh_task(); // USB handle task as host +} + +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + (void)desc_report; + (void)desc_len; + + ps_dev_addr = dev_addr; + ps_instance = instance; + host_device_mounted = true; + + uint16_t vid, pid; + tuh_vid_pid_get(dev_addr, &vid, &pid); + + if ( !tuh_hid_receive_report(dev_addr, instance) ) + { + // Error: cannot request report + } +} + + +/// Invoked when device is unmounted (bus reset/unplugged) +void tuh_umount_cb(uint8_t daddr) +{ + host_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 + passthrough_state = PS4State::no_nonce; +} + +void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + switch(report_id) { + case PS4AuthReport::PS4_RESET_AUTH: + awaiting_cb = false; + if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready) + passthrough_state = PS4State::receiving_nonce; + break; + case PS4AuthReport::PS4_GET_SIGNING_STATE: + awaiting_cb = false; + if (report_buffer[2] == 0) + passthrough_state = PS4State::sending_nonce; + break; + case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: + awaiting_cb = false; + 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; + passthrough_state = PS4State::no_nonce; // something we don't support + PS4Data::getInstance().ps4State = PS4State::signed_nonce_ready; + } + break; + default: + break; + } +} + +// On IN/OUT/FEATURE set report callback +void tuh_hid_set_report_complete_cb(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: + awaiting_cb = false; + if (nonce_page == 5) { + nonce_page = 0; + passthrough_state = PS4State::signed_nonce_ready; + } + break; + default: + break; + }; +} + + +// Invoked when received report from device via interrupt endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + (void) len; + if ( !tuh_hid_receive_report(dev_addr, instance) ) + { + //Error: cannot request report + } +} diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 260a09b13..2cedc8a5e 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -25,6 +25,7 @@ #include "addons/playernum.h" #include "addons/pleds.h" #include "addons/ps4mode.h" +#include "addons/pspassthrough.h" #include "addons/reverse.h" #include "addons/slider_socd.h" #include "addons/turbo.h" @@ -514,6 +515,11 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.addonOptions.focusModeOptions, oledLockEnabled, !!FOCUS_MODE_OLED_LOCK_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.focusModeOptions, rgbLockEnabled, !!FOCUS_MODE_RGB_LOCK_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.focusModeOptions, buttonLockEnabled, !!FOCUS_MODE_BUTTON_LOCK_ENABLED); + + // PS Passthrough + INIT_UNSET_PROPERTY(config.addonOptions.psPassthroughOptions, enabled, PSPASSTHROUGH_ENABLED); + INIT_UNSET_PROPERTY(config.addonOptions.psPassthroughOptions, pinDplus, PSPASSTHROUGH_PIN_DPLUS); + INIT_UNSET_PROPERTY(config.addonOptions.psPassthroughOptions, pin5V, PSPASSTHROUGH_PIN_5V); } diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index 2fab38fc3..1b3623c22 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -1118,6 +1118,11 @@ std::string setAddonOptions() docToValue(keyboardHostOptions.mapping.keyButtonA1, doc, "keyboardHostMap", "A1"); docToValue(keyboardHostOptions.mapping.keyButtonA2, doc, "keyboardHostMap", "A2"); + PSPassthroughOptions& psPassthroughOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; + docToValue(psPassthroughOptions.enabled, doc, "PSPassthroughAddonEnabled"); + docToPin(psPassthroughOptions.pinDplus, doc, "psPassthroughPinDplus"); + docToPin(psPassthroughOptions.pin5V, doc, "psPassthroughPin5V"); + Storage::getInstance().save(); return serialize_json(doc); @@ -1351,6 +1356,11 @@ std::string getAddonOptions() writeDoc(doc, "keyboardHostMap", "A1", keyboardHostOptions.mapping.keyButtonA1); writeDoc(doc, "keyboardHostMap", "A2", keyboardHostOptions.mapping.keyButtonA2); + PSPassthroughOptions& psPassthroughOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; + writeDoc(doc, "PSPassthroughAddonEnabled", psPassthroughOptions.enabled); + writeDoc(doc, "psPassthroughPinDplus", psPassthroughOptions.pinDplus); + writeDoc(doc, "psPassthroughPin5V", psPassthroughOptions.pin5V); + const FocusModeOptions& focusModeOptions = Storage::getInstance().getAddonOptions().focusModeOptions; writeDoc(doc, "focusModePin", cleanPin(focusModeOptions.pin)); writeDoc(doc, "focusModeButtonLockMask", focusModeOptions.buttonLockMask); diff --git a/src/gp2040.cpp b/src/gp2040.cpp index c5b8d7da6..2cb6d2452 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -103,7 +103,7 @@ void GP2040::setup() { adc_init(); // Setup Add-ons - addons.LoadAddon(new KeyboardHostAddon(), CORE0_INPUT); + //addons.LoadAddon(new KeyboardHostAddon(), CORE0_INPUT); addons.LoadAddon(new AnalogInput(), CORE0_INPUT); addons.LoadAddon(new BootselButtonAddon(), CORE0_INPUT); addons.LoadAddon(new DualDirectionalInput(), CORE0_INPUT); diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 0f75469ac..1dbfb1604 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -11,6 +11,7 @@ #include "addons/board_led.h" #include "addons/buzzerspeaker.h" #include "addons/ps4mode.h" +#include "addons/pspassthrough.h" #include @@ -27,6 +28,7 @@ void GP2040Aux::setup() { addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); + addons.LoadAddon(new PSPassthroughAddon(), CORE1_LOOP); // must be at the bottom } void GP2040Aux::run() { diff --git a/www/server/app.js b/www/server/app.js index d713acd8f..1dfd58a57 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -361,6 +361,8 @@ app.get("/api/getAddonsOptions", (req, res) => { keyboardHostPinDplus: 0, keyboardHostPin5V: -1, keyboardHostMap: DEFAULT_KEYBOARD_MAPPING, + psPassthroughPinDplus: 0, + psPassthroughPin5V: -1, AnalogInputEnabled: 1, BoardLedAddonEnabled: 1, FocusModeAddonEnabled: 1, @@ -379,6 +381,7 @@ app.get("/api/getAddonsOptions", (req, res) => { TurboInputEnabled: 1, WiiExtensionAddonEnabled: 1, SNESpadAddonEnabled: 1, + PSPassthroughAddonEnabled: 1, usedPins: Object.values(picoController), }); }); diff --git a/www/src/Locales/en/AddonsConfig.jsx b/www/src/Locales/en/AddonsConfig.jsx index 7a7110b69..033f79fab 100644 --- a/www/src/Locales/en/AddonsConfig.jsx +++ b/www/src/Locales/en/AddonsConfig.jsx @@ -118,4 +118,9 @@ export default { 'keyboard-host-d-plus-label': 'D+', 'keyboard-host-d-minus-label': 'D-', 'keyboard-host-five-v-label': '5V Power (optional)', + 'pspassthrough-header-text': 'PS Passthrough Configuration', + 'pspassthrough-sub-header-text': 'Following set the data +, - and 5V (optional) pins. Only the + and 5V pin can be configured.', + 'pspassthrough-d-plus-label': 'D+', + 'pspassthrough-d-minus-label': 'D-', + 'pspassthrough-five-v-label': '5V Power (optional)', }; diff --git a/www/src/Pages/AddonsConfigPage.jsx b/www/src/Pages/AddonsConfigPage.jsx index 0620a195d..951950fd0 100644 --- a/www/src/Pages/AddonsConfigPage.jsx +++ b/www/src/Pages/AddonsConfigPage.jsx @@ -303,6 +303,10 @@ const schema = yup.object().shape({ keyboardHostPinDplus: yup.number().label('Keyboard Host D+ Pin').validatePinWhenValue('KeyboardHostAddonEnabled'), keyboardHostPin5V: yup.number().label('Keyboard Host 5V Power Pin').validatePinWhenValue('KeyboardHostAddonEnabled'), + PSPassthroughAddonEnabled: yup.number().required().label('PS Passthrough Add-On Enabled'), + psPassthroughPinDplus: yup.number().label('PS Passthrough D+ Pin').validatePinWhenValue('PSPassthroughAddonEnabled'), + psPassthroughPin5V: yup.number().label('PS Passthrough 5V Power Pin').validatePinWhenValue('PSPassthroughAddonEnabled'), + PlayerNumAddonEnabled: yup.number().required().label('Player Number Add-On Enabled'), playerNumber: yup.number().label('Player Number').validateRangeWhenValue('PlayerNumAddonEnabled', 1, 4), @@ -1715,6 +1719,55 @@ export default function AddonsConfigPage() { onChange={(e) => {handleCheckbox("PS4ModeAddonEnabled", values); handleChange(e);}} /> +
+ + { handleCheckbox("PSPassthroughAddonEnabled", values); handleChange(e);}} + /> +
Date: Fri, 11 Aug 2023 16:42:07 -0400 Subject: [PATCH 02/24] Added missing TinyUSB library calls to pspassthrough.cpp for now --- src/addons/pspassthrough.cpp | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 6c5664ffc..4287a8ced 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -7,6 +7,14 @@ #include "CRC32.h" +// Get Report using control endpoint +// report_type is either Input, Output or Feature, (value from hid_report_type_t) +bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); + +// Invoked when Sent Report to device via either control endpoint +// len = 0 indicate there is error in the transfer e.g stalled response +TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); + // Data passed between PS Passthrough and TinyUSB Host callbacks static bool host_device_mounted = false; static uint8_t ps_dev_addr = 0; @@ -210,3 +218,53 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons //Error: cannot request report } } + +static void get_report_complete(tuh_xfer_t* xfer) +{ + TU_LOG2("HID Get Report complete\r\n"); + + if (tuh_hid_get_report_complete_cb) + { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const instance = ps_instance; + + uint8_t const report_type = tu_u16_high(xfer->setup->wValue); + uint8_t const report_id = tu_u16_low(xfer->setup->wValue); + + tuh_hid_get_report_complete_cb(xfer->daddr, instance, report_id, report_type, + (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); + } +} + +bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) +{ + //hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + //TU_LOG2("HID Get Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HID_REQ_CONTROL_GET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = 0, //hid_itf->itf_num, + .wLength = len + }; + + tuh_xfer_t xfer = + { + .daddr = dev_addr, + .ep_addr = 0, + .setup = &request, + .buffer = (uint8_t*)report, + .complete_cb = get_report_complete, + .user_data = 0 + }; + + TU_ASSERT( tuh_control_xfer(&xfer) ); + return true; +} From d51543d743c28622b2b2117cf8bdcab894e5745e Mon Sep 17 00:00:00 2001 From: Luke A Date: Fri, 11 Aug 2023 18:54:51 -0400 Subject: [PATCH 03/24] Moving GPAddons over to USBAddon then running a USB Host manager to handle TinyUSB callbacks --- CMakeLists.txt | 1 + headers/addonmanager.h | 2 +- headers/addons/keyboard_host.h | 44 ++++++-- headers/addons/pspassthrough.h | 12 +- headers/usbaddon.h | 24 ++++ headers/usbhostmanager.h | 33 ++++++ src/addonmanager.cpp | 9 +- src/addons/keyboard_host.cpp | 138 ++++++++--------------- src/addons/pspassthrough.cpp | 197 +++++++++------------------------ src/gp2040.cpp | 14 ++- src/gp2040aux.cpp | 12 +- src/usbhostmanager.cpp | 155 ++++++++++++++++++++++++++ 12 files changed, 388 insertions(+), 253 deletions(-) create mode 100644 headers/usbaddon.h create mode 100644 headers/usbhostmanager.h create mode 100644 src/usbhostmanager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 929b506f3..b139ba843 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,7 @@ src/addonmanager.cpp src/configmanager.cpp src/storagemanager.cpp src/system.cpp +src/usbhostmanager.cpp src/config_legacy.cpp src/config_utils.cpp src/configs/webconfig.cpp diff --git a/headers/addonmanager.h b/headers/addonmanager.h index b8fa9ec14..d292f70f0 100644 --- a/headers/addonmanager.h +++ b/headers/addonmanager.h @@ -21,7 +21,7 @@ class AddonManager { public: AddonManager() {} ~AddonManager() {} - void LoadAddon(GPAddon*, ADDON_PROCESS); + bool LoadAddon(GPAddon*, ADDON_PROCESS); void PreprocessAddons(ADDON_PROCESS); void ProcessAddons(ADDON_PROCESS); GPAddon * GetAddon(std::string); // hack for NeoPicoLED diff --git a/headers/addons/keyboard_host.h b/headers/addons/keyboard_host.h index 8ff7761ab..fcf88d7c3 100644 --- a/headers/addons/keyboard_host.h +++ b/headers/addons/keyboard_host.h @@ -1,7 +1,7 @@ #ifndef _KeyboardHost_H #define _KeyboardHost_H -#include "gpaddon.h" +#include "usbaddon.h" #include "gamepad.h" #ifndef KEYBOARD_HOST_ENABLED @@ -21,12 +21,12 @@ struct KeyboardButtonMapping { - KeyboardButtonMapping(uint16_t bm) : - buttonMask(bm) - {} - uint8_t key; - const uint16_t buttonMask; + uint16_t buttonMask; + + inline void setMask(uint16_t m) { + buttonMask = m; + } inline void setKey(uint8_t p) { @@ -36,14 +36,42 @@ struct KeyboardButtonMapping bool isAssigned() const { return key != 0xff; } }; -class KeyboardHostAddon : public GPAddon { +class KeyboardHostAddon : public USBAddon { public: virtual bool available(); virtual void setup(); // KeyboardHost Setup virtual void process() {} // KeyboardHost Process virtual void preprocess(); virtual std::string name() { return KeyboardHostName; } -private: +// USB Add-on Features + virtual void initPIO(); + virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + virtual void unmount(uint8_t dev_addr); + virtual void report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + virtual void set_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {} + 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; + void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report); + GamepadState _keyboard_host_state; + KeyboardButtonMapping _keyboard_host_mapDpadUp; + KeyboardButtonMapping _keyboard_host_mapDpadDown; + KeyboardButtonMapping _keyboard_host_mapDpadLeft; + KeyboardButtonMapping _keyboard_host_mapDpadRight; + KeyboardButtonMapping _keyboard_host_mapButtonB1; + KeyboardButtonMapping _keyboard_host_mapButtonB2; + KeyboardButtonMapping _keyboard_host_mapButtonB3; + KeyboardButtonMapping _keyboard_host_mapButtonB4; + KeyboardButtonMapping _keyboard_host_mapButtonL1; + KeyboardButtonMapping _keyboard_host_mapButtonR1; + KeyboardButtonMapping _keyboard_host_mapButtonL2; + KeyboardButtonMapping _keyboard_host_mapButtonR2; + KeyboardButtonMapping _keyboard_host_mapButtonS1; + KeyboardButtonMapping _keyboard_host_mapButtonS2; + KeyboardButtonMapping _keyboard_host_mapButtonL3; + KeyboardButtonMapping _keyboard_host_mapButtonR3; + KeyboardButtonMapping _keyboard_host_mapButtonA1; + KeyboardButtonMapping _keyboard_host_mapButtonA2; }; #endif // _KeyboardHost_H_ \ No newline at end of file diff --git a/headers/addons/pspassthrough.h b/headers/addons/pspassthrough.h index 19fff0dba..8f24a5b12 100644 --- a/headers/addons/pspassthrough.h +++ b/headers/addons/pspassthrough.h @@ -1,7 +1,7 @@ #ifndef _PSPassthrough_H #define _PSPassthrough_H -#include "gpaddon.h" +#include "usbaddon.h" #include "ps4_driver.h" @@ -24,14 +24,22 @@ // KeyboardHost Module Name #define PSPassthroughName "PSPassthrough" -class PSPassthroughAddon : public GPAddon { +class PSPassthroughAddon : public USBAddon { public: virtual bool available(); virtual void setup(); // PSPassthrough Setup virtual void process(); // PSPassthrough Process virtual void preprocess() {} virtual std::string name() { return PSPassthroughName; } +// USB Add-on Features + virtual void initPIO(); + virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + virtual void unmount(uint8_t dev_addr); + virtual void set_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); + 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; }; #endif // _PSPassthrough_H_ \ No newline at end of file diff --git a/headers/usbaddon.h b/headers/usbaddon.h new file mode 100644 index 000000000..54c165f4f --- /dev/null +++ b/headers/usbaddon.h @@ -0,0 +1,24 @@ +#ifndef _USBAddon_H_ +#define _USBAddon_H_ + +#include "gpaddon.h" + +#include + +class USBAddon : public GPAddon +{ +public: + virtual bool available() = 0; + virtual void setup() = 0; + virtual void process() = 0; + virtual void preprocess() = 0; + virtual std::string name() = 0; + virtual void initPIO() = 0; + virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) = 0; + virtual void unmount(uint8_t dev_addr) = 0; + virtual void report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) = 0; + virtual void set_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) = 0; + virtual void get_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) = 0; +}; + +#endif \ No newline at end of file diff --git a/headers/usbhostmanager.h b/headers/usbhostmanager.h new file mode 100644 index 000000000..122bb0baf --- /dev/null +++ b/headers/usbhostmanager.h @@ -0,0 +1,33 @@ +#ifndef _USBHOSTMANAGER_H_ +#define _USBHOSTMANAGER_H_ + +#include "usbaddon.h" +#include + +// Missing TinyUSB call +bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); + +class USBHostManager { +public: + USBHostManager(USBHostManager const&) = delete; + void operator=(USBHostManager const&) = delete; + static USBHostManager& getInstance() {// Thread-safe storage ensures cross-thread talk + static USBHostManager instance; // Guaranteed to be destroyed. // Instantiated on first use. + return instance; + } + void init(); + void pushAddon(USBAddon *); // If anything needs to update in the gpconfig driver + void setClock(); + void processCore0(); // do we separate Core0 and Core1? + void processCore1(); + void hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + void hid_umount_cb(uint8_t daddr); + void hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + 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() {} + std::vector addons; +}; + +#endif \ No newline at end of file diff --git a/src/addonmanager.cpp b/src/addonmanager.cpp index 55806f93e..8b82c1cad 100644 --- a/src/addonmanager.cpp +++ b/src/addonmanager.cpp @@ -1,15 +1,16 @@ #include "addonmanager.h" -void AddonManager::LoadAddon(GPAddon* addon, ADDON_PROCESS processAt) { +bool 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); - } else { - delete addon; // Don't use the memory if we don't have to - } + return true; + } + delete addon; // Don't use the memory if we don't have to + return false; } diff --git a/src/addons/keyboard_host.cpp b/src/addons/keyboard_host.cpp index b0a646ffc..cd9a13e24 100644 --- a/src/addons/keyboard_host.cpp +++ b/src/addons/keyboard_host.cpp @@ -1,30 +1,9 @@ #include "addons/keyboard_host.h" #include "storagemanager.h" +#include "usbhostmanager.h" #include "pio_usb.h" -static bool host_device_mounted = false; -static GamepadState _keyboard_host_state; - -static KeyboardButtonMapping _keyboard_host_mapDpadUp = KeyboardButtonMapping(GAMEPAD_MASK_UP); -static KeyboardButtonMapping _keyboard_host_mapDpadDown = KeyboardButtonMapping(GAMEPAD_MASK_DOWN); -static KeyboardButtonMapping _keyboard_host_mapDpadLeft = KeyboardButtonMapping(GAMEPAD_MASK_LEFT); -static KeyboardButtonMapping _keyboard_host_mapDpadRight = KeyboardButtonMapping(GAMEPAD_MASK_RIGHT); -static KeyboardButtonMapping _keyboard_host_mapButtonB1 = KeyboardButtonMapping(GAMEPAD_MASK_B1); -static KeyboardButtonMapping _keyboard_host_mapButtonB2 = KeyboardButtonMapping(GAMEPAD_MASK_B2); -static KeyboardButtonMapping _keyboard_host_mapButtonB3 = KeyboardButtonMapping(GAMEPAD_MASK_B3); -static KeyboardButtonMapping _keyboard_host_mapButtonB4 = KeyboardButtonMapping(GAMEPAD_MASK_B4); -static KeyboardButtonMapping _keyboard_host_mapButtonL1 = KeyboardButtonMapping(GAMEPAD_MASK_L1); -static KeyboardButtonMapping _keyboard_host_mapButtonR1 = KeyboardButtonMapping(GAMEPAD_MASK_R1); -static KeyboardButtonMapping _keyboard_host_mapButtonL2 = KeyboardButtonMapping(GAMEPAD_MASK_L2); -static KeyboardButtonMapping _keyboard_host_mapButtonR2 = KeyboardButtonMapping(GAMEPAD_MASK_R2); -static KeyboardButtonMapping _keyboard_host_mapButtonS1 = KeyboardButtonMapping(GAMEPAD_MASK_S1); -static KeyboardButtonMapping _keyboard_host_mapButtonS2 = KeyboardButtonMapping(GAMEPAD_MASK_S2); -static KeyboardButtonMapping _keyboard_host_mapButtonL3 = KeyboardButtonMapping(GAMEPAD_MASK_L3); -static KeyboardButtonMapping _keyboard_host_mapButtonR3 = KeyboardButtonMapping(GAMEPAD_MASK_R3); -static KeyboardButtonMapping _keyboard_host_mapButtonA1 = KeyboardButtonMapping(GAMEPAD_MASK_A1); -static KeyboardButtonMapping _keyboard_host_mapButtonA2 = KeyboardButtonMapping(GAMEPAD_MASK_A2); - bool KeyboardHostAddon::available() { const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; return keyboardHostOptions.enabled && @@ -33,12 +12,10 @@ bool KeyboardHostAddon::available() { } void KeyboardHostAddon::setup() { - set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + USBHostManager::getInstance().setClock(); + const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; const KeyboardMapping& keyboardMapping = keyboardHostOptions.mapping; - // board_init(); - // board_init() should be doing what the two lines below are doing but doesn't work - // needs tinyusb_board library linked if (keyboardHostOptions.pin5V != -1) { const int32_t pin5V = keyboardHostOptions.pin5V; @@ -47,16 +24,27 @@ void KeyboardHostAddon::setup() { gpio_pull_up(pin5V); } - pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; - pio_cfg.pin_dp = keyboardHostOptions.pinDplus; - tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); - tuh_init(BOARD_TUH_RHPORT); - - while((to_ms_since_boot(get_absolute_time()) < 250)) { - if (host_device_mounted) break; - tuh_task(); - } - + initPIO(); + + _keyboard_host_enabled = false; + _keyboard_host_mapDpadUp.setMask(GAMEPAD_MASK_UP); + _keyboard_host_mapDpadDown.setMask(GAMEPAD_MASK_DOWN); + _keyboard_host_mapDpadLeft.setMask(GAMEPAD_MASK_LEFT); + _keyboard_host_mapDpadRight.setMask(GAMEPAD_MASK_RIGHT); + _keyboard_host_mapButtonB1.setMask(GAMEPAD_MASK_B1); + _keyboard_host_mapButtonB2.setMask(GAMEPAD_MASK_B2); + _keyboard_host_mapButtonB3.setMask(GAMEPAD_MASK_B3); + _keyboard_host_mapButtonB4.setMask(GAMEPAD_MASK_B4); + _keyboard_host_mapButtonL1.setMask(GAMEPAD_MASK_L1); + _keyboard_host_mapButtonR1.setMask(GAMEPAD_MASK_R1); + _keyboard_host_mapButtonL2.setMask(GAMEPAD_MASK_L2); + _keyboard_host_mapButtonR2.setMask(GAMEPAD_MASK_R2); + _keyboard_host_mapButtonS1.setMask(GAMEPAD_MASK_S1); + _keyboard_host_mapButtonS2.setMask(GAMEPAD_MASK_S2); + _keyboard_host_mapButtonL3.setMask(GAMEPAD_MASK_L3); + _keyboard_host_mapButtonR3.setMask(GAMEPAD_MASK_R3); + _keyboard_host_mapButtonA1.setMask(GAMEPAD_MASK_A1); + _keyboard_host_mapButtonA2.setMask(GAMEPAD_MASK_A2); _keyboard_host_mapDpadUp.setKey(keyboardMapping.keyDpadUp); _keyboard_host_mapDpadDown.setKey(keyboardMapping.keyDpadDown); _keyboard_host_mapDpadLeft.setKey(keyboardMapping.keyDpadLeft); @@ -87,46 +75,40 @@ void KeyboardHostAddon::preprocess() { gamepad->state.ry |= _keyboard_host_state.ry; gamepad->state.lt |= _keyboard_host_state.lt; gamepad->state.rt |= _keyboard_host_state.rt; +} - tuh_task(); +void KeyboardHostAddon::initPIO() { + // Probably can't move away from this in the USB manager + const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; + pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; + pio_cfg.pin_dp = keyboardHostOptions.pinDplus; + tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); + tuh_init(BOARD_TUH_RHPORT); } -/* -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) -{ + +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)desc_report; - (void)desc_len; +void KeyboardHostAddon::unmount(uint8_t dev_addr) { + if ( _keyboard_host_enabled == true ) + _keyboard_host_enabled = false; +} - host_device_mounted = true; +void KeyboardHostAddon::report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len){ + if ( _keyboard_host_enabled == false ) + return; // do nothing if our add-on is not enabled // Interface protocol (hid_interface_protocol_enum_t) uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - uint16_t vid, pid; - tuh_vid_pid_get(dev_addr, &vid, &pid); - // tuh_hid_report_received_cb() will be invoked when report is available - if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) - { - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { - // Error: cannot request report - } - } -} + if (itf_protocol != HID_ITF_PROTOCOL_KEYBOARD) + return; -// Invoked when device with hid interface is un-mounted -void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) -{ - (void) dev_addr; - (void) instance; + process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report ); } uint8_t getKeycodeFromModifier(uint8_t modifier) { @@ -145,7 +127,7 @@ uint8_t getKeycodeFromModifier(uint8_t modifier) { } // convert hid keycode to ascii and print via usb device CDC (ignore non-printable) -void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report) +void KeyboardHostAddon::process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report) { (void) dev_addr; @@ -198,29 +180,3 @@ void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report) } } } - -// Invoked when received report from device via interrupt endpoint -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ - if ( _keyboard_host_enabled == false ) - return; // do nothing if our add-on is not enabled - - (void) len; - uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - - switch(itf_protocol) - { - case HID_ITF_PROTOCOL_KEYBOARD: - process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report ); - break; - - default: break; - } - - // continue to request to receive report - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { - //Error: cannot request report - } -} -*/ \ No newline at end of file diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 4287a8ced..d0667a5f5 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -1,22 +1,12 @@ #include "addons/pspassthrough.h" #include "storagemanager.h" - -#include "pio_usb.h" -#include "tusb.h" -#include "host/usbh_classdriver.h" +#include "usbhostmanager.h" #include "CRC32.h" -// Get Report using control endpoint -// report_type is either Input, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); - -// Invoked when Sent Report to device via either control endpoint -// len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); +#include "pio_usb.h" // Data passed between PS Passthrough and TinyUSB Host callbacks -static bool host_device_mounted = false; static uint8_t ps_dev_addr = 0; static uint8_t ps_instance = 0; static tusb_desc_device_t desc_device; @@ -33,7 +23,7 @@ bool PSPassthroughAddon::available() { } void PSPassthroughAddon::setup() { - set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + USBHostManager::getInstance().setClock(); const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; @@ -44,16 +34,7 @@ void PSPassthroughAddon::setup() { gpio_pull_up(pin5V); } - pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; - pio_cfg.pin_dp = (uint8_t)psOptions.pinDplus; - tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); - tuh_init(BOARD_TUH_RHPORT); - - while((to_ms_since_boot(get_absolute_time()) < 2000)) { - if (host_device_mounted) - break; - tuh_task(); - } + initPIO(); nonce_page = 0; // no nonce yet send_nonce_part = 0; // which part of the nonce are we getting from send? @@ -134,137 +115,67 @@ void PSPassthroughAddon::process() { } break; }; - - tuh_task(); // USB handle task as host } -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) -{ - (void)desc_report; - (void)desc_len; - - ps_dev_addr = dev_addr; - ps_instance = instance; - host_device_mounted = true; - - uint16_t vid, pid; - tuh_vid_pid_get(dev_addr, &vid, &pid); +void PSPassthroughAddon::initPIO() { + const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { - // Error: cannot request report - } + pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; + pio_cfg.pin_dp = (uint8_t)psOptions.pinDplus; + tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); + tuh_init(BOARD_TUH_RHPORT); } - -/// Invoked when device is unmounted (bus reset/unplugged) -void tuh_umount_cb(uint8_t daddr) -{ - host_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 - passthrough_state = PS4State::no_nonce; +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; } -void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { - switch(report_id) { - case PS4AuthReport::PS4_RESET_AUTH: - awaiting_cb = false; - if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready) - passthrough_state = PS4State::receiving_nonce; - break; - case PS4AuthReport::PS4_GET_SIGNING_STATE: - awaiting_cb = false; - if (report_buffer[2] == 0) - passthrough_state = PS4State::sending_nonce; - break; - case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: - awaiting_cb = false; - 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; - passthrough_state = PS4State::no_nonce; // something we don't support - PS4Data::getInstance().ps4State = PS4State::signed_nonce_ready; - } - break; - default: - break; - } +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 + passthrough_state = PS4State::no_nonce; } -// On IN/OUT/FEATURE set report callback -void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { +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: - awaiting_cb = false; - if (nonce_page == 5) { - nonce_page = 0; - passthrough_state = PS4State::signed_nonce_ready; - } - break; - default: - break; + case PS4AuthReport::PS4_SET_AUTH_PAYLOAD: + awaiting_cb = false; + if (nonce_page == 5) { + nonce_page = 0; + passthrough_state = PS4State::signed_nonce_ready; + } + break; + default: + break; }; } - -// Invoked when received report from device via interrupt endpoint -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ - (void) len; - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { - //Error: cannot request report - } -} - -static void get_report_complete(tuh_xfer_t* xfer) -{ - TU_LOG2("HID Get Report complete\r\n"); - - if (tuh_hid_get_report_complete_cb) - { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const instance = ps_instance; - - uint8_t const report_type = tu_u16_high(xfer->setup->wValue); - uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - - tuh_hid_get_report_complete_cb(xfer->daddr, instance, report_id, report_type, - (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); - } -} - -bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) -{ - //hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - //TU_LOG2("HID Get Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HID_REQ_CONTROL_GET_REPORT, - .wValue = tu_u16(report_type, report_id), - .wIndex = 0, //hid_itf->itf_num, - .wLength = len - }; - - tuh_xfer_t xfer = - { - .daddr = dev_addr, - .ep_addr = 0, - .setup = &request, - .buffer = (uint8_t*)report, - .complete_cb = get_report_complete, - .user_data = 0 - }; - - TU_ASSERT( tuh_control_xfer(&xfer) ); - return true; +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_RESET_AUTH: + awaiting_cb = false; + if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready) + passthrough_state = PS4State::receiving_nonce; + break; + case PS4AuthReport::PS4_GET_SIGNING_STATE: + awaiting_cb = false; + if (report_buffer[2] == 0) + passthrough_state = PS4State::sending_nonce; + break; + case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: + awaiting_cb = false; + 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; + passthrough_state = PS4State::no_nonce; // something we don't support + PS4Data::getInstance().ps4State = PS4State::signed_nonce_ready; + } + break; + default: + break; + }; } diff --git a/src/gp2040.cpp b/src/gp2040.cpp index 2cb6d2452..5c1411552 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -8,6 +8,7 @@ #include "configmanager.h" // Global Managers #include "storagemanager.h" #include "addonmanager.h" +#include "usbhostmanager.h" #include "addons/analog.h" // Inputs for Core0 #include "addons/bootsel_button.h" @@ -42,6 +43,9 @@ static const uint32_t REBOOT_HOTKEY_HOLD_TIME_MS = 4000; GP2040::GP2040() : nextRuntime(0) { Storage::getInstance().SetGamepad(new Gamepad(GAMEPAD_DEBOUNCE_MILLIS)); Storage::getInstance().SetProcessedGamepad(new Gamepad(GAMEPAD_DEBOUNCE_MILLIS)); + + // Init TinyUSB Host Manager + USBHostManager::getInstance().init(); } GP2040::~GP2040() { @@ -102,8 +106,12 @@ void GP2040::setup() { // Initialize our ADC (various add-ons) adc_init(); - // Setup Add-ons - //addons.LoadAddon(new KeyboardHostAddon(), CORE0_INPUT); + // Setup USB Host Add-ons + KeyboardHostAddon * keyboardHostAddon = new KeyboardHostAddon(); + if( addons.LoadAddon(keyboardHostAddon, CORE0_INPUT) ) + USBHostManager::getInstance().pushAddon(keyboardHostAddon); + + // Setup Regular Add-ons addons.LoadAddon(new AnalogInput(), CORE0_INPUT); addons.LoadAddon(new BootselButtonAddon(), CORE0_INPUT); addons.LoadAddon(new DualDirectionalInput(), CORE0_INPUT); @@ -137,6 +145,8 @@ void GP2040::run() { continue; } + USBHostManager::getInstance().processCore0(); + if (nextRuntime > getMicro()) { // fix for unsigned sleep_us(50); // Give some time back to our CPU (lower power consumption) continue; diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 1dbfb1604..1b540466b 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -4,6 +4,7 @@ #include "storagemanager.h" // Global Managers #include "addonmanager.h" +#include "usbhostmanager.h" #include "addons/i2cdisplay.h" // Add-Ons #include "addons/neopicoleds.h" @@ -22,19 +23,26 @@ GP2040Aux::~GP2040Aux() { } void GP2040Aux::setup() { + // Setup Regular Add-ons addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); - addons.LoadAddon(new PSPassthroughAddon(), CORE1_LOOP); // must be at the bottom + + // Setup USB add-ons + PSPassthroughAddon * psPassthroughAddon = new PSPassthroughAddon(); + if( addons.LoadAddon(psPassthroughAddon, CORE1_LOOP) ) + USBHostManager::getInstance().pushAddon(psPassthroughAddon); } void GP2040Aux::run() { while (1) { + USBHostManager::getInstance().processCore1(); + 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; } addons.ProcessAddons(CORE1_LOOP); diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp new file mode 100644 index 000000000..8dc1507ee --- /dev/null +++ b/src/usbhostmanager.cpp @@ -0,0 +1,155 @@ +#include "usbhostmanager.h" + +#include "tusb.h" +#include "host/usbh_classdriver.h" + +void USBHostManager::init() { +} + +void USBHostManager::setClock() { + set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + + stdio_init_all(); + printf("Setting speed to 120khz!\r\n"); + // Adjust our clock speed for USB +} + +void USBHostManager::pushAddon(USBAddon * usbAddon) { // If anything needs to update in the gpconfig driver + printf("Pushing add-on %s\r\n", usbAddon->name().c_str()); + addons.push_back(usbAddon); +} + +// Core 0 - USB host manager does nothing for now +void USBHostManager::processCore0() { +} + +// Core 1 - USB host manager calls TinyUSB Host task +void USBHostManager::processCore1() { + if ( !addons.empty() ){ + tuh_task(); + } +} + +void USBHostManager::hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { + printf("USB HID Mounted %i %i\r\n", dev_addr, instance); + for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ + printf("Calling mount on add-on %s\r\n", (*it)->name().c_str()); + (*it)->mount(dev_addr, instance, desc_report, desc_len); + } +} + +void USBHostManager::hid_umount_cb(uint8_t daddr) { + printf("USB HID unmounted %i\r\n", daddr); + for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ + printf("Calling unmount on add-on %s\r\n", (*it)->name().c_str()); + (*it)->unmount(daddr); + } +} + +void USBHostManager::hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { + //printf("Report Received!\r\n"); + for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ + //printf("Sending to add-on %s\r\n", (*it)->name()); + (*it)->report_received(dev_addr, instance, report, len); + } +} + +void USBHostManager::hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + printf("Set Report Received!\r\n"); + for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ + printf("Sending to add-on %s\r\n", (*it)->name().c_str()); + (*it)->set_report_complete(dev_addr, instance, report_id, report_type, len); + } +} + +void USBHostManager::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + printf("Get Report Received!\r\n"); + for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ + printf("Sending to add-on %s\r\n", (*it)->name().c_str()); + (*it)->get_report_complete(dev_addr, instance, report_id, report_type, len); + } +} + +// TinyUSB Mount Callback +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + USBHostManager::getInstance().hid_mount_cb(dev_addr, instance, desc_report, desc_len); + + if ( !tuh_hid_receive_report(dev_addr, instance) ) { + // Error: cannot request report + } +} + +/// Invoked when device is unmounted (bus reset/unplugged) +void tuh_hid_umount_cb(uint8_t daddr) +{ + USBHostManager::getInstance().hid_umount_cb(daddr); +} + +// Invoked when received report from device via interrupt endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + USBHostManager::getInstance().hid_report_received_cb(dev_addr, instance, report, len); + + if ( !tuh_hid_receive_report(dev_addr, instance) ) { + //Error: cannot request report + } +} + + +// On IN/OUT/FEATURE set report callback +void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + USBHostManager::getInstance().hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, len); +} + + +// GET REPORT FEATURE +void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + USBHostManager::getInstance().hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len); +} + +// TinyUSB Calls missing from TinyUSB :( +static void get_report_complete(tuh_xfer_t* xfer) +{ + if (tuh_hid_get_report_complete_cb) + { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const instance = 0; + + uint8_t const report_type = tu_u16_high(xfer->setup->wValue); + uint8_t const report_id = tu_u16_low(xfer->setup->wValue); + + tuh_hid_get_report_complete_cb(xfer->daddr, instance, report_id, report_type, + (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); + } +} + +bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) +{ + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HID_REQ_CONTROL_GET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = 0, //hid_itf->itf_num, + .wLength = len + }; + + tuh_xfer_t xfer = + { + .daddr = dev_addr, + .ep_addr = 0, + .setup = &request, + .buffer = (uint8_t*)report, + .complete_cb = get_report_complete, + .user_data = 0 + }; + + TU_ASSERT( tuh_control_xfer(&xfer) ); + return true; +} From b46b70ca356b7047f56a8841d17deac34c5d966c Mon Sep 17 00:00:00 2001 From: Luke A Date: Fri, 11 Aug 2023 21:03:59 -0400 Subject: [PATCH 04/24] Set the PS passthrough add-on to default off --- headers/addons/pspassthrough.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/headers/addons/pspassthrough.h b/headers/addons/pspassthrough.h index 8f24a5b12..dac7c8527 100644 --- a/headers/addons/pspassthrough.h +++ b/headers/addons/pspassthrough.h @@ -6,19 +6,15 @@ #include "ps4_driver.h" #ifndef PSPASSTHROUGH_ENABLED -#define PSPASSTHROUGH_ENABLED 1 +#define PSPASSTHROUGH_ENABLED 0 #endif #ifndef PPSPASSTHROUGH_PIN_DPLUS -#define PSPASSTHROUGH_PIN_DPLUS 16 +#define PSPASSTHROUGH_PIN_DPLUS -1 #endif #ifndef PSPASSTHROUGH_PIN_5V -#define PSPASSTHROUGH_PIN_5V 18 -#endif - -#ifndef PSPASSTHROUGH_DEBUG -#define PSPASSTHROUGH_DEBUG true +#define PSPASSTHROUGH_PIN_5V -1 #endif // KeyboardHost Module Name From a511712b8866c6e3a44b1d54a92dc12d4d7f45e7 Mon Sep 17 00:00:00 2001 From: Luke A Date: Sat, 12 Aug 2023 01:17:12 -0400 Subject: [PATCH 05/24] Added i2c display upgrade for PS4/PS5, fixed up usb add-ons a bit, moved NeoPico and PlayerLED to gp2040 to prevent USBHost from missing tuh_task() re-acquire --- headers/addonmanager.h | 1 + headers/addons/keyboard_host.h | 1 - headers/addons/pspassthrough.h | 1 - headers/usbaddon.h | 1 - headers/usbhostmanager.h | 8 +++--- lib/TinyUSB_Gamepad/src/ps4_driver.cpp | 14 ++++------- lib/TinyUSB_Gamepad/src/ps4_driver.h | 11 ++++++++ src/addons/i2cdisplay.cpp | 26 +++++++++++++++++-- src/addons/keyboard_host.cpp | 13 +--------- src/addons/ps4mode.cpp | 1 + src/addons/pspassthrough.cpp | 14 ++--------- src/gp2040.cpp | 12 ++++++--- src/gp2040aux.cpp | 5 +--- src/usbhostmanager.cpp | 35 ++++++++++---------------- 14 files changed, 73 insertions(+), 70 deletions(-) diff --git a/headers/addonmanager.h b/headers/addonmanager.h index d292f70f0..62cec6a13 100644 --- a/headers/addonmanager.h +++ b/headers/addonmanager.h @@ -9,6 +9,7 @@ enum ADDON_PROCESS { CORE0_INPUT, CORE0_USBREPORT, + CORE0_LOOP, CORE1_LOOP }; diff --git a/headers/addons/keyboard_host.h b/headers/addons/keyboard_host.h index fcf88d7c3..3fd379789 100644 --- a/headers/addons/keyboard_host.h +++ b/headers/addons/keyboard_host.h @@ -44,7 +44,6 @@ class KeyboardHostAddon : public USBAddon { virtual void preprocess(); virtual std::string name() { return KeyboardHostName; } // USB Add-on Features - virtual void initPIO(); virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); virtual void unmount(uint8_t dev_addr); virtual void report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); diff --git a/headers/addons/pspassthrough.h b/headers/addons/pspassthrough.h index dac7c8527..aa81e595b 100644 --- a/headers/addons/pspassthrough.h +++ b/headers/addons/pspassthrough.h @@ -28,7 +28,6 @@ class PSPassthroughAddon : public USBAddon { virtual void preprocess() {} virtual std::string name() { return PSPassthroughName; } // USB Add-on Features - virtual void initPIO(); virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); virtual void unmount(uint8_t dev_addr); virtual void set_report_complete(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); diff --git a/headers/usbaddon.h b/headers/usbaddon.h index 54c165f4f..a03ba644c 100644 --- a/headers/usbaddon.h +++ b/headers/usbaddon.h @@ -13,7 +13,6 @@ class USBAddon : public GPAddon virtual void process() = 0; virtual void preprocess() = 0; virtual std::string name() = 0; - virtual void initPIO() = 0; virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) = 0; virtual void unmount(uint8_t dev_addr) = 0; virtual void report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) = 0; diff --git a/headers/usbhostmanager.h b/headers/usbhostmanager.h index 122bb0baf..7af5cfea5 100644 --- a/headers/usbhostmanager.h +++ b/headers/usbhostmanager.h @@ -4,6 +4,8 @@ #include "usbaddon.h" #include +#include "pio_usb.h" + // Missing TinyUSB call bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); @@ -15,19 +17,19 @@ class USBHostManager { static USBHostManager instance; // Guaranteed to be destroyed. // Instantiated on first use. return instance; } - void init(); + void init(uint8_t); void pushAddon(USBAddon *); // If anything needs to update in the gpconfig driver - void setClock(); void processCore0(); // do we separate Core0 and Core1? void processCore1(); void hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); - void hid_umount_cb(uint8_t daddr); + void hid_umount_cb(uint8_t daddr, uint8_t instance); void hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); 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() {} std::vector addons; + usb_device_t *usb_device; }; #endif \ No newline at end of file diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp index 8b7da201f..2ae1beeaf 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp @@ -17,9 +17,9 @@ uint8_t ps4_endpoint_in = 0; uint8_t ps4_endpoint_out = 0; uint8_t ps4_out_buffer[PS4_OUT_SIZE] = {}; -// Alternative version, do we want to use 0x07 for PS5 mode? +// Controller descriptor (byte[4] = 0x00 for ps4, 0x07 for ps5) static constexpr uint8_t output_0x03[] = { - 0x21, 0x27, 0x04, 0xcf, 0x07, 0x2c, 0x56, + 0x21, 0x27, 0x04, 0xcf, 0x00, 0x2c, 0x56, 0x08, 0x00, 0x3d, 0x00, 0xe8, 0x03, 0x04, 0x00, 0xff, 0x7f, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -27,13 +27,6 @@ static constexpr uint8_t output_0x03[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -// Passinglink version -/*static constexpr uint8_t output_0x03[] = { - 0x21, 0x27, 0x4, 0x40, 0x7, 0x2c, 0x56, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xd, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 -};*/ - // Nonce Page Size: 0x38 (56) // Response Page Size: 0x38 (56) static constexpr uint8_t output_0xf3[] = { 0x0, 0x38, 0x38, 0, 0, 0, 0 }; @@ -69,6 +62,9 @@ ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen) return -1; } memcpy(buf, output_0x03, reqlen); + if ( PS4Data::getInstance().authType == PS4AuthType::PS5_PASSTHROUGH ) { + buf[4] = 0x07; // Tell auth we are an arcade stick + } return reqlen; // Use our private RSA key to sign the nonce and return chunks case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.h b/lib/TinyUSB_Gamepad/src/ps4_driver.h index e39d6d3d9..3788bf54f 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.h +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.h @@ -21,6 +21,13 @@ typedef enum PS4_RESET_AUTH = 0xF3 // Unknown (PS4 Report 0xF3) } PS4AuthReport; +typedef enum +{ + NO_AUTH = 0, + PS4_KEY = 1, + PS5_PASSTHROUGH = 2 +} PS4AuthType; + // USB endpoint state vars extern const usbd_class_driver_t ps4_driver; @@ -65,9 +72,13 @@ class PS4Data { // buffer = 256 + 16 + 256 + 256 + 256 + 24 // == 1064 bytes (almost 1 kb) uint8_t ps4_auth_buffer[1064]; + + PS4AuthType authType; + private: PS4Data() { ps4State = PS4State::no_nonce; + authType = PS4AuthType::NO_AUTH; authsent = false; memset(nonce_buffer, 0, 256); memset(ps4_auth_buffer, 0, 1064); diff --git a/src/addons/i2cdisplay.cpp b/src/addons/i2cdisplay.cpp index 914b5049b..eeaabcef4 100644 --- a/src/addons/i2cdisplay.cpp +++ b/src/addons/i2cdisplay.cpp @@ -938,9 +938,31 @@ void I2CDisplayAddon::drawStatusBar(Gamepad * gamepad) case INPUT_MODE_XINPUT: statusBar += "XINPUT"; break; case INPUT_MODE_PS4: if (PS4Data::getInstance().authsent == true ) { - statusBar += "PS4:AS"; + switch ( PS4Data::getInstance().authType ) { + case PS4AuthType::PS4_KEY: + statusBar += "PS4:AS"; + break; + case PS4AuthType::PS5_PASSTHROUGH: + statusBar += "PS5:AS"; + break; + case PS4AuthType::NO_AUTH: + default: + statusBar += "PS?:AS"; + break; + }; } else { - statusBar += "PS4 "; + switch ( PS4Data::getInstance().authType ) { + case PS4AuthType::PS4_KEY: + statusBar += "PS4 "; + break; + case PS4AuthType::PS5_PASSTHROUGH: + statusBar += "PS5 "; + break; + case PS4AuthType::NO_AUTH: + default: + statusBar += "PS4:NK"; + break; + }; } break; case INPUT_MODE_KEYBOARD: statusBar += "HID-KB"; break; diff --git a/src/addons/keyboard_host.cpp b/src/addons/keyboard_host.cpp index cd9a13e24..e58f2664b 100644 --- a/src/addons/keyboard_host.cpp +++ b/src/addons/keyboard_host.cpp @@ -12,8 +12,6 @@ bool KeyboardHostAddon::available() { } void KeyboardHostAddon::setup() { - USBHostManager::getInstance().setClock(); - const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; const KeyboardMapping& keyboardMapping = keyboardHostOptions.mapping; @@ -24,7 +22,7 @@ void KeyboardHostAddon::setup() { gpio_pull_up(pin5V); } - initPIO(); + USBHostManager::getInstance().init((uint8_t)keyboardHostOptions.pinDplus); _keyboard_host_enabled = false; _keyboard_host_mapDpadUp.setMask(GAMEPAD_MASK_UP); @@ -77,15 +75,6 @@ void KeyboardHostAddon::preprocess() { gamepad->state.rt |= _keyboard_host_state.rt; } -void KeyboardHostAddon::initPIO() { - // Probably can't move away from this in the USB manager - const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; - pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; - pio_cfg.pin_dp = keyboardHostOptions.pinDplus; - tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); - tuh_init(BOARD_TUH_RHPORT); -} - 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 diff --git a/src/addons/ps4mode.cpp b/src/addons/ps4mode.cpp index f1fadd8eb..5f1b5903e 100644 --- a/src/addons/ps4mode.cpp +++ b/src/addons/ps4mode.cpp @@ -45,6 +45,7 @@ void PS4ModeAddon::setup() { if (mbedtls_rsa_import(&rsa_context, &N, &P, &Q, nullptr, &E) == 0 && mbedtls_rsa_complete(&rsa_context) == 0) { ready = true; + PS4Data::getInstance().authType = PS4AuthType::PS4_KEY; } DELETE_CONFIG_MPI(N) diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index d0667a5f5..31c6134a5 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -23,8 +23,6 @@ bool PSPassthroughAddon::available() { } void PSPassthroughAddon::setup() { - USBHostManager::getInstance().setClock(); - const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; if (psOptions.pin5V != -1) { // Feather USB-A's require this @@ -34,12 +32,13 @@ void PSPassthroughAddon::setup() { gpio_pull_up(pin5V); } - initPIO(); + USBHostManager::getInstance().init((uint8_t)psOptions.pinDplus); 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 passthrough_state = PS4State::no_nonce; + PS4Data::getInstance().authType = PS4AuthType::PS5_PASSTHROUGH; } void PSPassthroughAddon::process() { @@ -117,15 +116,6 @@ void PSPassthroughAddon::process() { }; } -void PSPassthroughAddon::initPIO() { - const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; - - pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; - pio_cfg.pin_dp = (uint8_t)psOptions.pinDplus; - tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); - tuh_init(BOARD_TUH_RHPORT); -} - 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; diff --git a/src/gp2040.cpp b/src/gp2040.cpp index 5c1411552..92eab0130 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -26,6 +26,9 @@ #include "addons/wiiext.h" #include "addons/snes_input.h" +#include "addons/neopicoleds.h" +#include "addons/pleds.h" + // Pico includes #include "pico/bootrom.h" #include "pico/time.h" @@ -43,9 +46,6 @@ static const uint32_t REBOOT_HOTKEY_HOLD_TIME_MS = 4000; GP2040::GP2040() : nextRuntime(0) { Storage::getInstance().SetGamepad(new Gamepad(GAMEPAD_DEBOUNCE_MILLIS)); Storage::getInstance().SetProcessedGamepad(new Gamepad(GAMEPAD_DEBOUNCE_MILLIS)); - - // Init TinyUSB Host Manager - USBHostManager::getInstance().init(); } GP2040::~GP2040() { @@ -126,6 +126,8 @@ void GP2040::setup() { addons.LoadAddon(new PlayerNumAddon(), CORE0_USBREPORT); addons.LoadAddon(new SliderSOCDInput(), CORE0_INPUT); addons.LoadAddon(new TiltInput(), CORE0_INPUT); + addons.LoadAddon(new NeoPicoLEDAddon(), CORE0_LOOP); + addons.LoadAddon(new PlayerLEDAddon(), CORE0_LOOP); } void GP2040::run() { @@ -147,6 +149,7 @@ void GP2040::run() { USBHostManager::getInstance().processCore0(); + // 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) continue; @@ -181,6 +184,9 @@ void GP2040::run() { tud_task(); // TinyUSB Task update + // Process Loops + addons.ProcessAddons(ADDON_PROCESS::CORE0_LOOP); + nextRuntime = getMicro() + GAMEPAD_POLL_MICRO; } } diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 1b540466b..0aa8f8ebe 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -7,8 +7,7 @@ #include "usbhostmanager.h" #include "addons/i2cdisplay.h" // Add-Ons -#include "addons/neopicoleds.h" -#include "addons/pleds.h" + #include "addons/board_led.h" #include "addons/buzzerspeaker.h" #include "addons/ps4mode.h" @@ -25,8 +24,6 @@ GP2040Aux::~GP2040Aux() { void GP2040Aux::setup() { // Setup Regular Add-ons addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); - addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); - addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index 8dc1507ee..db033e00e 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -1,26 +1,28 @@ #include "usbhostmanager.h" +#include "pio_usb.h" #include "tusb.h" #include "host/usbh_classdriver.h" -void USBHostManager::init() { -} - -void USBHostManager::setClock() { +void USBHostManager::init(uint8_t dataPin) { set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues - stdio_init_all(); - printf("Setting speed to 120khz!\r\n"); - // Adjust our clock speed for USB + pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; + pio_cfg.alarm_pool = (void*)alarm_pool_create(2, 1); + pio_cfg.pin_dp = dataPin; + tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg); + tuh_init(BOARD_TUH_RHPORT); } void USBHostManager::pushAddon(USBAddon * usbAddon) { // If anything needs to update in the gpconfig driver - printf("Pushing add-on %s\r\n", usbAddon->name().c_str()); addons.push_back(usbAddon); } // Core 0 - USB host manager does nothing for now void USBHostManager::processCore0() { + if ( !addons.empty() ){ + //tuh_task(); + } } // Core 1 - USB host manager calls TinyUSB Host task @@ -31,41 +33,31 @@ void USBHostManager::processCore1() { } void USBHostManager::hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { - printf("USB HID Mounted %i %i\r\n", dev_addr, instance); for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ - printf("Calling mount on add-on %s\r\n", (*it)->name().c_str()); (*it)->mount(dev_addr, instance, desc_report, desc_len); } } -void USBHostManager::hid_umount_cb(uint8_t daddr) { - printf("USB HID unmounted %i\r\n", daddr); +void USBHostManager::hid_umount_cb(uint8_t daddr, uint8_t instance) { for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ - printf("Calling unmount on add-on %s\r\n", (*it)->name().c_str()); (*it)->unmount(daddr); } } void USBHostManager::hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { - //printf("Report Received!\r\n"); for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ - //printf("Sending to add-on %s\r\n", (*it)->name()); (*it)->report_received(dev_addr, instance, report, len); } } void USBHostManager::hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { - printf("Set Report Received!\r\n"); for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ - printf("Sending to add-on %s\r\n", (*it)->name().c_str()); (*it)->set_report_complete(dev_addr, instance, report_id, report_type, len); } } void USBHostManager::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { - printf("Get Report Received!\r\n"); for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ - printf("Sending to add-on %s\r\n", (*it)->name().c_str()); (*it)->get_report_complete(dev_addr, instance, report_id, report_type, len); } } @@ -81,9 +73,9 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re } /// Invoked when device is unmounted (bus reset/unplugged) -void tuh_hid_umount_cb(uint8_t daddr) +void tuh_hid_umount_cb(uint8_t daddr, uint8_t instance) { - USBHostManager::getInstance().hid_umount_cb(daddr); + USBHostManager::getInstance().hid_umount_cb(daddr, instance); } // Invoked when received report from device via interrupt endpoint @@ -96,7 +88,6 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons } } - // On IN/OUT/FEATURE set report callback void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { USBHostManager::getInstance().hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, len); From 7aafe0aaaa370f010984835d2a5c5118c2d40de2 Mon Sep 17 00:00:00 2001 From: Luke A Date: Sat, 12 Aug 2023 01:20:51 -0400 Subject: [PATCH 06/24] Extra add-ons are still causing issues in Core1. Investigate further..... --- src/gp2040aux.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 0aa8f8ebe..20fd0e0db 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -23,11 +23,12 @@ GP2040Aux::~GP2040Aux() { void GP2040Aux::setup() { // Setup Regular Add-ons +/* addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); 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) ) From 64a5b471f8c047ab8610a48215dd59a80a69cce5 Mon Sep 17 00:00:00 2001 From: Luke A Date: Sat, 12 Aug 2023 13:25:44 -0400 Subject: [PATCH 07/24] Moving tuh_task() to core0 seems to fix all the issues i was having --- headers/usbhostmanager.h | 3 +-- src/addons/pspassthrough.cpp | 11 +++++++++++ src/gp2040.cpp | 9 ++------- src/gp2040aux.cpp | 16 +++++++++------- src/usbhostmanager.cpp | 11 ++--------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/headers/usbhostmanager.h b/headers/usbhostmanager.h index 7af5cfea5..f5964fbf5 100644 --- a/headers/usbhostmanager.h +++ b/headers/usbhostmanager.h @@ -19,8 +19,7 @@ class USBHostManager { } void init(uint8_t); void pushAddon(USBAddon *); // If anything needs to update in the gpconfig driver - void processCore0(); // do we separate Core0 and Core1? - void processCore1(); + void process(); void hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); void hid_umount_cb(uint8_t daddr, uint8_t instance); void hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 31c6134a5..433e29ce8 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -120,6 +120,15 @@ void PSPassthroughAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const ps_dev_addr = dev_addr; ps_instance = instance; ps_device_mounted = true; + + uint8_t output_0x03[48]; + output_0x03[0] = 0x03; + memset(&output_0x03[1], 0, 47); + uint8_t* buf = report_buffer; + uint16_t len = sizeof(output_0x03); + memcpy(buf, output_0x03, len); + + tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_DEFINITION, HID_REPORT_TYPE_FEATURE, buf, len); } void PSPassthroughAddon::unmount(uint8_t dev_addr) { @@ -146,6 +155,8 @@ 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: + break; case PS4AuthReport::PS4_RESET_AUTH: awaiting_cb = false; if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready) diff --git a/src/gp2040.cpp b/src/gp2040.cpp index 92eab0130..4e24754b3 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -26,9 +26,6 @@ #include "addons/wiiext.h" #include "addons/snes_input.h" -#include "addons/neopicoleds.h" -#include "addons/pleds.h" - // Pico includes #include "pico/bootrom.h" #include "pico/time.h" @@ -126,8 +123,6 @@ void GP2040::setup() { addons.LoadAddon(new PlayerNumAddon(), CORE0_USBREPORT); addons.LoadAddon(new SliderSOCDInput(), CORE0_INPUT); addons.LoadAddon(new TiltInput(), CORE0_INPUT); - addons.LoadAddon(new NeoPicoLEDAddon(), CORE0_LOOP); - addons.LoadAddon(new PlayerLEDAddon(), CORE0_LOOP); } void GP2040::run() { @@ -147,11 +142,11 @@ void GP2040::run() { continue; } - USBHostManager::getInstance().processCore0(); + USBHostManager::getInstance().process(); // 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; } diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 20fd0e0db..682cb6b88 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -6,13 +6,16 @@ #include "addonmanager.h" #include "usbhostmanager.h" -#include "addons/i2cdisplay.h" // Add-Ons - #include "addons/board_led.h" #include "addons/buzzerspeaker.h" #include "addons/ps4mode.h" #include "addons/pspassthrough.h" + +#include "addons/i2cdisplay.h" // Add-Ons +#include "addons/neopicoleds.h" +#include "addons/pleds.h" + #include GP2040Aux::GP2040Aux() : nextRuntime(0) { @@ -23,12 +26,14 @@ GP2040Aux::~GP2040Aux() { void GP2040Aux::setup() { // Setup Regular Add-ons -/* addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); + addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); + addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); 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) ) @@ -37,10 +42,7 @@ void GP2040Aux::setup() { void GP2040Aux::run() { while (1) { - USBHostManager::getInstance().processCore1(); - if (nextRuntime > getMicro()) { // fix for unsigned - //sleep_us(50); // Give some time back to our CPU (lower power consumption) continue; } addons.ProcessAddons(CORE1_LOOP); diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index db033e00e..bf6358b55 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -18,15 +18,8 @@ void USBHostManager::pushAddon(USBAddon * usbAddon) { // If anything needs to up addons.push_back(usbAddon); } -// Core 0 - USB host manager does nothing for now -void USBHostManager::processCore0() { - if ( !addons.empty() ){ - //tuh_task(); - } -} - -// Core 1 - USB host manager calls TinyUSB Host task -void USBHostManager::processCore1() { +// Host manager should call tuh_task as fast as possible +void USBHostManager::process() { if ( !addons.empty() ){ tuh_task(); } From 3b373a98bad3109d5f869d92a38f2407c0a5edf7 Mon Sep 17 00:00:00 2001 From: Luke A Date: Sat, 12 Aug 2023 15:43:36 -0400 Subject: [PATCH 08/24] Working on Hori PS4, need to update for Magic-S Ultimate --- src/addons/pspassthrough.cpp | 33 ++++++++++++++++++++++----------- src/gp2040aux.cpp | 3 +-- src/usbhostmanager.cpp | 16 ++++++++++++++++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 433e29ce8..98802e181 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -47,7 +47,6 @@ void PSPassthroughAddon::process() { // Did we get the nonce? Let's begin auth if ( PS4Data::getInstance().ps4State == nonce_ready ) { if ( !awaiting_cb ) { // Reset the device auth - uint8_t output_0xf3[] = { 0xf3, 0x0, 0x38, 0x38, 0, 0, 0, 0 }; uint8_t* buf = report_buffer; uint16_t len = sizeof(output_0xf3); memcpy(buf, output_0xf3, len); @@ -121,17 +120,21 @@ void PSPassthroughAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const ps_instance = instance; ps_device_mounted = true; - uint8_t output_0x03[48]; - output_0x03[0] = 0x03; - memset(&output_0x03[1], 0, 47); - uint8_t* buf = report_buffer; - uint16_t len = sizeof(output_0x03); - memcpy(buf, output_0x03, len); + printf("Mounted USB device\r\n"); + + // Reset as soon as its connected + memset(report_buffer, 0, sizeof(report_buffer)); + report_buffer[0] = PS4AuthReport::PS4_DEFINITION; + uint8_t* buf = report_buffer; + uint16_t len = 48; + awaiting_cb = true; tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_DEFINITION, HID_REPORT_TYPE_FEATURE, buf, len); } void PSPassthroughAddon::unmount(uint8_t dev_addr) { + printf("Unmounted USB device\r\n"); + ps_device_mounted = false; nonce_page = 0; // no nonce yet send_nonce_part = 0; // which part of the nonce are we getting from send? @@ -142,7 +145,7 @@ 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: - awaiting_cb = false; + printf("Set Auth Payload\r\n"); if (nonce_page == 5) { nonce_page = 0; passthrough_state = PS4State::signed_nonce_ready; @@ -151,24 +154,31 @@ void PSPassthroughAddon::set_report_complete(uint8_t dev_addr, uint8_t instance, default: break; }; + awaiting_cb = false; } 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: - awaiting_cb = false; + printf("Reset Auth!\r\n"); if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready) passthrough_state = PS4State::receiving_nonce; break; case PS4AuthReport::PS4_GET_SIGNING_STATE: - awaiting_cb = false; + printf("Get signing state!\r\n"); if (report_buffer[2] == 0) passthrough_state = PS4State::sending_nonce; break; case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: - awaiting_cb = false; + 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; @@ -179,4 +189,5 @@ void PSPassthroughAddon::get_report_complete(uint8_t dev_addr, uint8_t instance, default: break; }; + awaiting_cb = false; } diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 682cb6b88..eae031200 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -32,8 +32,7 @@ void GP2040Aux::setup() { addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); 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) ) diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index bf6358b55..e9f7c3625 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -7,6 +7,8 @@ void USBHostManager::init(uint8_t dataPin) { 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); pio_cfg.pin_dp = dataPin; @@ -55,9 +57,20 @@ void USBHostManager::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instan } } +void tuh_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + printf("USBHostManager::tuh_mount_cb\r\n"); + //USBHostManager::getInstance().hid_mount_cb(dev_addr, instance, desc_report, desc_len); + + //if ( !tuh_hid_receive_report(dev_addr, instance) ) { + // Error: cannot request report + //} +} + // TinyUSB Mount Callback void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { + printf("USBHostManager::tuh_hid_mount_cb\r\n"); USBHostManager::getInstance().hid_mount_cb(dev_addr, instance, desc_report, desc_len); if ( !tuh_hid_receive_report(dev_addr, instance) ) { @@ -68,6 +81,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re /// Invoked when device is unmounted (bus reset/unplugged) void tuh_hid_umount_cb(uint8_t daddr, uint8_t instance) { + printf("USBHostManager::tuh_hid_umount_cb\r\n"); USBHostManager::getInstance().hid_umount_cb(daddr, instance); } @@ -83,12 +97,14 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons // On IN/OUT/FEATURE set report callback void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + printf("USBHostManager::tuh_hid_set_report_complete_cb\r\n"); USBHostManager::getInstance().hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, len); } // GET REPORT FEATURE void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { + printf("USBHostManager::tuh_hid_get_report_complete_cb\r\n"); USBHostManager::getInstance().hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len); } From 32236d1160b350f37391019472dd747d7e629d17 Mon Sep 17 00:00:00 2001 From: Luke A Date: Sun, 13 Aug 2023 13:59:56 -0400 Subject: [PATCH 09/24] Pulled correct interface number for tuh_hid_mount_cb() (support for non-0 HID interface devices) --- src/addons/pspassthrough.cpp | 6 +-- src/usbhostmanager.cpp | 96 ++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 98802e181..afdbfbd70 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -47,6 +47,7 @@ void PSPassthroughAddon::process() { // Did we get the nonce? Let's begin auth if ( PS4Data::getInstance().ps4State == nonce_ready ) { if ( !awaiting_cb ) { // Reset the device auth + uint8_t const output_0xf3[] = { 0x0, 0x38, 0x38, 0, 0, 0, 0 }; uint8_t* buf = report_buffer; uint16_t len = sizeof(output_0xf3); memcpy(buf, output_0xf3, len); @@ -120,11 +121,8 @@ void PSPassthroughAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const ps_instance = instance; ps_device_mounted = true; - printf("Mounted USB device\r\n"); - // Reset as soon as its connected memset(report_buffer, 0, sizeof(report_buffer)); - report_buffer[0] = PS4AuthReport::PS4_DEFINITION; uint8_t* buf = report_buffer; uint16_t len = 48; @@ -133,8 +131,6 @@ void PSPassthroughAddon::mount(uint8_t dev_addr, uint8_t instance, uint8_t const } void PSPassthroughAddon::unmount(uint8_t dev_addr) { - printf("Unmounted USB device\r\n"); - ps_device_mounted = false; nonce_page = 0; // no nonce yet send_nonce_part = 0; // which part of the nonce are we getting from send? diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index e9f7c3625..0eecf2522 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -7,10 +7,8 @@ void USBHostManager::init(uint8_t dataPin) { 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); + 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); @@ -57,31 +55,89 @@ void USBHostManager::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instan } } -void tuh_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +static uint8_t _intf_num = 0; + +// Required helper class for HID_REQ_CONTROL_GET_REPORT addition +uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) { - printf("USBHostManager::tuh_mount_cb\r\n"); - //USBHostManager::getInstance().hid_mount_cb(dev_addr, instance, desc_report, desc_len); + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) + { + break; + } - //if ( !tuh_hid_receive_report(dev_addr, instance) ) { - // Error: cannot request report - //} + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; } -// TinyUSB Mount Callback void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { - printf("USBHostManager::tuh_hid_mount_cb\r\n"); - USBHostManager::getInstance().hid_mount_cb(dev_addr, instance, desc_report, desc_len); + // Get Interface Number for our HID class + uint16_t temp_buf[128]; + tusb_desc_configuration_t const* desc_cfg; + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(dev_addr, 0, temp_buf, sizeof(temp_buf))) + { + tusb_desc_configuration_t const* desc_cfg = (tusb_desc_configuration_t*) temp_buf; + uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint8_t const* p_desc = tu_desc_next(desc_cfg); + + // parse each interfaces + while( p_desc < desc_end ) + { + uint8_t assoc_itf_count = 1; + // Class will always starts with Interface Association (if any) and then Interface descriptor + if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) + { + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + + p_desc = tu_desc_next(p_desc); // next to Interface + } + + // must be interface from now + if( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) return; + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + + // only open and listen to HID endpoint IN + if (desc_itf->bInterfaceClass == TUSB_CLASS_HID) + { + _intf_num = desc_itf->bInterfaceNumber; + break; // we got the interface number + } + + // next Interface or IAD descriptor + uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end-p_desc)); + p_desc += drv_len; + } + } // This block can be removed once TinyUSB library incorporates HID_REQ_CONTROL_GET_REPORT callback + USBHostManager::getInstance().hid_mount_cb(dev_addr, instance, desc_report, desc_len); if ( !tuh_hid_receive_report(dev_addr, instance) ) { - // Error: cannot request report + // Error: cannot request report } } /// Invoked when device is unmounted (bus reset/unplugged) void tuh_hid_umount_cb(uint8_t daddr, uint8_t instance) { - printf("USBHostManager::tuh_hid_umount_cb\r\n"); USBHostManager::getInstance().hid_umount_cb(daddr, instance); } @@ -97,18 +153,18 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons // On IN/OUT/FEATURE set report callback void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { - printf("USBHostManager::tuh_hid_set_report_complete_cb\r\n"); - USBHostManager::getInstance().hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, len); + if ( len != 0 ) + USBHostManager::getInstance().hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, len); } // GET REPORT FEATURE void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) { - printf("USBHostManager::tuh_hid_get_report_complete_cb\r\n"); - USBHostManager::getInstance().hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len); + if ( len != 0 ) + USBHostManager::getInstance().hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len); } -// TinyUSB Calls missing from TinyUSB :( +// Request for HID_REQ_CONTROL_GET_REPORT missing from TinyUSB static void get_report_complete(tuh_xfer_t* xfer) { if (tuh_hid_get_report_complete_cb) @@ -136,7 +192,7 @@ bool tuh_hid_get_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u }, .bRequest = HID_REQ_CONTROL_GET_REPORT, .wValue = tu_u16(report_type, report_id), - .wIndex = 0, //hid_itf->itf_num, + .wIndex = _intf_num, // pulled in from tuh_hid_mount_cb() .wLength = len }; From 5388646e5c8ca4cb46270c5b05add7a65dd77f10 Mon Sep 17 00:00:00 2001 From: Luke A Date: Sun, 13 Aug 2023 17:09:11 -0400 Subject: [PATCH 10/24] Fixed timing issues with tuh_task, keyboard host is now working again. 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. --- headers/addonmanager.h | 5 +++-- headers/addons/keyboard_host.h | 3 ++- headers/addons/pspassthrough.h | 8 +++++++- headers/usbhostmanager.h | 9 +++++++-- src/addonmanager.cpp | 22 +++++++++++++++++----- src/addons/keyboard_host.cpp | 19 ++++++------------- src/addons/pspassthrough.cpp | 25 +------------------------ src/gp2040.cpp | 12 +++--------- src/gp2040aux.cpp | 10 ++++++---- src/usbhostmanager.cpp | 27 +++++++++++++++++---------- 10 files changed, 69 insertions(+), 71 deletions(-) diff --git a/headers/addonmanager.h b/headers/addonmanager.h index 62cec6a13..079349d34 100644 --- a/headers/addonmanager.h +++ b/headers/addonmanager.h @@ -2,6 +2,7 @@ #define _ADDONMANAGER_H_ #include "gpaddon.h" +#include "usbaddon.h" #include #include @@ -9,7 +10,6 @@ enum ADDON_PROCESS { CORE0_INPUT, CORE0_USBREPORT, - CORE0_LOOP, CORE1_LOOP }; @@ -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 diff --git a/headers/addons/keyboard_host.h b/headers/addons/keyboard_host.h index 3fd379789..af9c61b04 100644 --- a/headers/addons/keyboard_host.h +++ b/headers/addons/keyboard_host.h @@ -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 @@ -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; diff --git a/headers/addons/pspassthrough.h b/headers/addons/pspassthrough.h index aa81e595b..6275a9520 100644 --- a/headers/addons/pspassthrough.h +++ b/headers/addons/pspassthrough.h @@ -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_ \ No newline at end of file diff --git a/headers/usbhostmanager.h b/headers/usbhostmanager.h index f5964fbf5..566c3bb95 100644 --- a/headers/usbhostmanager.h +++ b/headers/usbhostmanager.h @@ -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); @@ -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 addons; usb_device_t *usb_device; + uint8_t dataPin; + bool tuh_ready; }; #endif \ No newline at end of file diff --git a/src/addonmanager.cpp b/src/addonmanager.cpp index 8b82c1cad..fa1376c95 100644 --- a/src/addonmanager.cpp +++ b/src/addonmanager.cpp @@ -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 diff --git a/src/addons/keyboard_host.cpp b/src/addons/keyboard_host.cpp index e58f2664b..a5294e940 100644 --- a/src/addons/keyboard_host.cpp +++ b/src/addons/keyboard_host.cpp @@ -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)); @@ -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); @@ -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){ @@ -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 ; @@ -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; @@ -168,4 +161,4 @@ void KeyboardHostAddon::process_kbd_report(uint8_t dev_addr, hid_keyboard_report _keyboard_host_state.rt = 0; } } -} +} \ No newline at end of file diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index afdbfbd70..1e92fd2cd 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -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; @@ -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? @@ -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 @@ -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)); @@ -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 @@ -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; @@ -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; diff --git a/src/gp2040.cpp b/src/gp2040.cpp index 4e24754b3..ab62100ad 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -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); @@ -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; } @@ -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; } } diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index eae031200..b0240c913 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -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); @@ -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() { diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index 0eecf2522..f944157ab 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -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 @@ -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(); } } @@ -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::iterator it = addons.begin(); it != addons.end(); it++ ){ - (*it)->unmount(daddr); + (*it)->unmount(dev_addr); } } From 66997cad37b713132fc5d088b8536e5ee32bd95a Mon Sep 17 00:00:00 2001 From: Luke A Date: Sun, 13 Aug 2023 17:14:39 -0400 Subject: [PATCH 11/24] Added PS Passthrough to the BoardConfig.h file --- configs/Pico/BoardConfig.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configs/Pico/BoardConfig.h b/configs/Pico/BoardConfig.h index 7f46f77c8..3e5c15b68 100644 --- a/configs/Pico/BoardConfig.h +++ b/configs/Pico/BoardConfig.h @@ -296,6 +296,11 @@ #define KEYBOARD_HOST_PIN_DPLUS -1 #define KEYBOARD_HOST_PIN_5V -1 +// PS Passthrough Host Addon defaults +#define PSPASSTHROUGH_HOST_ENABLED 0 +#define PSPASSTHROUGH_HOST_PIN_DPLUS -1 +#define PSPASSTHROUGH_HOST_PIN_5V -1 + // For details on this, see: https://gp2040-ce.info/#/development?id=i2c-display-splash #define DEFAULT_SPLASH \ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, \ From 0804696e2d67136096a6bc1653bcc5685cfead9d Mon Sep 17 00:00:00 2001 From: Luke A Date: Sun, 13 Aug 2023 17:24:32 -0400 Subject: [PATCH 12/24] Force PS4 mode to arcade stick for now, will make this a toggle switch in the web config --- lib/TinyUSB_Gamepad/src/ps4_driver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp index 2ae1beeaf..fb3062cdd 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp @@ -62,9 +62,9 @@ ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen) return -1; } memcpy(buf, output_0x03, reqlen); - if ( PS4Data::getInstance().authType == PS4AuthType::PS5_PASSTHROUGH ) { + //if ( PS4Data::getInstance().authType == PS4AuthType::PS5_PASSTHROUGH ) { buf[4] = 0x07; // Tell auth we are an arcade stick - } + //} return reqlen; // Use our private RSA key to sign the nonce and return chunks case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: From 74e721e4ac373553defbdabbf22206be9219d05a Mon Sep 17 00:00:00 2001 From: Luke A Date: Sun, 13 Aug 2023 17:34:19 -0400 Subject: [PATCH 13/24] Broke this as well --- src/usbhostmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index f944157ab..5637d22b9 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -38,7 +38,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) { +void USBHostManager::hid_umount_cb(uint8_t dev_addr, uint8_t instance) { for( std::vector::iterator it = addons.begin(); it != addons.end(); it++ ){ (*it)->unmount(dev_addr); } From 0a0d4ad6060783d0ed66fc0a0da64ecf7ec88a67 Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 12:49:31 -0400 Subject: [PATCH 14/24] Added proper race conditions, updated web page, updated toggle mode in the web config, language is updated, should be ready! --- configs/Pico/BoardConfig.h | 2 ++ headers/usbhostmanager.h | 6 ++++- lib/TinyUSB_Gamepad/src/ps4_driver.cpp | 4 +-- lib/TinyUSB_Gamepad/src/ps4_driver.h | 14 +++-------- proto/config.proto | 1 + proto/enums.proto | 8 ++++++ src/addons/i2cdisplay.cpp | 32 +++++++----------------- src/addons/ps4mode.cpp | 1 - src/addons/pspassthrough.cpp | 1 - src/config_utils.cpp | 1 + src/configs/webconfig.cpp | 2 ++ src/gamepad.cpp | 7 ++++++ src/gp2040.cpp | 2 ++ src/gp2040aux.cpp | 4 +-- src/usbhostmanager.cpp | 15 +++++++++++- www/server/app.js | 1 + www/src/Locales/en/AddonsConfig.jsx | 2 +- www/src/Locales/en/SettingsPage.jsx | 6 +++++ www/src/Pages/SettingsPage.jsx | 34 +++++++++++++++++++++++--- 19 files changed, 96 insertions(+), 47 deletions(-) diff --git a/configs/Pico/BoardConfig.h b/configs/Pico/BoardConfig.h index 3e5c15b68..f707cb3e4 100644 --- a/configs/Pico/BoardConfig.h +++ b/configs/Pico/BoardConfig.h @@ -62,6 +62,8 @@ #define DEFAULT_INPUT_MODE INPUT_MODE_XINPUT //INPUT_MODE_XINPUT (XInput), INPUT_MODE_SWITCH (Nintendo Switch), INPUT_MODE_HID (D-Input), INPUT_MODE_KEYBOARD (Keyboard) #define DEFAULT_DPAD_MODE DPAD_MODE_DIGITAL //DPAD_MODE_DIGITAL, DPAD_MODE_LEFT_ANALOG, DPAD_MODE_RIGHT_ANALOG, +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/headers/usbhostmanager.h b/headers/usbhostmanager.h index 566c3bb95..ccc525a17 100644 --- a/headers/usbhostmanager.h +++ b/headers/usbhostmanager.h @@ -18,6 +18,8 @@ class USBHostManager { return instance; } void setDataPin(uint8_t); // start USB host (change CPU, setup PIO PICO usb pin) + void readyCore0(); // Core 0 - READY + void readyCore1(); // Core 1 - READY void start(); void pushAddon(USBAddon *); // If anything needs to update in the gpconfig driver void process(); @@ -27,12 +29,14 @@ 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() : tuh_ready(false) { + USBHostManager() : tuh_ready(false), core0Ready(false), core1Ready(false) { } std::vector addons; usb_device_t *usb_device; uint8_t dataPin; + bool core0Ready; + bool core1Ready; bool tuh_ready; }; diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp index fb3062cdd..5af9499b8 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.cpp +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.cpp @@ -62,9 +62,7 @@ ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen) return -1; } memcpy(buf, output_0x03, reqlen); - //if ( PS4Data::getInstance().authType == PS4AuthType::PS5_PASSTHROUGH ) { - buf[4] = 0x07; // Tell auth we are an arcade stick - //} + buf[4] = (uint8_t)PS4Data::getInstance().ps4ControllerType; // Change controller type in definition return reqlen; // Use our private RSA key to sign the nonce and return chunks case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: diff --git a/lib/TinyUSB_Gamepad/src/ps4_driver.h b/lib/TinyUSB_Gamepad/src/ps4_driver.h index 3788bf54f..5a40652ec 100644 --- a/lib/TinyUSB_Gamepad/src/ps4_driver.h +++ b/lib/TinyUSB_Gamepad/src/ps4_driver.h @@ -10,6 +10,8 @@ #include "gamepad/descriptors/PS4Descriptors.h" +#include "enums.pb.h" + #define PS4_OUT_SIZE 64 typedef enum @@ -21,13 +23,6 @@ typedef enum PS4_RESET_AUTH = 0xF3 // Unknown (PS4 Report 0xF3) } PS4AuthReport; -typedef enum -{ - NO_AUTH = 0, - PS4_KEY = 1, - PS5_PASSTHROUGH = 2 -} PS4AuthType; - // USB endpoint state vars extern const usbd_class_driver_t ps4_driver; @@ -72,15 +67,14 @@ class PS4Data { // buffer = 256 + 16 + 256 + 256 + 256 + 24 // == 1064 bytes (almost 1 kb) uint8_t ps4_auth_buffer[1064]; - - PS4AuthType authType; + uint32_t ps4ControllerType; private: PS4Data() { ps4State = PS4State::no_nonce; - authType = PS4AuthType::NO_AUTH; authsent = false; memset(nonce_buffer, 0, 256); memset(ps4_auth_buffer, 0, 1064); + ps4ControllerType = PS4ControllerType::PS4_CONTROLLER; } }; diff --git a/proto/config.proto b/proto/config.proto index 4f12b8287..1973faf1e 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -14,6 +14,7 @@ message GamepadOptions optional bool lockHotkeys = 7; optional bool fourWayMode = 8; optional uint32 profileNumber = 9; + optional uint32 ps4ControllerType = 10; } message KeyboardMapping diff --git a/proto/enums.proto b/proto/enums.proto index bdfd3ce3f..85fe61951 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -180,3 +180,11 @@ enum ForcedSetupMode FORCED_SETUP_MODE_LOCK_WEB_CONFIG = 2; FORCED_SETUP_MODE_LOCK_BOTH = 3; }; + +enum PS4ControllerType +{ + option (nanopb_enumopt).long_names = false; + + PS4_CONTROLLER = 0; + PS4_ARCADESTICK = 7; +} diff --git a/src/addons/i2cdisplay.cpp b/src/addons/i2cdisplay.cpp index eeaabcef4..cab913527 100644 --- a/src/addons/i2cdisplay.cpp +++ b/src/addons/i2cdisplay.cpp @@ -937,32 +937,18 @@ void I2CDisplayAddon::drawStatusBar(Gamepad * gamepad) case INPUT_MODE_SWITCH: statusBar += "SWITCH"; break; case INPUT_MODE_XINPUT: statusBar += "XINPUT"; break; case INPUT_MODE_PS4: - if (PS4Data::getInstance().authsent == true ) { - switch ( PS4Data::getInstance().authType ) { - case PS4AuthType::PS4_KEY: + switch ( PS4Data::getInstance().ps4ControllerType ) { + if ( PS4Data::getInstance().ps4ControllerType == PS4ControllerType::PS4_CONTROLLER ) { + if (PS4Data::getInstance().authsent == true ) statusBar += "PS4:AS"; - break; - case PS4AuthType::PS5_PASSTHROUGH: - statusBar += "PS5:AS"; - break; - case PS4AuthType::NO_AUTH: - default: - statusBar += "PS?:AS"; - break; - }; - } else { - switch ( PS4Data::getInstance().authType ) { - case PS4AuthType::PS4_KEY: + else statusBar += "PS4 "; - break; - case PS4AuthType::PS5_PASSTHROUGH: + } else if ( PS4Data::getInstance().ps4ControllerType == PS4ControllerType::PS4_ARCADESTICK ) { + if (PS4Data::getInstance().authsent == true ) + statusBar += "PS5:AS"; + else statusBar += "PS5 "; - break; - case PS4AuthType::NO_AUTH: - default: - statusBar += "PS4:NK"; - break; - }; + } } break; case INPUT_MODE_KEYBOARD: statusBar += "HID-KB"; break; diff --git a/src/addons/ps4mode.cpp b/src/addons/ps4mode.cpp index 5f1b5903e..f1fadd8eb 100644 --- a/src/addons/ps4mode.cpp +++ b/src/addons/ps4mode.cpp @@ -45,7 +45,6 @@ void PS4ModeAddon::setup() { if (mbedtls_rsa_import(&rsa_context, &N, &P, &Q, nullptr, &E) == 0 && mbedtls_rsa_complete(&rsa_context) == 0) { ready = true; - PS4Data::getInstance().authType = PS4AuthType::PS4_KEY; } DELETE_CONFIG_MPI(N) diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 1e92fd2cd..5f6951e57 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -28,7 +28,6 @@ void PSPassthroughAddon::setup() { send_nonce_part = 0; // which part of the nonce are we getting from send? awaiting_cb = false; // did we receive the sign state yet passthrough_state = PS4State::no_nonce; - PS4Data::getInstance().authType = PS4AuthType::PS5_PASSTHROUGH; } void PSPassthroughAddon::process() { diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 2cedc8a5e..6c98b0e11 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -99,6 +99,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.gamepadOptions, lockHotkeys, DEFAULT_LOCK_HOTKEYS); INIT_UNSET_PROPERTY(config.gamepadOptions, fourWayMode, false); INIT_UNSET_PROPERTY(config.gamepadOptions, profileNumber, 1); + INIT_UNSET_PROPERTY(config.gamepadOptions, ps4ControllerType, DEFAULT_PS4CONTROLLER_TYPE); // hotkeyOptions HotkeyOptions& hotkeyOptions = config.hotkeyOptions; diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index 1b3623c22..510e60848 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -570,6 +570,7 @@ std::string setGamepadOptions() readDoc(gamepadOptions.lockHotkeys, doc, "lockHotkeys"); readDoc(gamepadOptions.fourWayMode, doc, "fourWayMode"); readDoc(gamepadOptions.profileNumber, doc, "profileNumber"); + readDoc(gamepadOptions.ps4ControllerType, doc, "PS4ControllerType"); HotkeyOptions& hotkeyOptions = Storage::getInstance().getHotkeyOptions(); save_hotkey(&hotkeyOptions.hotkey01, doc, "hotkey01"); @@ -605,6 +606,7 @@ std::string getGamepadOptions() writeDoc(doc, "lockHotkeys", gamepadOptions.lockHotkeys ? 1 : 0); writeDoc(doc, "fourWayMode", gamepadOptions.fourWayMode ? 1 : 0); writeDoc(doc, "profileNumber", gamepadOptions.profileNumber); + writeDoc(doc, "PS4ControllerType", gamepadOptions.ps4ControllerType); const PinMappings& pinMappings = Storage::getInstance().getPinMappings(); writeDoc(doc, "fnButtonPin", pinMappings.pinButtonFn); diff --git a/src/gamepad.cpp b/src/gamepad.cpp index 9d9dd7adc..fb939f39d 100644 --- a/src/gamepad.cpp +++ b/src/gamepad.cpp @@ -13,6 +13,9 @@ #include "storagemanager.h" +// PS5 compatibility +#include "ps4_driver.h" + // MUST BE DEFINED for mpgs uint32_t getMillis() { return to_ms_since_boot(get_absolute_time()); @@ -95,6 +98,7 @@ void Gamepad::setup() { // Configure pin mapping const PinMappings& pinMappings = Storage::getInstance().getProfilePinMappings(); + const GamepadOptions& gamepadOptions = Storage::getInstance().getGamepadOptions(); const auto convertPin = [](int32_t pin) -> uint8_t { return isValidPin(pin) ? pin : 0xff; }; mapDpadUp = new GamepadButtonMapping(convertPin(pinMappings.pinDpadUp), GAMEPAD_MASK_UP); @@ -141,6 +145,9 @@ void Gamepad::setup() gpio_set_dir(pinMappings.pinButtonFn, GPIO_IN); // Set as INPUT gpio_pull_up(pinMappings.pinButtonFn); // Set as PULLUP } + + // setup PS5 compatibility + PS4Data::getInstance().ps4ControllerType = gamepadOptions.ps4ControllerType; } /** diff --git a/src/gp2040.cpp b/src/gp2040.cpp index ab62100ad..eed6e3146 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -120,6 +120,8 @@ void GP2040::setup() { addons.LoadAddon(new PlayerNumAddon(), CORE0_USBREPORT); addons.LoadAddon(new SliderSOCDInput(), CORE0_INPUT); addons.LoadAddon(new TiltInput(), CORE0_INPUT); + + USBHostManager::getInstance().readyCore0(); } void GP2040::run() { diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index b0240c913..36f4fcc19 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -36,9 +36,7 @@ void GP2040Aux::setup() { addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); - - - USBHostManager::getInstance().start(); + USBHostManager::getInstance().readyCore1(); } void GP2040Aux::run() { diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index 5637d22b9..42c7062c3 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -8,10 +8,23 @@ void USBHostManager::setDataPin(uint8_t inPin) { dataPin = inPin; } +void USBHostManager::readyCore0() { + core0Ready = true; + if ( core0Ready && core1Ready ){ + start(); + } +} + +void USBHostManager::readyCore1() { + core1Ready = true; + if ( core0Ready && core1Ready ){ + start(); + } +} + 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; diff --git a/www/server/app.js b/www/server/app.js index 1dfd58a57..1870dbe8a 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -93,6 +93,7 @@ app.get("/api/getGamepadOptions", (req, res) => { fourWayMode: 0, fnButtonPin: -1, profileNumber: 1, + ps4ControllerType: 0, hotkey01: { auxMask: 32768, buttonsMask: 66304, diff --git a/www/src/Locales/en/AddonsConfig.jsx b/www/src/Locales/en/AddonsConfig.jsx index 033f79fab..8e0876a5e 100644 --- a/www/src/Locales/en/AddonsConfig.jsx +++ b/www/src/Locales/en/AddonsConfig.jsx @@ -118,7 +118,7 @@ export default { 'keyboard-host-d-plus-label': 'D+', 'keyboard-host-d-minus-label': 'D-', 'keyboard-host-five-v-label': '5V Power (optional)', - 'pspassthrough-header-text': 'PS Passthrough Configuration', + 'pspassthrough-header-text': 'PS Passthrough', 'pspassthrough-sub-header-text': 'Following set the data +, - and 5V (optional) pins. Only the + and 5V pin can be configured.', 'pspassthrough-d-plus-label': 'D+', 'pspassthrough-d-minus-label': 'D-', diff --git a/www/src/Locales/en/SettingsPage.jsx b/www/src/Locales/en/SettingsPage.jsx index cdb80ef98..558cf5f36 100644 --- a/www/src/Locales/en/SettingsPage.jsx +++ b/www/src/Locales/en/SettingsPage.jsx @@ -2,6 +2,7 @@ export default { 'settings-header-text': 'Settings', 'input-mode-label': 'Input Mode', 'input-mode-extra-label': 'Switch Touchpad and Share', + 'input-mode-PS4ControllerType-label': 'PS4 Controller Type', 'input-mode-options': { 'xinput': "XInput", 'nintendo-switch': "Nintendo Switch", @@ -9,6 +10,10 @@ export default { 'keyboard': "Keyboard", 'ps4': "PS4" }, + 'ps4-mode-options': { + 'controller': "Controller", + 'arcadestick': "Arcade Stick", + }, 'd-pad-mode-label': 'D-Pad Mode', 'd-pad-mode-options': { "d-pad": "D-Pad", @@ -25,6 +30,7 @@ export default { 'off': 'Off' }, 'profile-number-label': 'Profile Number', + 'ps4-compatibility-label': 'For PS5 compatibility, use "Arcade Stick" and enable PS Passthrough add-on
For PS4 support, use "Controller" and enable PS4 Mode add-on if you have the necessary files', 'hotkey-settings-label': 'Hotkey Settings', 'hotkey-settings-sub-header': "The <1>Fn slider provides a mappable Function button in the <3 exact='true' to='/pin-mapping'>Pin Mapping page. By selecting the <1>Fn slider option, the Function button must be held along with the selected hotkey settings.<5 />Additionally, select <1>None from the dropdown to unassign any button.", 'hotkey-settings-warning': 'Function button is not mapped. The Fn slider will be disabled.', diff --git a/www/src/Pages/SettingsPage.jsx b/www/src/Pages/SettingsPage.jsx index bd960c31e..3a09a0bd0 100644 --- a/www/src/Pages/SettingsPage.jsx +++ b/www/src/Pages/SettingsPage.jsx @@ -33,6 +33,11 @@ const SOCD_MODES = [ { labelKey: 'socd-cleaning-mode-options.off', value: 4 }, ]; +const PS4_MODES = [ + { labelKey: 'ps4-mode-options.controller', value: 0 }, + { labelKey: 'ps4-mode-options.arcadestick', value: 7 }, +]; + const HOTKEY_ACTIONS = [ { labelKey: 'hotkey-actions.no-action', value: 0 }, { labelKey: 'hotkey-actions.dpad-digital', value: 1 }, @@ -88,6 +93,7 @@ const schema = yup.object().shape({ lockHotkeys: yup.number().required().label('Lock Hotkeys'), fourWayMode: yup.number().required().label('4-Way Joystick Mode'), profileNumber: yup.number().required().label('Profile Number'), + ps4ControllerType: yup.number().required().label('PS4 Controller Type'), }); const FormContext = ({ setButtonLabels }) => { @@ -120,6 +126,8 @@ const FormContext = ({ setButtonLabels }) => { values.fourWayMode = parseInt(values.fourWayMode); if (!!values.profileNumber) values.profileNumber = parseInt(values.profileNumber); + if (!!values.ps4ControllerType) + values.ps4ControllerType = parseInt(values.ps4ControllerType); setButtonLabels({ swapTpShareLabels: (values.switchTpShareForDs4 === 1) && (values.inputMode === 4) }); @@ -184,6 +192,7 @@ export default function SettingsPage() { const translatedSocdModes = translateArray(SOCD_MODES); const translatedHotkeyActions = translateArray(HOTKEY_ACTIONS); const translatedForcedSetupModes = translateArray(FORCED_SETUP_MODES); + const translatedPS4ControllerTypeModes = translateArray(PS4_MODES); return ( @@ -205,16 +214,35 @@ export default function SettingsPage() { {errors.inputMode}
+ {(values.inputMode === PS4Mode) &&
- {values.inputMode === PS4Mode && { setFieldValue("switchTpShareForDs4", e.target.checked ? 1 : 0); }} - />} -
+ /> + } + {(values.inputMode === PS4Mode) && +
+ + + {translatedPS4ControllerTypeModes.map((o, i) => )} + +
} + {(values.inputMode === PS4Mode) && +
+ + For PS5 compatibility, use "Arcade Stick" and enable PS Passthrough add-on
For PS4 support, use "Controller" and enable PS4 Mode add-on if you have the necessary files +
+
} {t('SettingsPage:d-pad-mode-label')} From 7252371036870ae80539c9d2dd176081dfbbc5b0 Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 12:59:57 -0400 Subject: [PATCH 15/24] Added #define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER to board configs --- configs/AlpacaOwO/BoardConfig.h | 2 ++ configs/BentoBox/BoardConfig.h | 2 ++ configs/DURAL/BoardConfig.h | 2 ++ configs/FightboardV3/BoardConfig.h | 2 ++ configs/FightboardV3Mirrored/BoardConfig.h | 2 ++ configs/FlatboxRev4/BoardConfig.h | 2 ++ configs/FlatboxRev5/BoardConfig.h | 2 ++ configs/FlatboxRev5RGB/BoardConfig.h | 2 ++ configs/KB2040/BoardConfig.h | 2 ++ configs/KeyboardConverter/BoardConfig.h | 2 ++ configs/MavercadeKeebfighter/BoardConfig.h | 2 ++ configs/PicoAnn/BoardConfig.h | 2 ++ configs/PicoFightingBoard/BoardConfig.h | 2 ++ configs/RP2040AdvancedBreakoutBoard/BoardConfig.h | 2 ++ configs/RP2040MiniBreakoutBoard/BoardConfig.h | 2 ++ configs/ReflexEncoder/BoardConfig.h | 2 ++ configs/SGFDevices/BoardConfig.h | 1 + configs/SparkFunProMicro/BoardConfig.h | 3 +++ configs/Stress/BoardConfig.h | 2 ++ configs/WaveshareZero/BoardConfig.h | 2 ++ 20 files changed, 40 insertions(+) diff --git a/configs/AlpacaOwO/BoardConfig.h b/configs/AlpacaOwO/BoardConfig.h index 3091b08c8..fa149e544 100644 --- a/configs/AlpacaOwO/BoardConfig.h +++ b/configs/AlpacaOwO/BoardConfig.h @@ -63,6 +63,8 @@ #define DEFAULT_INPUT_MODE INPUT_MODE_XINPUT //INPUT_MODE_XINPUT (XInput), INPUT_MODE_SWITCH (Nintendo Switch), INPUT_MODE_HID (D-Input), INPUT_MODE_KEYBOARD (Keyboard) #define DEFAULT_DPAD_MODE DPAD_MODE_DIGITAL //DPAD_MODE_DIGITAL, DPAD_MODE_LEFT_ANALOG, DPAD_MODE_RIGHT_ANALOG, +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/BentoBox/BoardConfig.h b/configs/BentoBox/BoardConfig.h index c77cf99d2..99355ee68 100644 --- a/configs/BentoBox/BoardConfig.h +++ b/configs/BentoBox/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/DURAL/BoardConfig.h b/configs/DURAL/BoardConfig.h index c3f005884..74e039022 100644 --- a/configs/DURAL/BoardConfig.h +++ b/configs/DURAL/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/FightboardV3/BoardConfig.h b/configs/FightboardV3/BoardConfig.h index e89ba091f..2f13fdb9c 100644 --- a/configs/FightboardV3/BoardConfig.h +++ b/configs/FightboardV3/BoardConfig.h @@ -61,6 +61,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/FightboardV3Mirrored/BoardConfig.h b/configs/FightboardV3Mirrored/BoardConfig.h index 6b9c52209..df07c7b7b 100644 --- a/configs/FightboardV3Mirrored/BoardConfig.h +++ b/configs/FightboardV3Mirrored/BoardConfig.h @@ -61,6 +61,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/FlatboxRev4/BoardConfig.h b/configs/FlatboxRev4/BoardConfig.h index 7201ede80..1b471c711 100644 --- a/configs/FlatboxRev4/BoardConfig.h +++ b/configs/FlatboxRev4/BoardConfig.h @@ -82,6 +82,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/FlatboxRev5/BoardConfig.h b/configs/FlatboxRev5/BoardConfig.h index 41c2ab315..3ddc55627 100644 --- a/configs/FlatboxRev5/BoardConfig.h +++ b/configs/FlatboxRev5/BoardConfig.h @@ -82,6 +82,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/FlatboxRev5RGB/BoardConfig.h b/configs/FlatboxRev5RGB/BoardConfig.h index 4b3b2533f..3a86a0d05 100644 --- a/configs/FlatboxRev5RGB/BoardConfig.h +++ b/configs/FlatboxRev5RGB/BoardConfig.h @@ -82,6 +82,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/KB2040/BoardConfig.h b/configs/KB2040/BoardConfig.h index c79ce1d79..77526f7d3 100644 --- a/configs/KB2040/BoardConfig.h +++ b/configs/KB2040/BoardConfig.h @@ -61,6 +61,8 @@ #define DEFAULT_INPUT_MODE INPUT_MODE_XINPUT //INPUT_MODE_XINPUT (XInput), INPUT_MODE_SWITCH (Nintendo Switch), INPUT_MODE_HID (D-Input), INPUT_MODE_KEYBOARD (Keyboard) #define DEFAULT_DPAD_MODE DPAD_MODE_DIGITAL //DPAD_MODE_DIGITAL, DPAD_MODE_LEFT_ANALOG, DPAD_MODE_RIGHT_ANALOG, +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF #define DEFAULT_LOCK_HOTKEYS false// This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) diff --git a/configs/KeyboardConverter/BoardConfig.h b/configs/KeyboardConverter/BoardConfig.h index 06640b1c8..4ee7ea63f 100644 --- a/configs/KeyboardConverter/BoardConfig.h +++ b/configs/KeyboardConverter/BoardConfig.h @@ -63,6 +63,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/MavercadeKeebfighter/BoardConfig.h b/configs/MavercadeKeebfighter/BoardConfig.h index 026be1eaa..c0dec1b4e 100644 --- a/configs/MavercadeKeebfighter/BoardConfig.h +++ b/configs/MavercadeKeebfighter/BoardConfig.h @@ -82,6 +82,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/PicoAnn/BoardConfig.h b/configs/PicoAnn/BoardConfig.h index 6ebe3e7f3..5892a95ed 100644 --- a/configs/PicoAnn/BoardConfig.h +++ b/configs/PicoAnn/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/PicoFightingBoard/BoardConfig.h b/configs/PicoFightingBoard/BoardConfig.h index 7053e9ff9..394fbc1e2 100644 --- a/configs/PicoFightingBoard/BoardConfig.h +++ b/configs/PicoFightingBoard/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/RP2040AdvancedBreakoutBoard/BoardConfig.h b/configs/RP2040AdvancedBreakoutBoard/BoardConfig.h index 1c702a43d..53580b35d 100644 --- a/configs/RP2040AdvancedBreakoutBoard/BoardConfig.h +++ b/configs/RP2040AdvancedBreakoutBoard/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/RP2040MiniBreakoutBoard/BoardConfig.h b/configs/RP2040MiniBreakoutBoard/BoardConfig.h index 15fd5eb68..d506ee35f 100644 --- a/configs/RP2040MiniBreakoutBoard/BoardConfig.h +++ b/configs/RP2040MiniBreakoutBoard/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/ReflexEncoder/BoardConfig.h b/configs/ReflexEncoder/BoardConfig.h index c9e71cf2a..061ff63ad 100644 --- a/configs/ReflexEncoder/BoardConfig.h +++ b/configs/ReflexEncoder/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/SGFDevices/BoardConfig.h b/configs/SGFDevices/BoardConfig.h index 4f5373bd2..061f16bc7 100644 --- a/configs/SGFDevices/BoardConfig.h +++ b/configs/SGFDevices/BoardConfig.h @@ -81,6 +81,7 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) diff --git a/configs/SparkFunProMicro/BoardConfig.h b/configs/SparkFunProMicro/BoardConfig.h index 1da61b689..b7577deb1 100644 --- a/configs/SparkFunProMicro/BoardConfig.h +++ b/configs/SparkFunProMicro/BoardConfig.h @@ -52,6 +52,9 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true + +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/Stress/BoardConfig.h b/configs/Stress/BoardConfig.h index 84d75ec6b..d03935006 100644 --- a/configs/Stress/BoardConfig.h +++ b/configs/Stress/BoardConfig.h @@ -59,6 +59,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. diff --git a/configs/WaveshareZero/BoardConfig.h b/configs/WaveshareZero/BoardConfig.h index 78c664091..3594792ab 100644 --- a/configs/WaveshareZero/BoardConfig.h +++ b/configs/WaveshareZero/BoardConfig.h @@ -60,6 +60,8 @@ #define DEFAULT_FORCED_SETUP_MODE FORCED_SETUP_MODE_OFF // FORCED_SETUP_MODE_OFF, FORCED_SETUP_MODE_LOCK_MODE_SWITCH, FORCED_SETUP_MODE_LOCK_WEB_CONFIG, FORCED_SETUP_MODE_LOCK_BOTH #define DEFAULT_LOCK_HOTKEYS false // or true +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER + // This is the LEDs section. // The default `TURBO_LED_PIN` pin is set to `15` ( it is recommended to run through 3V3(OUT) with a resistor) // The Turbo LED will flash at a speed consistant with the set speed of the Turbo when a Turbo button is active. From e592863dac7028b0849182bbfd0eba137f6c72da Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 13:46:52 -0400 Subject: [PATCH 16/24] Fix PS4 controller type error --- www/src/Pages/SettingsPage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/src/Pages/SettingsPage.jsx b/www/src/Pages/SettingsPage.jsx index 3a09a0bd0..a7802f47c 100644 --- a/www/src/Pages/SettingsPage.jsx +++ b/www/src/Pages/SettingsPage.jsx @@ -93,7 +93,7 @@ const schema = yup.object().shape({ lockHotkeys: yup.number().required().label('Lock Hotkeys'), fourWayMode: yup.number().required().label('4-Way Joystick Mode'), profileNumber: yup.number().required().label('Profile Number'), - ps4ControllerType: yup.number().required().label('PS4 Controller Type'), + ps4ControllerType: yup.number().required().oneOf(PS4_MODES.map(o => o.value)).label('PS4 Controller Type'), }); const FormContext = ({ setButtonLabels }) => { From 3e84ba206adcec0e027fb0f8015b9ccb77ee0ea3 Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 14:02:27 -0400 Subject: [PATCH 17/24] Match capitalization to WebConfig --- src/configs/webconfig.cpp | 4 ++-- www/src/Locales/en/SettingsPage.jsx | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index 510e60848..c0a453fff 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -570,7 +570,7 @@ std::string setGamepadOptions() readDoc(gamepadOptions.lockHotkeys, doc, "lockHotkeys"); readDoc(gamepadOptions.fourWayMode, doc, "fourWayMode"); readDoc(gamepadOptions.profileNumber, doc, "profileNumber"); - readDoc(gamepadOptions.ps4ControllerType, doc, "PS4ControllerType"); + readDoc(gamepadOptions.ps4ControllerType, doc, "ps4ControllerType"); HotkeyOptions& hotkeyOptions = Storage::getInstance().getHotkeyOptions(); save_hotkey(&hotkeyOptions.hotkey01, doc, "hotkey01"); @@ -606,7 +606,7 @@ std::string getGamepadOptions() writeDoc(doc, "lockHotkeys", gamepadOptions.lockHotkeys ? 1 : 0); writeDoc(doc, "fourWayMode", gamepadOptions.fourWayMode ? 1 : 0); writeDoc(doc, "profileNumber", gamepadOptions.profileNumber); - writeDoc(doc, "PS4ControllerType", gamepadOptions.ps4ControllerType); + writeDoc(doc, "ps4ControllerType", gamepadOptions.ps4ControllerType); const PinMappings& pinMappings = Storage::getInstance().getPinMappings(); writeDoc(doc, "fnButtonPin", pinMappings.pinButtonFn); diff --git a/www/src/Locales/en/SettingsPage.jsx b/www/src/Locales/en/SettingsPage.jsx index 558cf5f36..79de1a33f 100644 --- a/www/src/Locales/en/SettingsPage.jsx +++ b/www/src/Locales/en/SettingsPage.jsx @@ -2,7 +2,6 @@ export default { 'settings-header-text': 'Settings', 'input-mode-label': 'Input Mode', 'input-mode-extra-label': 'Switch Touchpad and Share', - 'input-mode-PS4ControllerType-label': 'PS4 Controller Type', 'input-mode-options': { 'xinput': "XInput", 'nintendo-switch': "Nintendo Switch", From 9002f6705b57b58379a88c3264def20ba615f348 Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 15:12:01 -0400 Subject: [PATCH 18/24] Set "ALWAYS" vs. "LOOP" add-ons for core1 --- headers/addonmanager.h | 1 + src/gp2040aux.cpp | 15 +++++++++++---- www/src/Pages/SettingsPage.jsx | 1 - 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/headers/addonmanager.h b/headers/addonmanager.h index 079349d34..2ea368728 100644 --- a/headers/addonmanager.h +++ b/headers/addonmanager.h @@ -10,6 +10,7 @@ enum ADDON_PROCESS { CORE0_INPUT, CORE0_USBREPORT, + CORE1_ALWAYS, CORE1_LOOP }; diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 36f4fcc19..11e6e7418 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -29,9 +29,9 @@ void GP2040Aux::setup() { addons.LoadUSBAddon(new PSPassthroughAddon(), CORE1_LOOP); // Setup Regular Add-ons - addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); - addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); - addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); + addons.LoadAddon(new I2CDisplayAddon(), CORE1_ALWAYS); + addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_ALWAYS); + addons.LoadAddon(new PlayerLEDAddon(), CORE1_ALWAYS); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); @@ -40,11 +40,18 @@ void GP2040Aux::setup() { } void GP2040Aux::run() { + bool configMode = Storage::getInstance().GetConfigMode(); while (1) { if (nextRuntime > getMicro()) { // fix for unsigned continue; } - addons.ProcessAddons(CORE1_LOOP); + + addons.ProcessAddons(CORE1_ALWAYS); + + // Config Loop (Only run "ALWAYS" add-ons) + if (configMode == false) + addons.ProcessAddons(CORE1_LOOP); + nextRuntime = getMicro() + GAMEPAD_POLL_MICRO; } } diff --git a/www/src/Pages/SettingsPage.jsx b/www/src/Pages/SettingsPage.jsx index a7802f47c..25d15d01e 100644 --- a/www/src/Pages/SettingsPage.jsx +++ b/www/src/Pages/SettingsPage.jsx @@ -227,7 +227,6 @@ export default function SettingsPage() { } {(values.inputMode === PS4Mode) &&
- Date: Mon, 14 Aug 2023 15:40:04 -0400 Subject: [PATCH 19/24] Moved CPU Frequency to start of setup() and removed alarm pool as it seems incorrect. --- src/addons/keyboard_host.cpp | 2 ++ src/addons/pspassthrough.cpp | 2 ++ src/usbhostmanager.cpp | 3 +-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/addons/keyboard_host.cpp b/src/addons/keyboard_host.cpp index a5294e940..a15dd5985 100644 --- a/src/addons/keyboard_host.cpp +++ b/src/addons/keyboard_host.cpp @@ -10,6 +10,8 @@ bool KeyboardHostAddon::available() { } void KeyboardHostAddon::setup() { + set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions; const KeyboardMapping& keyboardMapping = keyboardHostOptions.mapping; diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index 5f6951e57..bf880ed08 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -13,6 +13,8 @@ bool PSPassthroughAddon::available() { } void PSPassthroughAddon::setup() { + set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; if (psOptions.pin5V != -1) { // Feather USB-A's require this diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index 42c7062c3..78a0a4489 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -24,9 +24,8 @@ void USBHostManager::readyCore1() { void USBHostManager::start() { if ( !addons.empty() ) { - 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.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); From c8abb2aec07ba7574a1af7ed65657b36fd5b26fd Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 16:37:33 -0400 Subject: [PATCH 20/24] Fixed Core0/Core1 sync issues, all usb host add-ons should live on Core0 it seems. --- headers/usbhostmanager.h | 2 -- src/addons/pspassthrough.cpp | 2 +- src/gp2040.cpp | 11 ++++++++++- src/gp2040aux.cpp | 25 ++++++------------------- src/usbhostmanager.cpp | 16 +--------------- 5 files changed, 18 insertions(+), 38 deletions(-) diff --git a/headers/usbhostmanager.h b/headers/usbhostmanager.h index ccc525a17..154a0fc34 100644 --- a/headers/usbhostmanager.h +++ b/headers/usbhostmanager.h @@ -18,8 +18,6 @@ class USBHostManager { return instance; } void setDataPin(uint8_t); // start USB host (change CPU, setup PIO PICO usb pin) - void readyCore0(); // Core 0 - READY - void readyCore1(); // Core 1 - READY void start(); void pushAddon(USBAddon *); // If anything needs to update in the gpconfig driver void process(); diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index bf880ed08..f2ee0ec44 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -9,7 +9,7 @@ bool PSPassthroughAddon::available() { const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; return psOptions.enabled && isValidPin(psOptions.pinDplus) && - (psOptions.pin5V == -1 || isValidPin(psOptions.pin5V)); + (psOptions.pin5V == -1 || isValidPin(psOptions.pin5V)); } void PSPassthroughAddon::setup() { diff --git a/src/gp2040.cpp b/src/gp2040.cpp index eed6e3146..74c476124 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -20,6 +20,7 @@ #include "addons/i2canalog1219.h" #include "addons/jslider.h" #include "addons/playernum.h" +#include "addons/pspassthrough.h" #include "addons/reverse.h" #include "addons/turbo.h" #include "addons/slider_socd.h" @@ -49,6 +50,13 @@ GP2040::~GP2040() { } void GP2040::setup() { + // Reduce CPU if any USB host add-on is enabled + const AddonOptions & addonOptions = Storage::getInstance().getAddonOptions(); + if ( addonOptions.keyboardHostOptions.enabled || + addonOptions.psPassthroughOptions.enabled ){ + set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues + } + // Setup Gamepad and Gamepad Storage Gamepad * gamepad = Storage::getInstance().GetGamepad(); gamepad->setup(); @@ -104,6 +112,7 @@ void GP2040::setup() { // Setup USB add-ons addons.LoadUSBAddon(new KeyboardHostAddon(), CORE0_INPUT); + addons.LoadUSBAddon(new PSPassthroughAddon(), CORE0_USBREPORT); // Setup Regular Add-ons addons.LoadAddon(new AnalogInput(), CORE0_INPUT); @@ -121,7 +130,7 @@ void GP2040::setup() { addons.LoadAddon(new SliderSOCDInput(), CORE0_INPUT); addons.LoadAddon(new TiltInput(), CORE0_INPUT); - USBHostManager::getInstance().readyCore0(); + USBHostManager::getInstance().start(); } void GP2040::run() { diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index 11e6e7418..b871b91c2 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -8,13 +8,10 @@ #include "addons/board_led.h" #include "addons/buzzerspeaker.h" -#include "addons/ps4mode.h" -#include "addons/pspassthrough.h" - - #include "addons/i2cdisplay.h" // Add-Ons -#include "addons/neopicoleds.h" #include "addons/pleds.h" +#include "addons/ps4mode.h" +#include "addons/neopicoleds.h" #include @@ -25,18 +22,13 @@ GP2040Aux::~GP2040Aux() { } void GP2040Aux::setup() { - // Setup USB add-ons - addons.LoadUSBAddon(new PSPassthroughAddon(), CORE1_LOOP); - // Setup Regular Add-ons - addons.LoadAddon(new I2CDisplayAddon(), CORE1_ALWAYS); - addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_ALWAYS); - addons.LoadAddon(new PlayerLEDAddon(), CORE1_ALWAYS); + addons.LoadAddon(new I2CDisplayAddon(), CORE1_LOOP); + addons.LoadAddon(new NeoPicoLEDAddon(), CORE1_LOOP); + addons.LoadAddon(new PlayerLEDAddon(), CORE1_LOOP); addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); - - USBHostManager::getInstance().readyCore1(); } void GP2040Aux::run() { @@ -46,12 +38,7 @@ void GP2040Aux::run() { continue; } - addons.ProcessAddons(CORE1_ALWAYS); - - // Config Loop (Only run "ALWAYS" add-ons) - if (configMode == false) - addons.ProcessAddons(CORE1_LOOP); - + addons.ProcessAddons(CORE1_LOOP); nextRuntime = getMicro() + GAMEPAD_POLL_MICRO; } } diff --git a/src/usbhostmanager.cpp b/src/usbhostmanager.cpp index 78a0a4489..1041a2ac6 100644 --- a/src/usbhostmanager.cpp +++ b/src/usbhostmanager.cpp @@ -8,27 +8,13 @@ void USBHostManager::setDataPin(uint8_t inPin) { dataPin = inPin; } -void USBHostManager::readyCore0() { - core0Ready = true; - if ( core0Ready && core1Ready ){ - start(); - } -} - -void USBHostManager::readyCore1() { - core1Ready = true; - if ( core0Ready && core1Ready ){ - start(); - } -} - void USBHostManager::start() { if ( !addons.empty() ) { 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); + sleep_us(10); // ensure we are ready tuh_ready = true; } } From 761d3b8a19f8f77a93573ddce22391106cf8ee8e Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 17:04:00 -0400 Subject: [PATCH 21/24] Might be a timing issue, but running start() in core0 causes a lock-up. Also updated config.proto to enum --- proto/config.proto | 2 +- src/gp2040.cpp | 2 -- src/gp2040aux.cpp | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/config.proto b/proto/config.proto index 1973faf1e..11a989581 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -14,7 +14,7 @@ message GamepadOptions optional bool lockHotkeys = 7; optional bool fourWayMode = 8; optional uint32 profileNumber = 9; - optional uint32 ps4ControllerType = 10; + optional PS4ControllerType ps4ControllerType = 10; } message KeyboardMapping diff --git a/src/gp2040.cpp b/src/gp2040.cpp index 74c476124..65f56d975 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -129,8 +129,6 @@ void GP2040::setup() { addons.LoadAddon(new PlayerNumAddon(), CORE0_USBREPORT); addons.LoadAddon(new SliderSOCDInput(), CORE0_INPUT); addons.LoadAddon(new TiltInput(), CORE0_INPUT); - - USBHostManager::getInstance().start(); } void GP2040::run() { diff --git a/src/gp2040aux.cpp b/src/gp2040aux.cpp index b871b91c2..85831622a 100644 --- a/src/gp2040aux.cpp +++ b/src/gp2040aux.cpp @@ -29,6 +29,8 @@ void GP2040Aux::setup() { addons.LoadAddon(new BoardLedAddon(), CORE1_LOOP); addons.LoadAddon(new BuzzerSpeakerAddon(), CORE1_LOOP); addons.LoadAddon(new PS4ModeAddon(), CORE1_LOOP); + + USBHostManager::getInstance().start(); } void GP2040Aux::run() { From 2e2e49a53070af2983ddd51528947a1682bf1ddc Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 17:09:12 -0400 Subject: [PATCH 22/24] Missed some refactoring changes --- src/addons/i2cdisplay.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/addons/i2cdisplay.cpp b/src/addons/i2cdisplay.cpp index cab913527..c23df486e 100644 --- a/src/addons/i2cdisplay.cpp +++ b/src/addons/i2cdisplay.cpp @@ -937,18 +937,16 @@ void I2CDisplayAddon::drawStatusBar(Gamepad * gamepad) case INPUT_MODE_SWITCH: statusBar += "SWITCH"; break; case INPUT_MODE_XINPUT: statusBar += "XINPUT"; break; case INPUT_MODE_PS4: - switch ( PS4Data::getInstance().ps4ControllerType ) { - if ( PS4Data::getInstance().ps4ControllerType == PS4ControllerType::PS4_CONTROLLER ) { - if (PS4Data::getInstance().authsent == true ) - statusBar += "PS4:AS"; - else - statusBar += "PS4 "; - } else if ( PS4Data::getInstance().ps4ControllerType == PS4ControllerType::PS4_ARCADESTICK ) { - if (PS4Data::getInstance().authsent == true ) - statusBar += "PS5:AS"; - else - statusBar += "PS5 "; - } + if ( PS4Data::getInstance().ps4ControllerType == PS4ControllerType::PS4_CONTROLLER ) { + if (PS4Data::getInstance().authsent == true ) + statusBar += "PS4:AS"; + else + statusBar += "PS4 "; + } else if ( PS4Data::getInstance().ps4ControllerType == PS4ControllerType::PS4_ARCADESTICK ) { + if (PS4Data::getInstance().authsent == true ) + statusBar += "PS5:AS"; + else + statusBar += "PS5 "; } break; case INPUT_MODE_KEYBOARD: statusBar += "HID-KB"; break; From 4941ae8fee03195c98847f016b7a59795221c8fc Mon Sep 17 00:00:00 2001 From: Luke A Date: Mon, 14 Aug 2023 17:32:47 -0400 Subject: [PATCH 23/24] Set PS4 controller default for configs that do not have default --- headers/gamepad/GamepadConfig.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/headers/gamepad/GamepadConfig.h b/headers/gamepad/GamepadConfig.h index 2a3b184bd..b38802375 100644 --- a/headers/gamepad/GamepadConfig.h +++ b/headers/gamepad/GamepadConfig.h @@ -17,6 +17,10 @@ #define DEFAULT_INPUT_MODE INPUT_MODE_XINPUT #endif +#ifndef DEFAULT_PS4CONTROLLER_TYPE +#define DEFAULT_PS4CONTROLLER_TYPE PS4_CONTROLLER +#endif + /* hotkeys */ #ifndef HOTKEY_01_AUX_MASK #define HOTKEY_01_AUX_MASK 0 From fb4ff641597dbcf32ad47ae553f09aaeda1f9c3d Mon Sep 17 00:00:00 2001 From: Luke A Date: Tue, 15 Aug 2023 11:46:55 -0400 Subject: [PATCH 24/24] Code clean-up, more revisions after this is confirmed working --- src/addons/pspassthrough.cpp | 129 ++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/src/addons/pspassthrough.cpp b/src/addons/pspassthrough.cpp index f2ee0ec44..32563da3f 100644 --- a/src/addons/pspassthrough.cpp +++ b/src/addons/pspassthrough.cpp @@ -13,8 +13,6 @@ bool PSPassthroughAddon::available() { } void PSPassthroughAddon::setup() { - set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues - const PSPassthroughOptions& psOptions = Storage::getInstance().getAddonOptions().psPassthroughOptions; if (psOptions.pin5V != -1) { // Feather USB-A's require this @@ -33,11 +31,13 @@ void PSPassthroughAddon::setup() { } void PSPassthroughAddon::process() { + if (!awaiting_cb) + return; + switch ( passthrough_state ) { - case PS4State::no_nonce: - // Did we get the nonce? Let's begin auth - if ( PS4Data::getInstance().ps4State == nonce_ready ) { - if ( !awaiting_cb ) { // Reset the device auth + case PS4State::no_nonce: + // Did we get the nonce? Let's begin auth + if ( PS4Data::getInstance().ps4State == nonce_ready ) { uint8_t const output_0xf3[] = { 0x0, 0x38, 0x38, 0, 0, 0, 0 }; uint8_t* buf = report_buffer; uint16_t len = sizeof(output_0xf3); @@ -45,63 +45,64 @@ void PSPassthroughAddon::process() { awaiting_cb = true; tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_RESET_AUTH, HID_REPORT_TYPE_FEATURE, buf, len); } - } - break; - case PS4State::receiving_nonce: - if ( !awaiting_cb ) { - uint8_t noncelen; - uint32_t crc32; - uint8_t nonce_buffer[64]; // [0xF0, ID, Page, 0, nonce(54 or 32 with 0 padding), CRC32 of data] - nonce_buffer[0] = PS4AuthReport::PS4_SET_AUTH_PAYLOAD; - nonce_buffer[1] = PS4Data::getInstance().nonce_id; - nonce_buffer[2] = nonce_page; - nonce_buffer[3] = 0; - if ( nonce_page == 4 ) { - noncelen = 32; // from 4 to 64 - 24 - 4 - memcpy(&nonce_buffer[4], &PS4Data::getInstance().nonce_buffer[nonce_page*56], noncelen); - memset(&nonce_buffer[4+noncelen], 0, 24); // zero padding - } else { - noncelen = 56; - memcpy(&nonce_buffer[4], &PS4Data::getInstance().nonce_buffer[nonce_page*56], noncelen); - + break; + case PS4State::receiving_nonce: + { + uint8_t noncelen; + uint32_t crc32; + uint8_t nonce_buffer[64]; // [0xF0, ID, Page, 0, nonce(54 or 32 with 0 padding), CRC32 of data] + nonce_buffer[0] = PS4AuthReport::PS4_SET_AUTH_PAYLOAD; + nonce_buffer[1] = PS4Data::getInstance().nonce_id; + nonce_buffer[2] = nonce_page; + nonce_buffer[3] = 0; + if ( nonce_page == 4 ) { + noncelen = 32; // from 4 to 64 - 24 - 4 + memcpy(&nonce_buffer[4], &PS4Data::getInstance().nonce_buffer[nonce_page*56], noncelen); + memset(&nonce_buffer[4+noncelen], 0, 24); // zero padding + } else { + noncelen = 56; + memcpy(&nonce_buffer[4], &PS4Data::getInstance().nonce_buffer[nonce_page*56], noncelen); + } + nonce_page++; + crc32 = CRC32::calculate(nonce_buffer, 60); + memcpy(&nonce_buffer[60], &crc32, sizeof(uint32_t)); + uint8_t* buf = report_buffer; + uint16_t len = sizeof(nonce_buffer); + memcpy(buf, nonce_buffer, len); + awaiting_cb = true; + tuh_hid_set_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_SET_AUTH_PAYLOAD, HID_REPORT_TYPE_FEATURE, buf, len); } - nonce_page++; - crc32 = CRC32::calculate(nonce_buffer, 60); - memcpy(&nonce_buffer[60], &crc32, sizeof(uint32_t)); - uint8_t* buf = report_buffer; - uint16_t len = sizeof(nonce_buffer); - memcpy(buf, nonce_buffer, len); - awaiting_cb = true; - tuh_hid_set_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_SET_AUTH_PAYLOAD, HID_REPORT_TYPE_FEATURE, buf, len); - } - break; - case PS4State::signed_nonce_ready: - if ( !awaiting_cb ) { // Get Auth State - uint8_t state_buffer[16]; - memset(state_buffer, 0, 16); - state_buffer[0] = PS4AuthReport::PS4_GET_SIGNING_STATE; - state_buffer[1] = PS4Data::getInstance().nonce_id; - memset(&state_buffer[2], 0, 14); - uint8_t* buf = report_buffer; - uint16_t len = sizeof(state_buffer); - memcpy(buf, state_buffer, len); - awaiting_cb = true; - tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_GET_SIGNING_STATE, HID_REPORT_TYPE_FEATURE, buf, len); - } - case PS4State::sending_nonce: - if ( !awaiting_cb ) { - uint8_t nonce_buffer[64]; - 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 - memset(&nonce_buffer[3], 0, 61); // zero rest of memory - uint8_t* buf = report_buffer; - uint16_t len = sizeof(nonce_buffer); - memcpy(buf, nonce_buffer, len); - send_nonce_part++; // Nonce Part is reset during callback - awaiting_cb = true; - tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_GET_SIGNATURE_NONCE, HID_REPORT_TYPE_FEATURE, buf, len); - } + break; + case PS4State::signed_nonce_ready: + { + uint8_t state_buffer[16]; + memset(state_buffer, 0, 16); + state_buffer[0] = PS4AuthReport::PS4_GET_SIGNING_STATE; + state_buffer[1] = PS4Data::getInstance().nonce_id; + memset(&state_buffer[2], 0, 14); + uint8_t* buf = report_buffer; + uint16_t len = sizeof(state_buffer); + memcpy(buf, state_buffer, len); + awaiting_cb = true; + tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_GET_SIGNING_STATE, HID_REPORT_TYPE_FEATURE, buf, len); + } + break; + case PS4State::sending_nonce: + { + uint8_t nonce_buffer[64]; + 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 + memset(&nonce_buffer[3], 0, 61); // zero rest of memory + uint8_t* buf = report_buffer; + uint16_t len = sizeof(nonce_buffer); + memcpy(buf, nonce_buffer, len); + send_nonce_part++; // Nonce Part is reset during callback + awaiting_cb = true; + tuh_hid_get_report(ps_dev_addr, ps_instance, PS4AuthReport::PS4_GET_SIGNATURE_NONCE, HID_REPORT_TYPE_FEATURE, buf, len); + } + break; + default: break; }; } @@ -149,12 +150,12 @@ void PSPassthroughAddon::get_report_complete(uint8_t dev_addr, uint8_t instance, passthrough_state = PS4State::receiving_nonce; break; case PS4AuthReport::PS4_GET_SIGNING_STATE: - if (report_buffer[2] == 0) + if (report_buffer[2] == 0) // 0 = ready, 1 = error in signing, 16 = not ready passthrough_state = PS4State::sending_nonce; break; case PS4AuthReport::PS4_GET_SIGNATURE_NONCE: 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 + if (send_nonce_part == 19) { send_nonce_part = 0; passthrough_state = PS4State::no_nonce; // something we don't support PS4Data::getInstance().ps4State = PS4State::signed_nonce_ready;