Xbox 360 Pass-through Authentication (#1138)

* [ImgBot] Optimize images

*Total -- 6,536.44kb -> 6,081.92kb (6.95%)

/configs/OpenCore0/assets/Open_Core0_LED_order.png -- 81.87kb -> 34.77kb (57.53%)
/configs/OpenCore0/assets/Open_Core0_pin_mapping.png -- 79.46kb -> 34.15kb (57.02%)
/configs/OpenCore0/assets/Open_Core0_layout.png -- 80.33kb -> 34.76kb (56.73%)
/configs/OpenCore0/assets/Open_Core0_2.jpg -- 3,134.92kb -> 2,976.17kb (5.06%)
/configs/OpenCore0/assets/Open_Core0.jpg -- 3,159.87kb -> 3,002.07kb (4.99%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>

* Very WIP xbox 360 auth, don't use this for any reason

* Packet size has to be 64

* Fixed a bug with descriptor strings that was causing the xbox 360 security auth to fail

* X360 Auth Working! Need to go over a lot of this code because I sync cores now, a lot of xinput changes, etc.

* Re-enabling printf to figure out what is going wrong with release

DO NOT USE THIS VERSION

* Let's revert some core dependence if that's the issue on release

* Add sync back in and move add-ons to after driver init

* Removing stdio init seems to fix haute42

* Lots of code cleaning. Core0 will always setup() before Core1() so we can remove core1 wait. Added nop to while loop just to add some CPU spice

* Updating TinyUSB to 0.17.0 release from Sept. 2024

* Getting x360 back up to working, fixing some small bugs

* One merge fix for feature data + tud auth data

* Formatting, getting ready for merge

* Last of the formatting!

---------

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
This commit is contained in:
Luke A
2024-09-23 23:07:38 -04:00
committed by GitHub
parent fd18b3cf56
commit 6a7dc59b98
18 changed files with 812 additions and 196 deletions

View File

@@ -3,14 +3,14 @@
static uint16_t * getStringDescriptor(const char * value, uint8_t index)
{
static uint16_t descriptorStringBuffer[32]; // Max 64 bytes, 31 unicode characters
static uint16_t descriptorStringBuffer[128]; // Max 256 bytes, 127 unicode characters
size_t charCount;
if ( index == 0 ) // language always has a character count of 1
charCount = 1;
else {
charCount = strlen(value);
if (charCount > 31)
charCount = 31;
if (charCount > 127)
charCount = 127;
}
// Fill descriptionStringBuffer[1] .. [32]
for (uint8_t i = 0; i < charCount; i++)

View File

@@ -6,16 +6,58 @@
typedef enum {
auth_idle_state = 0,
send_auth_console_to_dongle = 1,
send_auth_dongle_to_console = 2,
wait_auth_console_to_dongle = 3,
wait_auth_dongle_to_console = 4,
send_auth_dongle_to_console = 2
} XInputAuthState;
typedef struct {
XInputAuthState xboneState;
class XInputAuthBuffer {
public:
XInputAuthBuffer() {
data = nullptr;
length = 0;
}
~XInputAuthBuffer(){
if ( data != nullptr ) {
delete [] data;
}
}
// Console-to-Host e.g. Xbox 360 to MagicBoots
bool authCompleted;
void setBuffer(uint8_t * inData, uint16_t inLen) {
data = new uint8_t[inLen];
length = inLen;
memcpy(data, inData, inLen);
}
void reset() {
if ( data != nullptr ) {
delete [] data;
}
data = nullptr;
length = 0;
}
uint8_t * data;
uint16_t length;
};
#define X360_AUTHLEN_CONSOLE_INIT 34
#define X360_AUTHLEN_DONGLE_SERIAL 29
#define X360_AUTHLEN_DONGLE_INIT 46
#define X360_AUTHLEN_CHALLENGE 22
// We need to keep track of:
// Xbox 360 Console Auth Init 34 bytes
// Dongle Serial 29 bytes
// Console-Dongle Back and Forth 46 bytes & 22 bytes
typedef struct {
XInputAuthState xinputState;
uint8_t consoleInitialAuth[X360_AUTHLEN_CONSOLE_INIT]; // Console Init (Keep when Dongle Reboots)
uint8_t dongleSerial[X360_AUTHLEN_DONGLE_SERIAL]; // Dongle Serial
uint8_t passthruBuffer[X360_AUTHLEN_DONGLE_INIT]; // Back-and-Forth Buffer (46 or 22 bytes)
uint8_t passthruBufferLen; // Length of Passthru (do we need this?)
uint8_t passthruBufferID; // ID of vendor request
bool authCompleted = false;
bool hasInitAuth = false;
bool dongle_ready = false;
} XInputAuthData;
class XInputAuth : public GPAuthDriver {
@@ -23,7 +65,9 @@ public:
virtual void initialize();
virtual bool available();
void process();
XInputAuthData * getAuthData() { return &xinputAuthData; }
private:
XInputAuthData xinputAuthData;
};
#endif

View File

@@ -2,6 +2,16 @@
#define _XINPUTAUTHUSBLISTENER_H_
#include "usblistener.h"
#include "XInputAuth.h"
#include "usbhostmanager.h"
#include "drivers/shared/xinput_host.h"
#include "drivers/xinput/XInputDescriptors.h"
typedef enum {
DONGLE_AUTH_IDLE = 0,
DONGLE_AUTH_WAIT_STATE
} DONGLE_AUTH_STATE;
class XInputAuthUSBListener : public USBListener {
public:
@@ -9,15 +19,31 @@ public:
virtual void mount(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len){}
virtual void xmount(uint8_t dev_addr, uint8_t instance, uint8_t controllerType, uint8_t subtype);
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 report_sent(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len){}
virtual void report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {}
virtual void report_sent(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){}
void process();
void setAuthData(XInputAuthData *);
private:
bool xinputh_vendor_report(tusb_dir_t dir, uint8_t request, uint16_t value, uint16_t length, uint8_t * recvBuf, uintptr_t user_data);
// Helper functions for Xbox 360 Authentication
bool auth_dongle_get_serial();
bool auth_dongle_init_challenge();
bool auth_dongle_challenge_verify();
bool auth_dongle_data_reply(uint8_t replyLen);
bool auth_dongle_wait_get_state();
bool auth_dongle_keepalive();
void auth_dongle_wait(uint8_t waitID);
uint8_t xinput_dev_addr;
uint8_t xinput_instance;
bool mounted;
bool sending;
XInputAuthData * xinputAuthData;
uint32_t wait_time;
uint8_t wait_count;
uint8_t waitBuffer[64]; // wait buffer
uint8_t waitBufferID;
DONGLE_AUTH_STATE dongleAuthState;
};
#endif // _XINPUTAUTHUSBLISTENER_H_

View File

@@ -33,95 +33,236 @@
typedef struct __attribute((packed, aligned(1)))
{
uint8_t report_id;
uint8_t report_size;
uint8_t buttons1;
uint8_t buttons2;
uint8_t lt;
uint8_t rt;
int16_t lx;
int16_t ly;
int16_t rx;
int16_t ry;
uint8_t _reserved[6];
uint8_t report_id;
uint8_t report_size;
uint8_t buttons1;
uint8_t buttons2;
uint8_t lt;
uint8_t rt;
int16_t lx;
int16_t ly;
int16_t rx;
int16_t ry;
uint8_t _reserved[6];
} XInputReport;
static const uint8_t xinput_string_language[] = { 0x09, 0x04 };
static const uint8_t xinput_string_manfacturer[] = "Microsoft";
static const uint8_t xinput_string_product[] = "XInput STANDARD GAMEPAD";
static const uint8_t xinput_string_version[] = "1.0";
static const uint8_t xinput_string_serial[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const uint8_t xinput_string_manfacturer[] = "\xa9Microsoft Corporation";
static const uint8_t xinput_string_product[] = "Controller";
static const uint8_t xinput_string_version[] = "08FEC93"; // Fake a random serial, doesn't matter
static const uint8_t xinput_string_xsm3[] = "Xbox Security Method 3, Version 1.00, \xa9 2005 Microsoft Corporation. All rights reserved.";
static const uint8_t *xinput_string_descriptors[] __attribute__((unused)) =
{
xinput_string_language,
xinput_string_manfacturer,
xinput_string_product,
xinput_string_version
xinput_string_serial,
xinput_string_manfacturer,
xinput_string_product,
xinput_string_version,
xinput_string_xsm3
};
static const uint8_t xinput_device_descriptor[] =
{
0x12, // bLength
0x01, // bDescriptorType (Device)
0x00, 0x02, // bcdUSB 2.00
0xFF, // bDeviceClass
0xFF, // bDeviceSubClass
0xFF, // bDeviceProtocol
0x40, // bMaxPacketSize0 64
0x5E, 0x04, // idVendor 0x045E
0x8E, 0x02, // idProduct 0x028E
0x14, 0x01, // bcdDevice 2.14
0x01, // iManufacturer (String Index)
0x02, // iProduct (String Index)
0x03, // iSerialNumber (String Index)
0x01, // bNumConfigurations 1
0x12, // bLength
0x01, // bDescriptorType (Device)
0x00, 0x02, // bcdUSB 2.00
0xFF, // bDeviceClass
0xFF, // bDeviceSubClass
0xFF, // bDeviceProtocol
0x40, // bMaxPacketSize0 64
0x5E, 0x04, // idVendor 0x045E
0x8E, 0x02, // idProduct 0x028E
0x14, 0x01, // bcdDevice 2.14
0x01, // iManufacturer (String Index)
0x02, // iProduct (String Index)
0x03, // iSerialNumber (String Index)
0x01, // bNumConfigurations 1
};
// This needs to be:
// 4 interfaces
// remote wakeup enabled
static const uint8_t xinput_configuration_descriptor[] =
{
0x09, // bLength
0x02, // bDescriptorType (Configuration)
0x30, 0x00, // wTotalLength 48
0x01, // bNumInterfaces 1
0x01, // bConfigurationValue
0x00, // iConfiguration (String Index)
0x80, // bmAttributes
0xFA, // bMaxPower 500mA
0x09, // bLength
0x02, // bDescriptorType (Configuration)
0x99, 0x00, // wTotalLength 0x99
0x04, // bNumInterfaces 4
0x01, // bConfigurationValue
0x00, // iConfiguration (String Index)
0xA0, // bmAttributes (remote wakeup)
0xFA, // bMaxPower 500mA
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x00, // bInterfaceNumber 0
0x00, // bAlternateSetting
0x02, // bNumEndpoints 2
0xFF, // bInterfaceClass
0x5D, // bInterfaceSubClass
0x01, // bInterfaceProtocol
0x00, // iInterface (String Index)
// Control Interface (0x5D 0xFF)
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x00, // bInterfaceNumber 0
0x00, // bAlternateSetting
0x02, // bNumEndpoints 2
0xFF, // bInterfaceClass
0x5D, // bInterfaceSubClass
0x01, // bInterfaceProtocol
0x00, // iInterface (String Index)
0x10, // bLength
0x21, // bDescriptorType (HID)
0x10, 0x01, // bcdHID 1.10
0x01, // bCountryCode
0x24, // bNumDescriptors
0x81, // bDescriptorType[0] (Unknown 0x81)
0x14, 0x03, // wDescriptorLength[0] 788
0x00, // bDescriptorType[1] (Unknown 0x00)
0x03, 0x13, // wDescriptorLength[1] 4867
0x01, // bDescriptorType[2] (Unknown 0x02)
0x00, 0x03, // wDescriptorLength[2] 768
0x00, // bDescriptorType[3] (Unknown 0x00)
// Gamepad Descriptor
0x11, // bLength
0x21, // bDescriptorType (HID)
0x00, 0x01, // bcdHID 1.10
0x01, // SUB_TYPE
0x25, // reserved2
0x81, // DEVICE_EPADDR_IN
0x14, // bMaxDataSizeIn
0x00, 0x00, 0x00, 0x00, 0x13, // reserved3
0x02, // DEVICE_EPADDR_OUT is this right?
0x08, // bMaxDataSizeOut
0x00, 0x00, // reserved4
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x81, // bEndpointAddress (IN/D2H)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x01, // bInterval 1 (unit depends on device speed)
// Report IN Endpoint 1.1
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x81, // bEndpointAddress (IN/D2H)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x01, // bInterval 1 (unit depends on device speed)
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x01, // bEndpointAddress (OUT/H2D)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x08, // bInterval 8 (unit depends on device speed)
// Report OUT Endpoint 1.2
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x02, // bEndpointAddress (OUT/H2D)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x08, // bInterval 8 (unit depends on device speed)
// Interface Audio
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x01, // bInterfaceNumber 1
0x00, // bAlternateSetting
0x04, // bNumEndpoints 4
0xFF, // bInterfaceClass
0x5D, // bInterfaceSubClass
0x03, // bInterfaceProtocol
0x00, // iInterface (String Index)
// Audio Descriptor
0x1B, // bLength
0x21,
0x00,
0x01,
0x01,
0x01,
0x83, // XINPUT_MIC_IN
0x40, // ??
0x01, // ??
0x04, // XINPUT_AUDIO_OUT
0x20, // ??
0x16, // ??
0x85, // XINPUT_UNK_IN
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x16,
0x06, // XINPUT_UNK_OUT
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
// Report IN Endpoint 2.1
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x83, // bEndpointAddress (XINPUT_MIC_IN)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x02, // bInterval 2 (unit depends on device speed)
// Report OUT Endpoint 2.2
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x04, // bEndpointAddress (XINPUT_AUDIO_OUT)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x04, // bInterval 4 (unit depends on device speed)
// Report IN Endpoint 2.3
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x85, // bEndpointAddress (XINPUT_UNK_IN)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x40, // bInterval 128
// Report OUT Endpoint 2.4
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x06, // bEndpointAddress (XINPUT_UNK_OUT)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x10, // bInterval 16
// Interface Plugin Module
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x02, // bInterfaceNumber 2
0x00, // bAlternateSetting
0x01, // bNumEndpoints 1
0xFF, // bInterfaceClass
0x5D, // bInterfaceSubClass
0x02, // bInterfaceProtocol
0x00, // iInterface (String Index)
//PluginModuleDescriptor : {
0x09, // bLength
0x21, // bDescriptorType
0x00, 0x01, // version 1.00
0x01, // ??
0x22, // ??
0x86, // XINPUT_PLUGIN_MODULE_IN,
0x03, // ??
0x00, // ??
// Report IN Endpoint 3.1
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x86, // bEndpointAddress (XINPUT_PLUGIN_MODULE_IN)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x10, // bInterval 8 (unit depends on device speed)
// Interface Security
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x03, // bInterfaceNumber 3
0x00, // bAlternateSetting
0x00, // bNumEndpoints 0
0xFF, // bInterfaceClass
0xFD, // bInterfaceSubClass
0x13, // bInterfaceProtocol
0x04, // iInterface (String Index)
// SecurityDescriptor (XSM3)
0x06, // bLength
0x41, // bDescriptType (Xbox 360)
0x00,
0x01,
0x01,
0x03,
};
typedef enum
{
XSM360_AUTH_NONE = 0x00, // None
XSM360_GET_SERIAL = 0x81, // Xbox 360 Get Controller Serial
XSM360_INIT_AUTH = 0x82, // Xbox 360 Initialize Authentication
XSM360_RESPOND_CHALLENGE = 0x83, // Xbox 360 Respond with Challenge
XSM360_AUTH_KEEPALIVE = 0x84, // Xbox 360 Keep Authentication Alive
XSM360_REQUEST_STATE = 0x86, // Xbox 360 Request Authentication State
XSM360_VERIFY_AUTH = 0x87, // Xbox 360 Verify Authentication
} XSM360AuthRequest;

View File

@@ -9,6 +9,7 @@
#include "gpdriver.h"
#include "usblistener.h"
#include "drivers/shared/gpauthdriver.h"
#include "drivers/xinput/XInputAuth.h"
#include "drivers/xinput/XInputDescriptors.h"
#define XINPUT_OUT_SIZE 32
@@ -20,7 +21,7 @@ public:
virtual void initializeAux();
virtual void processAux();
virtual uint16_t get_report(uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen);
virtual void set_report(uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize);
virtual void set_report(uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {}
virtual bool vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request);
virtual const uint16_t * get_descriptor_string_cb(uint8_t index, uint16_t langid);
virtual const uint8_t * get_descriptor_device_cb();
@@ -29,11 +30,13 @@ public:
virtual const uint8_t * get_descriptor_device_qualifier_cb();
virtual uint16_t GetJoystickMidValue();
virtual USBListener * get_usb_auth_listener();
bool getAuthEnabled();
private:
uint8_t last_report[CFG_TUD_ENDPOINT0_SIZE] = { };
XInputReport xinputReport;
GPAuthDriver * authDriver;
XInputAuth * xAuthDriver;
uint8_t featureBuffer[XINPUT_OUT_SIZE];
uint8_t tud_buffer[64];
};
#endif

View File

@@ -17,8 +17,8 @@
class GP2040 {
public:
GP2040() {}
~GP2040() {}
GP2040(){}
~GP2040(){}
void setup(); // setup core0
void run(); // loop core0
private:

View File

@@ -15,9 +15,11 @@ public:
~GP2040Aux();
void setup(); // setup core1
void run(); // loop core1
bool ready(){ return isReady; }
private:
GPDriver * inputDriver;
AddonManager addons;
bool isReady;
};
#endif

View File

@@ -3,6 +3,7 @@
#include "drivermanager.h"
#include "drivers/ps4/PS4Driver.h"
#include "drivers/xbone/XBOneDriver.h"
#include "drivers/xinput/XInputDriver.h"
void ButtonLayoutScreen::init() {
const InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions;
@@ -132,7 +133,6 @@ void ButtonLayoutScreen::generateHeader() {
case INPUT_MODE_PS3: statusBar += "PS3"; break;
case INPUT_MODE_GENERIC: statusBar += "USBHID"; break;
case INPUT_MODE_SWITCH: statusBar += "SWITCH"; break;
case INPUT_MODE_XINPUT: statusBar += "XINPUT"; break;
case INPUT_MODE_MDMINI: statusBar += "GEN/MD"; break;
case INPUT_MODE_NEOGEO: statusBar += "NGMINI"; break;
case INPUT_MODE_PCEMINI: statusBar += "PCE/TG"; break;
@@ -161,6 +161,13 @@ void ButtonLayoutScreen::generateHeader() {
else
statusBar += "*";
break;
case INPUT_MODE_XINPUT:
statusBar += "X";
if(((XInputDriver*)DriverManager::getInstance().getDriver())->getAuthEnabled() == true )
statusBar += "B360";
else
statusBar += "INPUT";
break;
case INPUT_MODE_KEYBOARD: statusBar += "HID-KB"; break;
case INPUT_MODE_CONFIG: statusBar += "CONFIG"; break;
}

View File

@@ -116,6 +116,29 @@ bool tuh_xinput_receive_report(uint8_t dev_addr, uint8_t instance) {
return true;
}
bool tuh_xinput_receive_vendor_report(uint8_t dev_addr, uint8_t instance, uint8_t request, uint16_t value, uint8_t index, uint16_t length, uint8_t * recvBuf) {
const tusb_control_request_t xfer_ctrl_req = {
.bmRequestType_bit {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_VENDOR,
.direction = TUSB_DIR_IN,
},
.bRequest = request,
.wValue = value,
.wIndex = TU_U16(index, 0x03),
.wLength = length
};
tuh_xfer_t xfer = {
.daddr = dev_addr,
.ep_addr = 0,
.setup = &xfer_ctrl_req,
.buffer = recvBuf,
.complete_cb = NULL,
};
return tuh_control_xfer(&xfer);
}
bool tuh_xinput_send_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
xinputh_interface_t *xid_itf = get_instance(dev_addr, instance);
@@ -140,6 +163,28 @@ bool tuh_xinput_send_report(uint8_t dev_addr, uint8_t instance, uint8_t const *r
return ret;
}
bool tuh_xinput_send_vendor_report(uint8_t dev_addr, uint8_t instance, uint8_t request, uint16_t value, uint8_t index, uint16_t length, uint8_t * sendBuf) {
const tusb_control_request_t xfer_ctrl_req = {
.bmRequestType_bit {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_VENDOR,
.direction = TUSB_DIR_OUT,
},
.bRequest = request,
.wValue = value,
.wIndex = TU_U16(index, 0x03),
.wLength = length
};
tuh_xfer_t xfer = {
.daddr = dev_addr,
.ep_addr = 0,
.setup = &xfer_ctrl_req,
.buffer = sendBuf,
.complete_cb = NULL,
};
return tuh_control_xfer(&xfer);
}
bool tuh_xinput_ready(uint8_t dev_addr, uint8_t instance) {
TU_VERIFY(tuh_xinput_mounted(dev_addr, instance));

View File

@@ -113,7 +113,7 @@ void XBOneAuthUSBListener::report_received(uint8_t dev_addr, uint8_t instance, u
queue_host_report((uint8_t*)outgoingXGIP.generatePacket(), outgoingXGIP.getPacketLength());
break;
case GIP_DEVICE_DESCRIPTOR:
if ( incomingXGIP.endOfChunk() == true ) {
if ( incomingXGIP.endOfChunk() == true && xboxOneAuthData->dongle_ready != true) {
outgoingXGIP.reset(); // Power-on full string
outgoingXGIP.setAttributes(GIP_POWER_MODE_DEVICE_CONFIG, 2, 1, false, 0);
outgoingXGIP.setData(xb1_power_on, sizeof(xb1_power_on));

View File

@@ -6,6 +6,14 @@ void XInputAuth::initialize() {
if ( available() ) {
listener = new XInputAuthUSBListener();
}
if ( available() ) {
listener = new XInputAuthUSBListener();
xinputAuthData.xinputState = auth_idle_state;
xinputAuthData.authCompleted = false;
((XInputAuthUSBListener*)listener)->setup();
((XInputAuthUSBListener*)listener)->setAuthData(&xinputAuthData);
}
}
bool XInputAuth::available() {
@@ -13,5 +21,5 @@ bool XInputAuth::available() {
}
void XInputAuth::process() {
((XInputAuthUSBListener*)listener)->process();
}

View File

@@ -3,39 +3,245 @@
#include "usbhostmanager.h"
#include "drivers/shared/xinput_host.h"
#include "drivers/xinput/XInputDescriptors.h"
// Xbox 360 Auth Magic Numbers (wValue in USB Packet)
#define X360_WVALUE_CONSOLE_DATA 0x0003
#define X360_WVALUE_CONTROLLER_DATA 0x5C
#define X360_WVALUE_CONTROLLER_ID 0x5B
#define X360_WVALUE_NO_DATA 0x00
// How long to wait for calling auth state (in microseconds)
#define WAIT_TIME_MS 100
void XInputAuthUSBListener::setAuthData(XInputAuthData * authData ) {
xinputAuthData = authData;
xinputAuthData->dongle_ready = false;
memset(xinputAuthData->dongleSerial, 0, X360_AUTHLEN_DONGLE_SERIAL);
xinputAuthData->passthruBufferLen = 0;
xinputAuthData->xinputState = XInputAuthState::auth_idle_state;
}
void XInputAuthUSBListener::setup() {
xinput_dev_addr = 0xFF;
xinput_instance = 0xFF;
dongleAuthState = DONGLE_AUTH_STATE::DONGLE_AUTH_IDLE;
wait_time = 0;
wait_count = 0;
sending = false;
xinputAuthData->dongle_ready = false;
}
bool XInputAuthUSBListener::xinputh_vendor_report(tusb_dir_t dir, uint8_t request, uint16_t value, uint16_t length, uint8_t * buf, uintptr_t user_data){
const tusb_control_request_t xfer_ctrl_req = {
.bmRequestType_bit {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_VENDOR,
.direction = dir,
},
.bRequest = request,
.wValue = value,
.wIndex = TU_U16(0x01, 0x03),
.wLength = length
};
tuh_xfer_t xfer = {
.daddr = xinput_dev_addr,
.ep_addr = 0,
.setup = &xfer_ctrl_req,
.buffer = buf,
.complete_cb = NULL,
.user_data = user_data,
};
return tuh_control_xfer(&xfer);
}
void XInputAuthUSBListener::xmount(uint8_t dev_addr, uint8_t instance, uint8_t controllerType, uint8_t subtype) {
if ( controllerType == xinput_type_t::XBOX360) {
xinput_dev_addr = dev_addr;
xinput_instance = instance;
mounted = true;
// Get Xbox Security Method 3 (XSM3)
uint8_t recvBuf[0xB2];
tuh_descriptor_get_string_sync(xinput_dev_addr, 4, 0x0409, recvBuf, 0xB2);
// If our dongle has remounted for any reason, trigger a re-auth (Magicboots X360)
if ( xinputAuthData->hasInitAuth == true ) {
if ( auth_dongle_init_challenge() == true) {
auth_dongle_wait(XSM360AuthRequest::XSM360_INIT_AUTH);
}
} else {
auth_dongle_get_serial();
}
xinputAuthData->dongle_ready = true;
}
}
void XInputAuthUSBListener::unmount(uint8_t dev_addr) {
// Do not reset dongle_ready on unmount (Magic-X will remount but still be ready)
mounted = false;
}
void XInputAuthUSBListener::report_received(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
if ( mounted == false )
return;
if ( dev_addr == xinput_dev_addr ) {
xinputAuthData->dongle_ready = false;
dongleAuthState = DONGLE_AUTH_STATE::DONGLE_AUTH_IDLE;
}
}
void XInputAuthUSBListener::process() {
// Get Serial ID - 0x81
// No Auth Data or Dongle is not ready (Unmounted or Not Connected)
if ( xinputAuthData == nullptr || xinputAuthData->dongle_ready == false) {
return;
}
// Do Challenge Init - 0x82 (send console -> host)
// Idle State, check for incoming console data
if ( dongleAuthState == DONGLE_AUTH_STATE::DONGLE_AUTH_IDLE ) {
// Received a packet from the console to dongle
if ( xinputAuthData->xinputState == XInputAuthState::send_auth_console_to_dongle ) {
switch(xinputAuthData->passthruBufferID) {
case XSM360AuthRequest::XSM360_INIT_AUTH:
// Copy to our initial auth buffer incase the dongle reconnects
if ( xinputAuthData->hasInitAuth == false ) {
memcpy(xinputAuthData->consoleInitialAuth, xinputAuthData->passthruBuffer, xinputAuthData->passthruBufferLen);
xinputAuthData->hasInitAuth = true;
}
// Get Challenge Response - 0x83 (send console -> host)
// ?? - 0x84
// Get State - 0x86 (1 = in-progress, 2 = complete)
// ?? - 0x87
// Actions are performed in this order
if ( auth_dongle_init_challenge() == false) {
xinputAuthData->xinputState = XInputAuthState::auth_idle_state;
return;
}
auth_dongle_wait(XSM360AuthRequest::XSM360_INIT_AUTH);
break;
case XSM360AuthRequest::XSM360_VERIFY_AUTH:
// Challenge Verify (22 bytes)
if ( auth_dongle_challenge_verify() == false) {
xinputAuthData->xinputState = XInputAuthState::auth_idle_state;
return;
}
auth_dongle_wait(XSM360AuthRequest::XSM360_VERIFY_AUTH);
break;
default:
break;
}
}
} else if ( dongleAuthState == DONGLE_AUTH_STATE::DONGLE_AUTH_WAIT_STATE ) {
uint64_t now_time = to_ms_since_boot(get_absolute_time());
if ( now_time > wait_time ) {
if ( auth_dongle_wait_get_state() == false ) {
wait_time = now_time + WAIT_TIME_MS;
wait_count++;
} else {
switch(waitBufferID) {
case XSM360AuthRequest::XSM360_INIT_AUTH:
// Actions are performed in this order
if ( auth_dongle_data_reply(X360_AUTHLEN_DONGLE_INIT) == false ) {
xinputAuthData->xinputState = XInputAuthState::auth_idle_state;
} else {
auth_dongle_keepalive();
xinputAuthData->xinputState = XInputAuthState::send_auth_dongle_to_console;
}
break;
case XSM360AuthRequest::XSM360_VERIFY_AUTH:
if ( auth_dongle_data_reply(X360_AUTHLEN_CHALLENGE) == false ) {
xinputAuthData->xinputState = XInputAuthState::auth_idle_state;
} else {
xinputAuthData->xinputState = XInputAuthState::send_auth_dongle_to_console;
}
break;
default:
break;
}
dongleAuthState = DONGLE_AUTH_STATE::DONGLE_AUTH_IDLE;
wait_count = 0;
}
// TIMEOUT after 60 attempts
if ( wait_count == 60 ) {
dongleAuthState = DONGLE_AUTH_STATE::DONGLE_AUTH_IDLE;
wait_count = 0;
wait_time = 0;
xinputAuthData->xinputState = XInputAuthState::auth_idle_state;
}
}
}
}
bool XInputAuthUSBListener::auth_dongle_get_serial() {
// Get Serial ID Buffer (0x81)
xfer_result_t user_result;
if (xinputh_vendor_report(TUSB_DIR_IN, XSM360AuthRequest::XSM360_GET_SERIAL,
TU_U16(X360_WVALUE_CONTROLLER_ID, X360_AUTHLEN_DONGLE_SERIAL-6),
X360_AUTHLEN_DONGLE_SERIAL, xinputAuthData->dongleSerial, (uintptr_t)&user_result) == false
|| user_result != xfer_result_t::XFER_RESULT_SUCCESS) {
return false;
}
return true;
}
// Xbox 360 Console Auth Challenge Verify - 0x87
bool XInputAuthUSBListener::auth_dongle_init_challenge() {
// Send Auth Init Data to Dongle
xfer_result_t user_result;
if ( xinputh_vendor_report(TUSB_DIR_OUT,
XSM360AuthRequest::XSM360_INIT_AUTH, X360_WVALUE_CONSOLE_DATA,
X360_AUTHLEN_CONSOLE_INIT, xinputAuthData->consoleInitialAuth, (uintptr_t)&user_result) == false
|| user_result != xfer_result_t::XFER_RESULT_SUCCESS) {
return false;
}
return true;
}
// Auth Data reply gets a value of 0x5CXX with XX being the total data length minus 6 bytes for the header
bool XInputAuthUSBListener::auth_dongle_data_reply(uint8_t replyLen) {
// Get Xbox 360 Challenge Reply from Dongle
xfer_result_t user_result;
if ( xinputh_vendor_report(TUSB_DIR_IN,
XSM360AuthRequest::XSM360_RESPOND_CHALLENGE, TU_U16(X360_WVALUE_CONTROLLER_DATA, replyLen-6),
replyLen, xinputAuthData->passthruBuffer, (uintptr_t)&user_result) == false
|| user_result != xfer_result_t::XFER_RESULT_SUCCESS) {
return false;
}
xinputAuthData->passthruBufferLen = replyLen;
return true;
}
// Xbox 360 Console Auth Challenge Verify - 0x87
bool XInputAuthUSBListener::auth_dongle_challenge_verify() {
// Send Auth Init Data to Dongle
xfer_result_t user_result;
if ( xinputh_vendor_report(TUSB_DIR_OUT,
XSM360AuthRequest::XSM360_VERIFY_AUTH, X360_WVALUE_CONSOLE_DATA,
X360_AUTHLEN_CHALLENGE, xinputAuthData->passthruBuffer, (uintptr_t)&user_result) == false
|| user_result != xfer_result_t::XFER_RESULT_SUCCESS) {
return false;
}
return true;
}
// Xbox 360 Console Asks for Current Signing State
bool XInputAuthUSBListener::auth_dongle_wait_get_state() {
uint8_t wait_buf[2];
xfer_result_t user_result = xfer_result_t::XFER_RESULT_SUCCESS;
if ( xinputh_vendor_report(TUSB_DIR_IN,
XSM360AuthRequest::XSM360_REQUEST_STATE, X360_WVALUE_NO_DATA,
2, wait_buf, (uintptr_t)&user_result) == false || user_result != xfer_result_t::XFER_RESULT_SUCCESS ) {
return false;
}
return ( wait_buf[0] == 2 ); // Dongle is ready!
}
// Xbox 360 Console, Send an 0x84 KeepAlive, all is good message
bool XInputAuthUSBListener::auth_dongle_keepalive() {
// Auth Keepalive does not return anything and stalls on some dongles
xfer_result_t user_result;
xinputh_vendor_report(TUSB_DIR_IN,
XSM360AuthRequest::XSM360_AUTH_KEEPALIVE, X360_WVALUE_CONSOLE_DATA,
0, NULL, (uintptr_t)&user_result);
return true;
}
// Wait for X time before checking auth dongle wait-state (ready, not ready)
void XInputAuthUSBListener::auth_dongle_wait(uint8_t waitID) {
// Setup a wait-for mode for the dongle or controller to finish auth
wait_count = 0;
wait_time = to_ms_since_boot(get_absolute_time()) + WAIT_TIME_MS;
memcpy(waitBuffer, xinputAuthData->passthruBuffer, xinputAuthData->passthruBufferLen);
dongleAuthState = DONGLE_AUTH_STATE::DONGLE_AUTH_WAIT_STATE;
waitBufferID = waitID;
}

View File

@@ -4,7 +4,6 @@
*/
#include "drivers/xinput/XInputDriver.h"
#include "drivers/xinput/XInputAuth.h"
#include "drivers/shared/driverhelper.h"
#include "storagemanager.h"
@@ -22,14 +21,41 @@
#define DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR 0x0004
#define DESC_EXTENDED_PROPERTIES_DESCRIPTOR 0x0005
#define XINPUT_OUT_SIZE 32
#define CFG_TUD_XINPUT 4
#define XINPUT_DESC_TYPE_RESERVED 0x21
#define XINPUT_SECURITY_DESC_TYPE_RESERVED 0x41
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out; // optional Out endpoint
uint8_t boot_protocol; // Boot mouse or keyboard
bool boot_mode; // default = false (Report)
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[XINPUT_OUT_SIZE];
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[XINPUT_OUT_SIZE];
} xinputd_interface_t;
CFG_TUSB_MEM_SECTION static xinputd_interface_t _xinputd_itf[CFG_TUD_XINPUT];
uint8_t endpoint_in = 0;
uint8_t endpoint_out = 0;
uint8_t xinput_out_buffer[XINPUT_OUT_SIZE] = {};
static XInputAuthData * xinputAuthData = nullptr;
#include <stdio.h>
#include "pico/stdlib.h"
/*------------- Helpers -------------*/
static inline uint8_t get_index_by_itfnum(uint8_t itf_num) {
for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) {
if (itf_num == _xinputd_itf[i].itf_num) return i;
}
static bool authDriverPresent = false;
return 0xFF;
}
// Move to Proto Enums
typedef enum
@@ -57,31 +83,54 @@ static void xinput_reset(uint8_t rhport) {
(void)rhport;
}
static uint16_t xinput_open(uint8_t rhport, tusb_desc_interface_t const *itf_descriptor, uint16_t max_length)
{
uint16_t driver_length = sizeof(tusb_desc_interface_t) + (itf_descriptor->bNumEndpoints * sizeof(tusb_desc_endpoint_t)) + 16;
static uint16_t xinput_open(uint8_t rhport, tusb_desc_interface_t const *itf_descriptor, uint16_t max_length) {
uint16_t driver_length = 0;
// Xbox 360 Vendor USB Interfaces: Control, Audio, Plug-in, Security
if ( TUSB_CLASS_VENDOR_SPECIFIC == itf_descriptor->bInterfaceClass) {
driver_length = sizeof(tusb_desc_interface_t) + (itf_descriptor->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
TU_VERIFY(max_length >= driver_length, 0);
TU_VERIFY(max_length >= driver_length, 0);
// Find available interface
xinputd_interface_t *p_xinput = NULL;
for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) {
if (_xinputd_itf[i].ep_in == 0 && _xinputd_itf[i].ep_out == 0) {
p_xinput = &_xinputd_itf[i];
break;
}
}
uint8_t const *current_descriptor = tu_desc_next(itf_descriptor);
uint8_t found_endpoints = 0;
while ((found_endpoints < itf_descriptor->bNumEndpoints) && (driver_length <= max_length))
{
tusb_desc_endpoint_t const *endpoint_descriptor = (tusb_desc_endpoint_t const *)current_descriptor;
if (TUSB_DESC_ENDPOINT == tu_desc_type(endpoint_descriptor))
{
TU_ASSERT(usbd_edpt_open(rhport, endpoint_descriptor));
tusb_desc_interface_t *p_desc = (tusb_desc_interface_t *)itf_descriptor;
// Xbox 360 Interfaces (Control 0x01, Audio 0x02, Plug-in 0x03)
if (itf_descriptor->bInterfaceSubClass == 0x5D &&
((itf_descriptor->bInterfaceProtocol == 0x01 ) ||
(itf_descriptor->bInterfaceProtocol == 0x02 ) ||
(itf_descriptor->bInterfaceProtocol == 0x03 )) ) {
// Get Xbox 360 Definition
p_desc = (tusb_desc_interface_t *)tu_desc_next(p_desc);
TU_VERIFY(XINPUT_DESC_TYPE_RESERVED == p_desc->bDescriptorType, 0);
driver_length += p_desc->bLength;
if (tu_edpt_dir(endpoint_descriptor->bEndpointAddress) == TUSB_DIR_IN)
endpoint_in = endpoint_descriptor->bEndpointAddress;
else
endpoint_out = endpoint_descriptor->bEndpointAddress;
p_desc = (tusb_desc_interface_t *)tu_desc_next(p_desc);
TU_ASSERT(usbd_open_edpt_pair(rhport, (const uint8_t*)p_desc, itf_descriptor->bNumEndpoints,
TUSB_XFER_INTERRUPT, &p_xinput->ep_out, &p_xinput->ep_in), 0);
p_xinput->itf_num = itf_descriptor->bInterfaceNumber;
++found_endpoints;
}
// Control Endpoints are used for gamepad input/output
if ( itf_descriptor->bInterfaceProtocol == 0x01 ) {
endpoint_in = p_xinput->ep_in;
endpoint_out = p_xinput->ep_out;
}
// Xbox 360 Security Interface
} else if (itf_descriptor->bInterfaceSubClass == 0xFD &&
itf_descriptor->bInterfaceProtocol == 0x13) {
// Xinput reserved endpoint
//-------------- Xinput Descriptor --------------//
p_desc = (tusb_desc_interface_t *)tu_desc_next(p_desc);
TU_VERIFY(XINPUT_SECURITY_DESC_TYPE_RESERVED == p_desc->bDescriptorType, 0);
driver_length += p_desc->bLength;
}
}
current_descriptor = tu_desc_next(current_descriptor);
}
return driver_length;
}
@@ -90,32 +139,7 @@ static bool xinput_device_control_request(uint8_t rhport, uint8_t stage, tusb_co
(void)rhport;
(void)stage;
(void)request;
/*
// if authentication is present
if ( authDriverPresent &&
request->bmRequestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) {
switch(request->bRequest) {
case 0x81:
uint8_t serial[0x0B];
return sizeof(id_data_ms_controller);
case 0x82:
return 0;
case 0x83:
memcpy(requestBuffer, challenge_response, sizeof(challenge_response));
return sizeof(challenge_response);
case 0x84:
break;
case 0x86:
short state = 2; // 1 = in-progress, 2 = complete
memcpy(&request->wValue, &state, sizeof(state));
return sizeof(state);
case 0x87:
break;
default:
break;
};
}
*/
return true;
}
@@ -166,31 +190,33 @@ void XInputDriver::initialize() {
.sof = NULL
};
authDriver = nullptr;
xAuthDriver = nullptr;
}
void XInputDriver::initializeAux() {
authDriver = nullptr;
xAuthDriver = nullptr;
// AUTH DRIVER NON-FUNCTIONAL FOR NOW
/*
GamepadOptions & gamepadOptions = Storage::getInstance().getGamepadOptions();
if ( gamepadOptions.xinputAuthType == InputModeAuthType::INPUT_MODE_AUTH_TYPE_USB ) {
authDriver = new XInputAuth();
if ( authDriver->available() ) {
authDriver->initialize();
authDriverPresent = true; // for callbacks
xAuthDriver = new XInputAuth();
if ( xAuthDriver->available() ) {
xAuthDriver->initialize();
xinputAuthData = xAuthDriver->getAuthData();
}
}
*/
}
}
USBListener * XInputDriver::get_usb_auth_listener() {
if ( authDriver != nullptr && authDriver->available() ) {
return authDriver->getListener();
if ( xAuthDriver != nullptr && xAuthDriver->available() ) {
return xAuthDriver->getListener();
}
return nullptr;
}
bool XInputDriver::getAuthEnabled() {
return (xAuthDriver != nullptr);
}
void XInputDriver::process(Gamepad * gamepad) {
Gamepad * processedGamepad = Storage::getInstance().GetProcessedGamepad();
@@ -293,8 +319,8 @@ void XInputDriver::process(Gamepad * gamepad) {
}
void XInputDriver::processAux() {
if ( authDriver != nullptr && authDriver->available() ) {
((XInputAuth*)authDriver)->process();
if ( xAuthDriver != nullptr && xAuthDriver->available() ) {
xAuthDriver->process();
}
}
@@ -304,12 +330,81 @@ uint16_t XInputDriver::get_report(uint8_t report_id, hid_report_type_t report_ty
return sizeof(XInputReport);
}
// Only PS4 does anything with set report
void XInputDriver::set_report(uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {}
// Only XboxOG and Xbox One use vendor control xfer cb
// Only respond to vendor control xfers if we have a mounted x360 device
bool XInputDriver::vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) {
return false;
// Do nothing if we have no auth driver
if ( xAuthDriver == nullptr || !xAuthDriver->available() ) {
return false;
}
uint16_t len = 0;
if (request->bmRequestType_bit.direction == TUSB_DIR_IN) {
// Write IN data on control_stage_setup only
if (stage == CONTROL_STAGE_SETUP) {
uint16_t state = 1; // 1 = in-progress, 2 = complete
switch (request->bRequest) {
case XSM360_GET_SERIAL:
// Stall if we don't have a dongle ready
if ( xinputAuthData->dongle_ready == false ) {
return false;
}
len = X360_AUTHLEN_DONGLE_SERIAL;
memcpy(tud_buffer, xinputAuthData->dongleSerial, len);
break;
case XSM360_RESPOND_CHALLENGE:
if ( xinputAuthData->xinputState == XInputAuthState::send_auth_dongle_to_console ) {
memcpy(tud_buffer, xinputAuthData->passthruBuffer, xinputAuthData->passthruBufferLen);
len = xinputAuthData->passthruBufferLen;
} else {
// Stall if we don't have a dongle ready
return false;
}
break;
case XSM360_AUTH_KEEPALIVE:
len = 0;
break;
case XSM360_REQUEST_STATE:
// State Ready = 2, Not-Ready = 1
if ( xinputAuthData->xinputState == XInputAuthState::send_auth_dongle_to_console ) {
state = 2;
} else {
state = 1;
}
memcpy(tud_buffer, &state, sizeof(state));
len = sizeof(state);
break;
default:
break;
};
tud_control_xfer(rhport, request, tud_buffer, len);
}
} else if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) {
if (stage == CONTROL_STAGE_SETUP ) { // Pass on output setup in DIR OUT stage
tud_control_xfer(rhport, request, tud_buffer, request->wLength);
} else if ( stage == CONTROL_STAGE_DATA ) {
// Buf is filled, we can save the data to our auth
switch (request->bRequest) {
case XSM360AuthRequest::XSM360_INIT_AUTH:
if ( xinputAuthData->xinputState == XInputAuthState::auth_idle_state ) {
memcpy(xinputAuthData->passthruBuffer, tud_buffer, request->wLength);
xinputAuthData->passthruBufferLen = request->wLength;
xinputAuthData->passthruBufferID = XSM360AuthRequest::XSM360_INIT_AUTH;
xinputAuthData->xinputState = XInputAuthState::send_auth_console_to_dongle;
}
break;
case XSM360AuthRequest::XSM360_VERIFY_AUTH:
memcpy(xinputAuthData->passthruBuffer, tud_buffer, request->wLength);
xinputAuthData->passthruBufferLen = request->wLength;
xinputAuthData->passthruBufferID = XSM360AuthRequest::XSM360_VERIFY_AUTH;
xinputAuthData->xinputState = XInputAuthState::send_auth_console_to_dongle;
break;
default:
break;
};
}
}
return true;
}
const uint16_t * XInputDriver::get_descriptor_string_cb(uint8_t index, uint16_t langid) {

View File

@@ -16,7 +16,7 @@
#include <iterator>
GP2040Aux::GP2040Aux() : inputDriver(nullptr) {
GP2040Aux::GP2040Aux() : isReady(false), inputDriver(nullptr) {
}
GP2040Aux::~GP2040Aux() {
@@ -29,15 +29,6 @@ void GP2040Aux::setup() {
PeripheralManager::getInstance().initSPI();
PeripheralManager::getInstance().initUSB();
// Setup Add-ons
addons.LoadAddon(new DisplayAddon(), 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 DRV8833RumbleAddon(), CORE1_LOOP);
addons.LoadAddon(new ReactiveLEDAddon(), CORE1_LOOP);
// Initialize our input driver's auxilliary functions
inputDriver = DriverManager::getInstance().getDriver();
if ( inputDriver != nullptr ) {
@@ -52,6 +43,16 @@ void GP2040Aux::setup() {
// Initialize our USB manager
USBHostManager::getInstance().start();
// Setup Add-ons
addons.LoadAddon(new DisplayAddon(), 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);
// Ready to sync Core0 and Core1
isReady = true;
}
void GP2040Aux::run() {

View File

@@ -20,25 +20,34 @@ void __verbose_terminate_handler()
}
}
static GP2040 * gp2040Core0 = nullptr;
static GP2040Aux * gp2040Core1 = nullptr;
// Launch our second core with additional modules loaded in
void core1() {
multicore_lockout_victim_init(); // block core 1
// Create GP2040 w/ Additional Modules for Core 1
GP2040Aux * gp2040Core1 = new GP2040Aux();
// Create GP2040 w/ Additional Modules for Core 1
gp2040Core1->setup();
gp2040Core1->run();
}
int main() {
// Create GP2040 Main Core (core0), Core1 is dependent on Core0
GP2040 * gp2040 = new GP2040();
gp2040->setup();
gp2040Core0 = new GP2040();
gp2040Core1 = new GP2040Aux();
// Create GP2040 Main Core - Setup Core0
gp2040Core0->setup();
// Create GP2040 Thread for Core1
multicore_launch_core1(core1);
// Start Core0 Loop
gp2040->run();
// Sync Core0 and Core1
while(gp2040Core1->ready() == false ) {
__asm volatile ("nop\n");
}
gp2040Core0->run();
return 0;
}

View File

@@ -79,6 +79,8 @@ export default {
'<span>INFO:</span> Please ensure USB Peripheral is enabled and a PS5 compatible USB device is plugged in.',
'xbone-mode-text':
'<span>INFO:</span> Xbox One requires a USB host connection and USB dongle to properly authenticate in Xbox One mode.',
'xinput-mode-text':
'<span>INFO:</span> Xbox 360 mode can either work without authentication or with a USB dongle attached.',
'hotkey-settings-label': 'Hotkey Settings',
'hotkey-settings-sub-header':
'The <strong>Fn</strong> slider provides a mappable Function button in the <link_pinmap>Pin Mapping</link_pinmap> page. By selecting the <strong>Fn</strong> slider option, the Function button must be held along with the selected hotkey settings. <br /> Additionally, select <strong>None</strong> from the dropdown to unassign any button.',

View File

@@ -120,7 +120,12 @@ const SHA256 = (ascii) => {
};
const INPUT_MODES = [
{ labelKey: 'input-mode-options.xinput', value: 0, group: 'primary' }, //, authentication: ['none', 'usb'] }, AUTH WIP
{ labelKey: 'input-mode-options.xinput',
value: 0,
group: 'primary',
optional: ['usb'],
authentication: ['none', 'usb'],
},
{
labelKey: 'input-mode-options.nintendo-switch',
value: 1,
@@ -955,6 +960,28 @@ export default function SettingsPage() {
)}
</div>
);
case 'input-mode-options.xinput':
return (
<div className="row mb-3">
{generateAuthSelection(
inputMode,
t('SettingsPage:auth-settings-label'),
'xinputAuthType',
values.xinputAuthType,
errors.xinputAuthType,
handleChange,
)}
<Row className="mb-3">
<Col sm={10}>
<Trans
ns="SettingsPage"
i18nKey="xinput-mode-text"
components={{ span: <span className="text-success" /> }}
/>
</Col>
</Row>
</div>
);
case 'input-mode-options.xbone':
return (
<div className="row mb-3">