Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ src/drivers/psclassic/PSClassicDriver.cpp
src/drivers/sinput/SInputDriver.cpp
src/drivers/switch/SwitchDriver.cpp
src/drivers/switchpro/SwitchProDriver.cpp
src/drivers/switch2pro/Switch2ProDriver.cpp
src/drivers/xbone/XBOneAuth.cpp
src/drivers/xbone/XBOneAuthUSBListener.cpp
src/drivers/xbone/XBOneDriver.cpp
Expand Down Expand Up @@ -286,6 +287,8 @@ src/addons/playerleds.cpp
src/addons/reactiveleds.cpp
src/addons/rotaryencoder.cpp
src/addons/reverse.cpp
src/addons/amiibo.cpp
src/addons/amiibo_crypto.cpp
src/addons/drv8833_rumble.cpp
src/addons/turbo.cpp
src/addons/slider_socd.cpp
Expand Down
46 changes: 46 additions & 0 deletions headers/addons/amiibo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#ifndef _Amiibo_H
#define _Amiibo_H

#include "gpaddon.h"

#define AmiiboName "Amiibo"

#define AMIIBO_SLOT_COUNT 4
#define AMIIBO_DATA_SIZE 540
#define AMIIBO_SIGNATURE_SIZE 32
#define AMIIBO_FILE_SIZE (AMIIBO_DATA_SIZE + AMIIBO_SIGNATURE_SIZE)
#define AMIIBO_NAME_SIZE 32
#define AMIIBO_TAP_MS 2000
#define AMIIBO_KEY_SIZE 80

class AmiiboAddon : public GPAddon {
public:
virtual bool available();
virtual void setup();
virtual void preprocess() {}
virtual void process();
virtual void postprocess(bool sent) {}
virtual void reinit();
virtual std::string name() { return AmiiboName; }

static void tap(uint8_t slot);
static bool tagPresent();
static const uint8_t * tagData();
static const uint8_t * tagSignature();
static bool slotFilled(uint8_t slot);
static uint16_t slotSize(uint8_t slot);
static const char * slotName(uint8_t slot);
static bool slotRandomizeSerial(uint8_t slot);
static bool setSlotRandomizeSerial(uint8_t slot, bool enabled);
static bool writeSlot(uint8_t slot, const uint8_t * data, uint16_t length, const char * name);
static bool clearSlot(uint8_t slot);
static bool keyPresent(bool locked);
static bool writeKey(bool locked, const uint8_t * data, size_t length);
static bool clearKeys();
static uint32_t tapGeneration();
private:
Mask_t slotPinMasks[AMIIBO_SLOT_COUNT] = { };
Mask_t pressedPins = 0;
};

#endif
6 changes: 6 additions & 0 deletions headers/addons/amiibo_crypto.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>

bool amiiboKeyValid(const uint8_t *key, bool locked);
bool amiiboRandomize(const uint8_t *original540, uint8_t *output540,
const uint8_t *unfixed80, const uint8_t *locked80, const uint8_t *uid7);
36 changes: 22 additions & 14 deletions headers/display/ui/screens/ButtonLayoutScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include "GPGFX_UI_widgets.h"
#include "GPGFX_UI_layouts.h"

#define INPUT_HISTORY_MAX_INPUTS 22
#define INPUT_HISTORY_MAX_MODES 12
#define INPUT_HISTORY_MAX_INPUTS 23
#define INPUT_HISTORY_MAX_MODES 13

// Static to ensure memory is never doubled
static const char * displayNames[INPUT_HISTORY_MAX_MODES][INPUT_HISTORY_MAX_INPUTS] __attribute__((unused)) = {
Expand All @@ -24,84 +24,91 @@ static const char * displayNames[INPUT_HISTORY_MAX_MODES][INPUT_HISTORY_MAX_INPU
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
CHAR_CROSS, CHAR_CIRCLE, CHAR_SQUARE, CHAR_TRIANGLE,
"L1", "R1", "L2", "R2",
"SL", "ST", "L3", "R3", "PS", "A2"
"SL", "ST", "L3", "R3", "PS", "A2", ""
},
{ // Switch - 1
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"B", "A", "Y", "X",
"L", "R", "ZL", "ZR",
"-", "+", "LS", "RS", CHAR_HOME_S, CHAR_CAP_S
"-", "+", "LS", "RS", CHAR_HOME_S, CHAR_CAP_S, ""
},
{ // XInput - 2
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"A", "B", "X", "Y",
"LB", "RB", "LT", "RT",
CHAR_VIEW_X, CHAR_MENU_X, "LS", "RS", CHAR_HOME_X, "A2"
CHAR_VIEW_X, CHAR_MENU_X, "LS", "RS", CHAR_HOME_X, "A2", ""
},
{ // Keyboard / HID-KB - 3
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"B1", "B2", "B3", "B4",
"L1", "R1", "L2", "R2",
"S1", "S2", "L3", "R3", "A1", "A2"
"S1", "S2", "L3", "R3", "A1", "A2", ""
},
{ // PS4/PS5 - 4
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
CHAR_CROSS, CHAR_CIRCLE, CHAR_SQUARE, CHAR_TRIANGLE,
"L1", "R1", "L2", "R2",
CHAR_SHARE_P, "OP", "L3", "R3", CHAR_HOME_P, CHAR_TPAD_P
CHAR_SHARE_P, "OP", "L3", "R3", CHAR_HOME_P, CHAR_TPAD_P, ""
},
{ // GEN/MD Mini - 5
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"A", "B", "X", "Y",
"", "Z", "", "C",
"M", "S", "", "", "", ""
"M", "S", "", "", "", "", ""
},
{ // Neo Geo Mini - 6
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"B", "D", "A", "C",
"", "", "", "",
"SE", "ST", "", "", "", ""
"SE", "ST", "", "", "", "", ""
},
{ // PC Engine/TG16 Mini - 7
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"I", "II", "", "",
"", "", "", "",
"SE", "RUN", "", "", "", ""
"SE", "RUN", "", "", "", "", ""
},
{ // Egret II Mini - 8
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"A", "B", "C", "D",
"", "E", "", "F",
"CRD", "ST", "", "", "MN", ""
"CRD", "ST", "", "", "MN", "", ""
},
{ // Astro City Mini - 9
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"A", "B", "D", "E",
"", "C", "", "F",
"CRD", "ST", "", "", "", ""
"CRD", "ST", "", "", "", "", ""
},
{ // Original Xbox - 10
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"A", "B", "X", "Y",
"BL", "WH", "L", "R",
"BK", "ST", "LS", "RS", "", ""
"BK", "ST", "LS", "RS", "", "", ""
},
{ // HID / DINPUT - 11
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"2", "3", "1", "4",
"5", "6", "7", "8",
"9", "10", "11", "12", "13", "14"
"9", "10", "11", "12", "13", "14", ""
},
{ // Switch 2 Pro - 12
CHAR_UP, CHAR_DOWN, CHAR_LEFT, CHAR_RIGHT,
CHAR_UL, CHAR_UR, CHAR_DL, CHAR_DR,
"B", "A", "Y", "X",
"L", "R", "ZL", "ZR",
"-", "+", "LS", "RS", CHAR_HOME_S, CHAR_CAP_S, "C"
}
};

Expand Down Expand Up @@ -134,6 +141,7 @@ class ButtonLayoutScreen : public GPScreen {
const std::map<uint16_t, uint16_t> displayModeLookup = {
{INPUT_MODE_PS3, 0},
{INPUT_MODE_SWITCH, 1},
{INPUT_MODE_SWITCH2_PRO, 12},
{INPUT_MODE_XINPUT, 2},
{INPUT_MODE_XBONE, 2},
{INPUT_MODE_KEYBOARD, 3},
Expand Down
1 change: 1 addition & 0 deletions headers/display/ui/screens/MainMenuScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define INPUT_MODE_P5GENERAL_NAME "P5 General"
#define INPUT_MODE_SWITCH_PRO_NAME "Nintendo Switch Pro"
#define INPUT_MODE_SINPUT_NAME "SInput"
#define INPUT_MODE_SWITCH2_PRO_NAME "Nintendo Switch 2 Pro"
#define INPUT_MODE_CONFIG_NAME "Web Config"

#define SOCD_MODE_UP_PRIORITY_NAME "Up Priority"
Expand Down
181 changes: 181 additions & 0 deletions headers/drivers/switch2pro/Switch2ProDescriptors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* SPDX-License-Identifier: MIT
* Nintendo Switch 2 Pro Controller (057E:2069) USB identity.
*
* Descriptors and factory data follow mizuyoukanao/NX2-ProController-Emulation
* (RP2040 device-side emulation for Switch 2) and ndeadly/switch2_controller_research.
*/

#ifndef _SWITCH2_PRO_DESCRIPTORS_H_
#define _SWITCH2_PRO_DESCRIPTORS_H_

#include <stdint.h>

#define SWITCH2_GAMECUBE_PRODUCT_ID 0x2073

#define SWITCH2_FW_TYPE_PRO 0x02
#define SWITCH2_FW_TYPE_GAMECUBE 0x03

#define SWITCH2_PRO_DEVICE_PID_OFFSET 10
#define SWITCH2_PRO_FACTORY_PID_OFFSET 0x14
#define SWITCH2_PRO_GRIP_PID_OFFSET 24
#define SWITCH2_PRO_STRING_PRODUCT 2

#define SWITCH2_PRO_DEVICE_INFO_BT_OFFSET 10
#define SWITCH2_PRO_BT_RANDOM_BYTES 3
#define SWITCH2_PRO_FACTORY_SERIAL_DIGITS 5
#define SWITCH2_PRO_FACTORY_SERIAL_COUNT 11

#define SWITCH2_PRO_INPUT_REPORT_ID 0x09
#define SWITCH2_PRO_INPUT_REPORT_LEN 63

#define SWITCH2_PRO_ITF_HID 0
#define SWITCH2_PRO_ITF_VENDOR 1
#define SWITCH2_PRO_EP_BULK_OUT 0x02
#define SWITCH2_PRO_EP_BULK_IN 0x82

#define SWITCH2_PRO_MASK_B 0x01
#define SWITCH2_PRO_MASK_A 0x02
#define SWITCH2_PRO_MASK_Y 0x04
#define SWITCH2_PRO_MASK_X 0x08
#define SWITCH2_PRO_MASK_R 0x10
#define SWITCH2_PRO_MASK_ZR 0x20
#define SWITCH2_PRO_MASK_PLUS 0x40
#define SWITCH2_PRO_MASK_RSTICK 0x80

#define SWITCH2_PRO_MASK_DOWN 0x01
#define SWITCH2_PRO_MASK_RIGHT 0x02
#define SWITCH2_PRO_MASK_LEFT 0x04
#define SWITCH2_PRO_MASK_UP 0x08
#define SWITCH2_PRO_MASK_L 0x10
#define SWITCH2_PRO_MASK_ZL 0x20
#define SWITCH2_PRO_MASK_MINUS 0x40
#define SWITCH2_PRO_MASK_LSTICK 0x80

#define SWITCH2_PRO_MASK_HOME 0x01
#define SWITCH2_PRO_MASK_CAPTURE 0x02
#define SWITCH2_PRO_MASK_GR 0x04
#define SWITCH2_PRO_MASK_GL 0x08
#define SWITCH2_PRO_MASK_C 0x10

#define SWITCH2_PRO_STICK_MAX 0xFFF

static const uint8_t switch2pro_device_descriptor[] = {
0x12, // bLength
0x01, // bDescriptorType (Device)
0x00, 0x02, // bcdUSB 2.00
0xEF, // bDeviceClass (Miscellaneous)
0x02, // bDeviceSubClass (Common)
0x01, // bDeviceProtocol (Interface Association)
0x40, // bMaxPacketSize0 64
0x7E, 0x05, // idVendor 0x057E
0x69, 0x20, // idProduct 0x2069
0x01, 0x02, // bcdDevice 2.01
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
0x01, // bNumConfigurations
};

static const uint8_t switch2pro_device_qualifier[] = {
0x0A, // bLength
0x06, // bDescriptorType (Device Qualifier)
0x00, 0x02, // bcdUSB 2.00
0x00, 0x00, 0x00,
0x40, // bMaxPacketSize0 64
0x01, // bNumConfigurations
0x00, // bReserved
};

static const uint8_t switch2pro_report_descriptor[] = {
0x05, 0x01, 0x09, 0x05, 0xA1, 0x01, 0x85, 0x05, 0x05, 0xFF, 0x09, 0x01,
0x15, 0x00, 0x26, 0xFF, 0x00, 0x95, 0x3F, 0x75, 0x08, 0x81, 0x02, 0x85,
0x09, 0x09, 0x01, 0x95, 0x02, 0x81, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29,
0x15, 0x25, 0x01, 0x95, 0x15, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75,
0x03, 0x81, 0x03, 0x05, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x09, 0x30, 0x09,
0x31, 0x09, 0x33, 0x09, 0x35, 0x26, 0xFF, 0x0F, 0x95, 0x04, 0x75, 0x0C,
0x81, 0x02, 0xC0, 0x05, 0xFF, 0x09, 0x02, 0x26, 0xFF, 0x00, 0x95, 0x34,
0x75, 0x08, 0x81, 0x02, 0x85, 0x02, 0x09, 0x01, 0x95, 0x3F, 0x91, 0x02,
0xC0
};

static const uint8_t switch2pro_configuration_descriptor[] = {
0x09, 0x02, 0x50, 0x00, 0x02, 0x01, 0x04, 0xC0, 0xFA, 0x08, 0x0B, 0x00,
0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02, 0x03, 0x00,
0x00, 0x05, 0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0x61, 0x00, 0x07,
0x05, 0x81, 0x03, 0x40, 0x00, 0x04, 0x07, 0x05, 0x01, 0x03, 0x40, 0x00,
0x04, 0x08, 0x0B, 0x01, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x09, 0x04, 0x01,
0x00, 0x02, 0xFF, 0x00, 0x00, 0x06, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00,
0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
};

static const char * const switch2pro_strings[] = {
nullptr, // 0: language IDs (handled separately)
"Nintendo", // 1: manufacturer
"Switch 2 Pro Controller", // 2: product
"00", // 3: serial
"Config_0", // 4: configuration
"If_Hid", // 5: HID interface
"Switch 2 Pro Controller", // 6: vendor interface
};
static const char * const switch2gamecube_product_string = "Nintendo GameCube Controller";
static const uint16_t switch2pro_language_ids[] = { 0x0409, 0x0402, 0x0801 };

static const uint8_t switch2pro_device_info[] = {
0x02, 0x01, 0x04,
0x0C, 0x00, 0x00, 0x00,
0x00, 0x02, 0x03,
0xE8, 0x20, 0x17, 0x05, 0x48, 0xC8,
};
static const uint8_t switch2pro_bt_address_reversed[] = { 0xE8, 0x20, 0x17, 0x05, 0x48, 0xC8 };

#define SWITCH2_PRO_FACTORY_BODY_COLOR 0x19
#define SWITCH2_PRO_FACTORY_BUTTONS_COLOR 0x1C
#define SWITCH2_PRO_FACTORY_HIGHLIGHT_COLOR 0x1F
#define SWITCH2_PRO_FACTORY_GRIP_COLOR 0x22

static const uint8_t switch2pro_factory_data[] = {
0x01, 0x00,
0x48, 0x45, 0x4A, 0x31, 0x30, 0x30, 0x30, 0x30, 0x33, 0x31, 0x34, 0x33, 0x37, 0x32, 0x00, 0x00, // serial
0x7E, 0x05, // VID
0x69, 0x20, // PID
0x01, 0x06, 0x01,
0x23, 0x23, 0x23, // body colour
0xA0, 0xA0, 0xA0, // buttons colour
0xE6, 0xE6, 0xE6, // highlight colour
0x32, 0x32, 0x32, // grip colour
};

static const uint8_t switch2pro_flash_13040[] = {
0x85, 0x2e, 0xec, 0x41, 0x49, 0xec, 0x20, 0xbc, 0xc5, 0x5d, 0x3f, 0xbc, 0xad, 0x11, 0x42, 0x3b,
};
static const uint8_t switch2pro_flash_13080[] = {
0x01, 0xad, 0xd9, 0x9a, 0x55, 0x56, 0x65, 0xa0, 0x00, 0x0a, 0xa0, 0x00, 0x0a, 0xe2, 0x20, 0x0e,
0xe2, 0x20, 0x0e, 0x9a, 0xad, 0xd9, 0x9a, 0xad, 0xd9, 0x0a, 0xa5, 0x50, 0x0a, 0xa5, 0x50, 0x2f,
0xf6, 0x62, 0x2f, 0xf6, 0x62, 0x0a, 0xff, 0xff, 0xbc, 0x97, 0x85, 0x4f, 0x16, 0x5f, 0x2e, 0x96,
0x61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const uint8_t switch2pro_flash_130c0[] = {
0x01, 0xad, 0xd9, 0x9a, 0x55, 0x56, 0x65, 0xa0, 0x00, 0x0a, 0xa0, 0x00, 0x0a, 0xe2, 0x20, 0x0e,
0xe2, 0x20, 0x0e, 0x9a, 0xad, 0xd9, 0x9a, 0xad, 0xd9, 0x0a, 0xa5, 0x50, 0x0a, 0xa5, 0x50, 0x2f,
0xf6, 0x62, 0x2f, 0xf6, 0x62, 0x0a, 0xff, 0xff, 0x73, 0x38, 0x82, 0xf5, 0x55, 0x60, 0x2a, 0x56,
0x64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const uint8_t switch2pro_flash_13100[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd2, 0x7e, 0xbd,
0x33, 0x8a, 0xbe, 0xbe, 0xaa, 0x82, 0x20, 0x41,
};

static const uint8_t switch2pro_charging_grip_data[] = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x48, 0x45, 0x4a, 0x37, 0x31, 0x30, 0x30, 0x31, 0x31, 0x32,
0x31, 0x32, 0x34, 0x37, 0x00, 0x00, 0x7e, 0x05, 0x69, 0x20, 0x01, 0x06, 0x01, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
};

static const uint8_t switch2pro_device_key[] = {
0x10, 0x5f, 0x1a, 0xc4, 0x25, 0x63, 0x2b, 0xba, 0xe1, 0x05, 0xdf, 0x2c, 0x79, 0xee, 0xf6, 0x5c,
};

#endif // _SWITCH2_PRO_DESCRIPTORS_H_
Loading
Loading