convert files from CRLF endings to LF endings (#332)
bss@garnet ~/proj/GP2040-CE % find . -type f -exec file {} \; | grep CRLF | cut -d ':' -f 1 | xargs dos2unix
dos2unix: converting file ./lib/TinyUSB_Gamepad/src/ps4_driver.h to Unix format...
dos2unix: converting file ./lib/TinyUSB_Gamepad/src/ps4_driver.cpp to Unix format...
dos2unix: converting file ./lib/NeoPico/src/generated/ws2812.pio.h to Unix format...
dos2unix: converting file ./lib/httpd/fsdata.c to Unix format...
dos2unix: converting file ./www/.eslintrc.yml to Unix format...
dos2unix: converting file ./www/index.html to Unix format...
dos2unix: converting file ./www/vite.config.ts to Unix format...
dos2unix: converting file ./www/src/Components/ColorScheme.jsx to Unix format...
dos2unix: converting file ./www/src/index.jsx to Unix format...
dos2unix: converting file ./www/src/Icons/MoonStars.tsx to Unix format...
dos2unix: converting file ./www/src/Icons/CircleHalf.tsx to Unix format...
dos2unix: converting file ./www/src/Icons/Sun.tsx to Unix format...
dos2unix: converting file ./www/server/app.js to Unix format...
dos2unix: converting file ./www/.env to Unix format...
dos2unix: converting file ./src/addons/ps4mode.cpp to Unix format...
dos2unix: converting file ./.github/workflows/cmake.yml to Unix format...
dos2unix: converting file ./headers/gamepad/descriptors/PS4Descriptors.h to Unix format...
dos2unix: converting file ./headers/addons/ps4mode.h to Unix format...
dos2unix: converting file ./headers/mbedtls_config.h to Unix format...
dos2unix: converting file ./headers/configs/base64.h to Unix format...
dos2unix: converting file ./configs/Stress/README.md to Unix format...
dos2unix: converting file ./configs/Stress/env.ini to Unix format...
dos2unix: converting file ./configs/Stress/stress.h to Unix format...
dos2unix: converting file ./configs/Stress/BoardConfig.h to Unix format...
This commit is contained in:
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto
|
||||
120
.github/workflows/cmake.yml
vendored
120
.github/workflows/cmake.yml
vendored
@@ -1,60 +1,60 @@
|
||||
name: CMake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
pull_request_target:
|
||||
branches: [ "main" ]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
call-node-workflow:
|
||||
uses: ./.github/workflows/node.js.yml
|
||||
build:
|
||||
needs: call-node-workflow
|
||||
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
|
||||
# You can convert this to a matrix build if you need cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
GP2040_BOARDCONFIG: [Pico, BentoBox, DURAL, FightboardV3, FightboardV3Mirrored, FlatboxRev4, FlatboxRev5, KB2040, MavercadeKeebfighter, PicoAnn, PicoFightingBoard, ReflexEncoder, RP2040AdvancedBreakoutBoard, RP2040MiniBreakoutBoard, SparkFunProMicro, WaveshareZero, Stress ]
|
||||
|
||||
steps:
|
||||
#Global Setup
|
||||
- name: Checkout GP2040-CE
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup SDK pipeline
|
||||
uses: Fortinbra/RaspberryPiPicoBuild@v1
|
||||
|
||||
- name: Download a Build Artifact
|
||||
uses: actions/download-artifact@v3.0.2
|
||||
with:
|
||||
name: fsData
|
||||
path: ${{github.workspace}}/lib/httpd/
|
||||
|
||||
- name: Get core count
|
||||
id: core_count
|
||||
run : cat /proc/cpuinfo | grep processor | wc -l
|
||||
#End Global Setup
|
||||
|
||||
- name: Pico Build Configure CMake
|
||||
shell: bash
|
||||
run: PICO_SDK_PATH=${{github.workspace}}/pico-sdk GP2040_BOARDCONFIG=${{ matrix.GP2040_BOARDCONFIG }} SKIP_WEBBUILD=TRUE cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Pico Build
|
||||
shell: bash
|
||||
run: GP2040_BOARDCONFIG=${{ matrix.GP2040_BOARDCONFIG }} cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel ${{steps.core_count.outputs.output}}
|
||||
|
||||
- name: Upload Pico Artifact
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: GP2040-CE - ${{ matrix.GP2040_BOARDCONFIG }}
|
||||
path: ${{github.workspace}}/build/GP2040-CE_*_${{ matrix.GP2040_BOARDCONFIG }}.uf2
|
||||
if-no-files-found: error
|
||||
name: CMake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
pull_request_target:
|
||||
branches: [ "main" ]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
call-node-workflow:
|
||||
uses: ./.github/workflows/node.js.yml
|
||||
build:
|
||||
needs: call-node-workflow
|
||||
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
|
||||
# You can convert this to a matrix build if you need cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
GP2040_BOARDCONFIG: [Pico, BentoBox, DURAL, FightboardV3, FightboardV3Mirrored, FlatboxRev4, FlatboxRev5, KB2040, MavercadeKeebfighter, PicoAnn, PicoFightingBoard, ReflexEncoder, RP2040AdvancedBreakoutBoard, RP2040MiniBreakoutBoard, SparkFunProMicro, WaveshareZero, Stress ]
|
||||
|
||||
steps:
|
||||
#Global Setup
|
||||
- name: Checkout GP2040-CE
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup SDK pipeline
|
||||
uses: Fortinbra/RaspberryPiPicoBuild@v1
|
||||
|
||||
- name: Download a Build Artifact
|
||||
uses: actions/download-artifact@v3.0.2
|
||||
with:
|
||||
name: fsData
|
||||
path: ${{github.workspace}}/lib/httpd/
|
||||
|
||||
- name: Get core count
|
||||
id: core_count
|
||||
run : cat /proc/cpuinfo | grep processor | wc -l
|
||||
#End Global Setup
|
||||
|
||||
- name: Pico Build Configure CMake
|
||||
shell: bash
|
||||
run: PICO_SDK_PATH=${{github.workspace}}/pico-sdk GP2040_BOARDCONFIG=${{ matrix.GP2040_BOARDCONFIG }} SKIP_WEBBUILD=TRUE cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Pico Build
|
||||
shell: bash
|
||||
run: GP2040_BOARDCONFIG=${{ matrix.GP2040_BOARDCONFIG }} cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel ${{steps.core_count.outputs.output}}
|
||||
|
||||
- name: Upload Pico Artifact
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: GP2040-CE - ${{ matrix.GP2040_BOARDCONFIG }}
|
||||
path: ${{github.workspace}}/build/GP2040-CE_*_${{ matrix.GP2040_BOARDCONFIG }}.uf2
|
||||
if-no-files-found: error
|
||||
|
||||
@@ -1,265 +1,265 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#ifndef PICO_BOARD_CONFIG_H_
|
||||
#define PICO_BOARD_CONFIG_H_
|
||||
|
||||
#include <GamepadEnums.h>
|
||||
// This is the main pin definition section.
|
||||
// This will let you specify which GPIO pin each button is assigned too.
|
||||
// You can set any of the main pins as `-1` to disable it.
|
||||
// The Turbo pin and LS + RS slider pins can also be set to `-1` to disable that functionality.
|
||||
// Please note that only when `PIN_BUTTON_TURBO` is set to `-1` will the `T##` be removed from a connected display.
|
||||
// Please note that only when `PIN_SLIDER_LS` and `PIN_SLIDER_RS` are set to `-1` will the button combo shortcut for DP/LS/RS work.
|
||||
// The buttons are listed in GP2040 configuration, beside each the listed order is *GP2040 / Xinput / Switch / PS3 / Directinput / Arcade*
|
||||
|
||||
#define PIN_DPAD_UP 26 // UP
|
||||
#define PIN_DPAD_DOWN 28 // DOWN
|
||||
#define PIN_DPAD_LEFT 29 // LEFT
|
||||
#define PIN_DPAD_RIGHT 27 // RIGHT
|
||||
#define PIN_BUTTON_B1 1 // B1 / A / B / Cross / 2 / K1
|
||||
#define PIN_BUTTON_B2 3 // B2 / B / A / Circle / 3 / K2
|
||||
#define PIN_BUTTON_B3 0 // B3 / X / Y / Square / 1 / P1
|
||||
#define PIN_BUTTON_B4 2 // B4 / Y / X / Triangle / 4 / P2
|
||||
#define PIN_BUTTON_L1 5 // L1 / LB / L / L1 / 5 / P4
|
||||
#define PIN_BUTTON_R1 4 // R1 / RB / R / R1 / 6 / P3
|
||||
#define PIN_BUTTON_L2 6 // L2 / LT / ZL / L2 / 7 / K4
|
||||
#define PIN_BUTTON_R2 7 // R2 / RT / ZR / R2 / 8 / K3
|
||||
#define PIN_BUTTON_S1 8 // S1 / Back / Minus / Select / 9 / Coin
|
||||
#define PIN_BUTTON_S2 9 // S2 / Start / Plus / Start / 10 / Start
|
||||
#define PIN_BUTTON_L3 12 // L3 / LS / LS / L3 / 11 / LS
|
||||
#define PIN_BUTTON_R3 13 // R3 / RS / RS / R3 / 12 / RS
|
||||
#define PIN_BUTTON_A1 14 // A1 / Guide / Home / PS / 13 / ~
|
||||
#define PIN_BUTTON_A2 15 // A2 / ~ / Capture / ~ / 14 / ~
|
||||
#define PIN_BUTTON_TURBO -1 // Turbo
|
||||
#define PIN_BUTTON_REVERSE -1 // UDLR Reverse
|
||||
#define PIN_SLIDER_LS -1 // Left Stick Slider
|
||||
#define PIN_SLIDER_RS -1 // Right Stick Slider
|
||||
#define PIN_SLIDER_SOCD_ONE -1 // SOCD Slider Pin One
|
||||
#define PIN_SLIDER_SOCD_TWO -1 // SOCD Slider Pin Two
|
||||
|
||||
|
||||
// This is the SOCD section.
|
||||
// SOCD stands for `simultaneous opposing cardinal directions`.
|
||||
// There are three options for `DEFAULT_SOCD_MODE` currently:
|
||||
// 1 - `SOCD_MODE_NEUTRAL` - This is a neutral SOCD. EG. when you press `up` + `down` no input will be registered.
|
||||
// 2 - `SOCD_MODE_UP_PRIORITY` - This is up priority SOCD. EG. when you press `up` + `down` `up` will be registered.
|
||||
// 3 - `SOCD_MODE_SECOND_INPUT_PRIORITY` - This is last priority SOCD. EG. when you press and hold `up` then press `down` `down` will be registered.
|
||||
// 4 - `SOCD_MODE_FIRST_INPUT_PRIORITY` - This is first priority SOCD. EG. when you press and hold `up` then press `down` `up` will be registered.
|
||||
|
||||
#define DEFAULT_SOCD_MODE SOCD_MODE_NEUTRAL
|
||||
// SOCD Slider Slot Defaults
|
||||
#define SLIDER_SOCD_SLOT_ONE SOCD_MODE_UP_PRIORITY
|
||||
#define SLIDER_SOCD_SLOT_TWO SOCD_MODE_SECOND_INPUT_PRIORITY
|
||||
#define SLIDER_SOCD_SLOT_DEFAULT SOCD_MODE_NEUTRAL
|
||||
|
||||
#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
|
||||
|
||||
// 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.
|
||||
// It is recommended to disable the `TURBO_LED_PIN` by setting it to `-1` if you are sensitive of flashing lights.
|
||||
// The default `BOARD_LEDS_PIN` pin is set to `28`.
|
||||
// The board LED pin will allow you to connect addressible RGB LEDs on the Pico.
|
||||
// Addressible RGB LEDs should be connected to the `VBUS` pin (#40), an avalible ground pin and the defined `BOARD_LEDS_PIN`.
|
||||
// Special note - You should only ever use addressible RGB LEDs that are rated for 5v operation on the Pico.
|
||||
// The defualt `LED_BRIGHTNESS_MAXIMUM` value is `50`.
|
||||
// This will change how bright the LEDs are with `0` being off and `100` being full brightness.
|
||||
// The minimum `LED_BRIGHTNESS_MAXIMUM` value is `0`.
|
||||
// The maximum `LED_BRIGHTNESS_MAXIMUM` value is `100`.
|
||||
// The defualt `LED_BRIGHTNESS_STEPS` value is `5`.
|
||||
// This will change how many brightness steps there are when increasing or decreasing the brightness of the LEDs via the onboard shortcut.
|
||||
// It is recommend to keep this value at `5` or `10`.
|
||||
// The defualt `LED_FORMAT` is `LED_FORMAT_GRB`.
|
||||
// You can also choose the `LED_FORMAT` of `LED_FORMAT_RGB` if your addressible RGB LEDs are not working as intended.
|
||||
// The defualt `LEDS_PER_PIXEL` is set to `1`.
|
||||
// This will change how many addressible RGB LEDs there are per button.
|
||||
// The default LEDS_[BUTTON] is an order and has nothing to do with what GPIO pin something is connected to.
|
||||
// Unless you are planning on running custom animations I would recommmend you leave this as is.
|
||||
|
||||
#define TURBO_LED_PIN -1
|
||||
|
||||
#define BOARD_LEDS_PIN -1
|
||||
|
||||
#define LED_BRIGHTNESS_MAXIMUM 50
|
||||
#define LED_BRIGHTNESS_STEPS 5
|
||||
#define LED_FORMAT LED_FORMAT_GRB
|
||||
#define LEDS_PER_PIXEL 1
|
||||
|
||||
#define LEDS_DPAD_LEFT 0
|
||||
#define LEDS_DPAD_DOWN 1
|
||||
#define LEDS_DPAD_RIGHT 2
|
||||
#define LEDS_DPAD_UP 3
|
||||
#define LEDS_BUTTON_B3 4
|
||||
#define LEDS_BUTTON_B4 5
|
||||
#define LEDS_BUTTON_R1 6
|
||||
#define LEDS_BUTTON_L1 7
|
||||
#define LEDS_BUTTON_B1 8
|
||||
#define LEDS_BUTTON_B2 9
|
||||
#define LEDS_BUTTON_R2 10
|
||||
#define LEDS_BUTTON_L2 11
|
||||
|
||||
|
||||
// This is the Player LED section.
|
||||
// In this section you can specify if Player LEDs will be active, and, if active, which pins will be used for them.
|
||||
// The defualt is `PLED_TYPE_NONE` which will turn the Player LEDs off.
|
||||
// The default pin for each Player LED is `-1` which disables it.
|
||||
// To enable a `PLED#_PIN`, replace the `-1` with the GPIO pin number that is desired.
|
||||
// There are three options for `PLED_TYPE` currently:
|
||||
// 1 - `PLED_TYPE_NONE` - This will disable the Player LEDs
|
||||
// 2 - `PLED_TYPE_PWM` - This will enable the Player LEDs ( it is recommended to run through 3V3(OUT) with a resistor)
|
||||
// 3 - `PLED_TYPE_RGB` - This will enable the Player LEDs as addressible RGB LEDs (please not that this has not been implemented yet)
|
||||
|
||||
#define PLED_TYPE PLED_TYPE_NONE
|
||||
#define PLED1_PIN -1
|
||||
#define PLED2_PIN -1
|
||||
#define PLED3_PIN -1
|
||||
#define PLED4_PIN -1
|
||||
|
||||
|
||||
// This is the Analog section.
|
||||
// In this section you can specify if Analog is enabled, and, if endabled, which pins will be used for it.
|
||||
// The default for `ANALOG_ADC_VRX` and `ANALOG_ADC_VRY` is `-1` which disables them.
|
||||
// To enable a `ANALOG_ADC_VRX` and `ANALOG_ADC_VRY`, replace the `-1` with the GPIO pin numbers that are desired.
|
||||
|
||||
#define ANALOG_ADC_VRX -1
|
||||
#define ANALOG_ADC_VRY -1
|
||||
|
||||
// Reverse Button section
|
||||
#define REVERSE_LED_PIN -1
|
||||
|
||||
// This is the I2C Display section (commonly known as the OLED display section).
|
||||
// In this section you can specify if a display as been enabled, which pins are assined to it, the block address and speed.
|
||||
// The default for `HAS_I2C_DISPLAY` is `1` which enables it.
|
||||
// To disable the display you can change `HAS_I2C_DISPLAY` to `-1`.
|
||||
// The default `I2C_SDA_PIN` is `0`.
|
||||
// The defualt `I2C_SCL_PIN` is `1`.
|
||||
// The defualt `I2C_BLOCK` is `12c0`.
|
||||
// If you change the `I2C_SDA_PIN` and `I2C_SCL_PIN` pin mapping, you may need to change the `I2C_BLOCK` as well.
|
||||
// The defualt `I2C_SPEED` is `400000`.
|
||||
// This should be more than fast enough for most displays.
|
||||
// Some smaller displays (like 0.96" and 1.31") can go up to `800000` or even `1000000`.
|
||||
// The default `DISPLAY_FLIP` is `0`.
|
||||
// This can be changed to `1` to have the dispaly output flipped.
|
||||
// The default `DISPLAY_INVERY` is `0`.
|
||||
// This can be changed to `1` to have the color on the display inverted.
|
||||
// The default `BUTTON_LAYOUT` is `BUTTON_LAYOUT_STICK` which will show an arcade stick on the left hand side of the display.
|
||||
// There are seven options for `BUTTON_LAYOUT` currently:
|
||||
// 1 - BUTTON_LAYOUT_STICK - This is a basic joystick layout
|
||||
// 2 - BUTTON_LAYOUT_STICKLESS - This is a basic stickless (all button) layout
|
||||
// 3 - BUTTON_LAYOUT_BUTTONS_ANGLED - This a WASD button layout that is angled
|
||||
// 4 - BUTTON_LAYOUT_BUTTONS_BASIC - This a WASD button layout that is straight
|
||||
// 5 - BUTTON_LAYOUT_KEYBOARD_ANGLED - This is a WASD keyboard layout that is angled
|
||||
// 6 - BUTTON_LAYOUT_KEYBOARDA - This is a WASD keyboard layout that is straight
|
||||
// 7 - BUTTON_LAYOUT_DANCEPADA - This is a dance pad layout (must be used with `BUTTON_LAYOUT_DANCEPADB` in `BUTTON_LAYOUT_RIGHT`)
|
||||
// The default `BUTTON_LAYOUT_RIGHT` is `BUTTON_LAYOUT_NOIR8` which will show eight buttons on the right hand side of the display.
|
||||
// There are eleven options for `BUTTON_LAYOUT_RIGHT` currently:
|
||||
// 1 - BUTTON_LAYOUT_ARCADE - This is a standard 8 button arcade layout
|
||||
// 2 - BUTTON_LAYOUT_STICKLESSB - This is a basic stickless (all button) layout
|
||||
// 3 - BUTTON_LAYOUT_BUTTONS_ANGLEDB - This is a standard 8 button arcade layout that is angled
|
||||
// 4 - BUTTON_LAYOUT_VEWLIX - This is the standard 8 button Vewlix layout
|
||||
// 5 - BUTTON_LAYOUT_VEWLIX7 - This is the standard 7 button Vewlix layout
|
||||
// 6 - BUTTON_LAYOUT_CAPCOM - This is the standard 8 button Capcom layout
|
||||
// 7 - BUTTON_LAYOUT_CAPCOM6 - This is the stndard 6 button Capcom layout
|
||||
// 8 - BUTTON_LAYOUT_SEGA2P - This is the standard 8 button Sega2P layout
|
||||
// 9 - BUTTON_LAYOUT_NOIR8 - This is the standard 8 button Noir layout
|
||||
// 10 - BUTTON_LAYOUT_KEYBOARDB - This is a WASD keyboard layout that is straight
|
||||
// 11 - BUTTON_LAYOUT_DANCEPADB - This is a dance pad layout (must be used with `BUTTON_LAYOUT_DANCEPADA` in `BUTTON_LAYOUT`)
|
||||
// The default `SPLASH_MODE` is `NOSPLASH`.
|
||||
// There are four options for `SPLASH_MODE` currently:
|
||||
// 1 - `STATICSPLASH` - This will display the static splash image
|
||||
// 2 - `CLOSEIN` - This will display the static splash image as a top and bottom coming together animation
|
||||
// 3 - `CLOSEINCUSTOM` - This will display the custom splash image as a top and bottom coming together animation
|
||||
// 4 - `NOSPLASH` - This will not display a splash screen on boot
|
||||
// Special note - All of the splash screen images can be changed via `include/bitmaps.h`
|
||||
|
||||
#define HAS_I2C_DISPLAY -1
|
||||
#define I2C_SDA_PIN 0
|
||||
#define I2C_SCL_PIN 1
|
||||
#define I2C_BLOCK i2c0
|
||||
#define I2C_SPEED 400000
|
||||
#define DISPLAY_FLIP 0
|
||||
#define DISPLAY_INVERT 0
|
||||
|
||||
#define REVERSE_UP_DEFAULT 1
|
||||
#define REVERSE_DOWN_DEFAULT 1
|
||||
#define REVERSE_LEFT_DEFAULT 1
|
||||
#define REVERSE_RIGHT_DEFAULT 1
|
||||
|
||||
#define BUTTON_LAYOUT BUTTON_LAYOUT_STICK
|
||||
#define BUTTON_LAYOUT_RIGHT BUTTON_LAYOUT_VEWLIX
|
||||
#define SPLASH_MODE SPLASH_MODE_NONE
|
||||
#define SPLASH_CHOICE SPLASH_CHOICE_MAIN
|
||||
#define SPLASH_DURATION 7500 // Duration in milliseconds
|
||||
|
||||
// Board LED Add-on Setting
|
||||
// BOARD_LED_OFF - Turns the on-board LED off
|
||||
// MODE_INDICATOR - On-board LED blinks on various frequencies depending
|
||||
// on the current mode (config, normal, or no USB data)
|
||||
// INPUT_TEST - Blinks whenever any input is made
|
||||
|
||||
#define BOARD_LED_TYPE ON_BOARD_LED_MODE_OFF
|
||||
|
||||
// Dual Directional Add-on Options
|
||||
|
||||
#define PIN_DUAL_DIRECTIONAL_UP -1
|
||||
#define PIN_DUAL_DIRECTIONAL_DOWN -1
|
||||
#define PIN_DUAL_DIRECTIONAL_LEFT -1
|
||||
#define PIN_DUAL_DIRECTIONAL_RIGHT -1
|
||||
#define DUAL_DIRECTIONAL_STICK_MODE DPAD_MODE_DIGITAL
|
||||
#define DUAL_DIRECTIONAL_COMBINE_MODE DUAL_COMBINE_MODE_MIXED
|
||||
|
||||
// BOOTSEL Button Add-on setting
|
||||
#define BOOTSEL_BUTTON_MASK 0 // 0 means none, get other mask from GamepadState.h
|
||||
|
||||
// Extra Button Add-on setting
|
||||
#define EXTRA_BUTTON_MASK 0 // 0 means none, get other mask from GamepadState.h
|
||||
// For directions, use GAMEPAD_MASK_DU, GAMEPAD_MASK_DD, GAMEPAD_MASK_DL and GAMEPAD_MASK_DR
|
||||
#define EXTRA_BUTTON_PIN -1
|
||||
|
||||
// Keyboard Mapping Configuration
|
||||
// List of HID keycodes can be located here: https://github.com/hathach/tinyusb/blob/3623ba1884ddff23e9b64766cb6dd032f1425846/src/class/hid/hid.h#L356
|
||||
// Even for the modifier keys, HID_KEY entries should be used as the implementation expects those and will convert as necessary.
|
||||
#define KEY_DPAD_UP HID_KEY_ARROW_UP // UP
|
||||
#define KEY_DPAD_DOWN HID_KEY_ARROW_DOWN // DOWN
|
||||
#define KEY_DPAD_LEFT HID_KEY_ARROW_LEFT // LEFT
|
||||
#define KEY_DPAD_RIGHT HID_KEY_ARROW_RIGHT // RIGHT
|
||||
#define KEY_BUTTON_B1 HID_KEY_SHIFT_LEFT // B1 / A / B / Cross / 2 / K1
|
||||
#define KEY_BUTTON_B2 HID_KEY_Z // B2 / B / A / Circle / 3 / K2
|
||||
#define KEY_BUTTON_B3 HID_KEY_CONTROL_LEFT // B3 / X / Y / Square / 1 / P1
|
||||
#define KEY_BUTTON_B4 HID_KEY_ALT_LEFT // B4 / Y / X / Triangle / 4 / P2
|
||||
#define KEY_BUTTON_L1 HID_KEY_C // L1 / LB / L / L1 / 5 / P4
|
||||
#define KEY_BUTTON_R1 HID_KEY_SPACE // R1 / RB / R / R1 / 6 / P3
|
||||
#define KEY_BUTTON_L2 HID_KEY_V // L2 / LT / ZL / L2 / 7 / K4
|
||||
#define KEY_BUTTON_R2 HID_KEY_X // R2 / RT / ZR / R2 / 8 / K3
|
||||
#define KEY_BUTTON_S1 HID_KEY_5 // S1 / Back / Minus / Select / 9 / Coin
|
||||
#define KEY_BUTTON_S2 HID_KEY_1 // S2 / Start / Plus / Start / 10 / Start
|
||||
#define KEY_BUTTON_L3 HID_KEY_EQUAL // L3 / LS / LS / L3 / 11 / LS
|
||||
#define KEY_BUTTON_R3 HID_KEY_MINUS // R3 / RS / RS / R3 / 12 / RS
|
||||
#define KEY_BUTTON_A1 HID_KEY_9 // A1 / Guide / Home / PS / 13 / ~
|
||||
#define KEY_BUTTON_A2 HID_KEY_F2 // A2 / ~ / Capture / ~ / 14 / ~
|
||||
|
||||
// Hotkey Action Mapping
|
||||
// Find the list of hotkey actions in GamepadEnums.h
|
||||
#define HOTKEY_F1_UP_MASK GAMEPAD_MASK_UP
|
||||
#define HOTKEY_F1_UP_ACTION HOTKEY_HOME_BUTTON
|
||||
#define HOTKEY_F1_DOWN_MASK GAMEPAD_MASK_DOWN
|
||||
#define HOTKEY_F1_DOWN_ACTION HOTKEY_DPAD_DIGITAL
|
||||
#define HOTKEY_F1_LEFT_MASK GAMEPAD_MASK_LEFT
|
||||
#define HOTKEY_F1_LEFT_ACTION HOTKEY_DPAD_LEFT_ANALOG
|
||||
#define HOTKEY_F1_RIGHT_MASK GAMEPAD_MASK_RIGHT
|
||||
#define HOTKEY_F1_RIGHT_ACTION HOTKEY_DPAD_RIGHT_ANALOG
|
||||
|
||||
#define HOTKEY_F2_UP_MASK GAMEPAD_MASK_UP
|
||||
#define HOTKEY_F2_UP_ACTION HOTKEY_SOCD_UP_PRIORITY
|
||||
#define HOTKEY_F2_DOWN_MASK GAMEPAD_MASK_DOWN
|
||||
#define HOTKEY_F2_DOWN_ACTION HOTKEY_SOCD_NEUTRAL
|
||||
#define HOTKEY_F2_LEFT_MASK GAMEPAD_MASK_LEFT
|
||||
#define HOTKEY_F2_LEFT_ACTION HOTKEY_SOCD_LAST_INPUT
|
||||
#define HOTKEY_F2_RIGHT_MASK GAMEPAD_MASK_RIGHT
|
||||
#define HOTKEY_F2_RIGHT_ACTION HOTKEY_INVERT_Y_AXIS
|
||||
|
||||
#endif
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#ifndef PICO_BOARD_CONFIG_H_
|
||||
#define PICO_BOARD_CONFIG_H_
|
||||
|
||||
#include <GamepadEnums.h>
|
||||
// This is the main pin definition section.
|
||||
// This will let you specify which GPIO pin each button is assigned too.
|
||||
// You can set any of the main pins as `-1` to disable it.
|
||||
// The Turbo pin and LS + RS slider pins can also be set to `-1` to disable that functionality.
|
||||
// Please note that only when `PIN_BUTTON_TURBO` is set to `-1` will the `T##` be removed from a connected display.
|
||||
// Please note that only when `PIN_SLIDER_LS` and `PIN_SLIDER_RS` are set to `-1` will the button combo shortcut for DP/LS/RS work.
|
||||
// The buttons are listed in GP2040 configuration, beside each the listed order is *GP2040 / Xinput / Switch / PS3 / Directinput / Arcade*
|
||||
|
||||
#define PIN_DPAD_UP 26 // UP
|
||||
#define PIN_DPAD_DOWN 28 // DOWN
|
||||
#define PIN_DPAD_LEFT 29 // LEFT
|
||||
#define PIN_DPAD_RIGHT 27 // RIGHT
|
||||
#define PIN_BUTTON_B1 1 // B1 / A / B / Cross / 2 / K1
|
||||
#define PIN_BUTTON_B2 3 // B2 / B / A / Circle / 3 / K2
|
||||
#define PIN_BUTTON_B3 0 // B3 / X / Y / Square / 1 / P1
|
||||
#define PIN_BUTTON_B4 2 // B4 / Y / X / Triangle / 4 / P2
|
||||
#define PIN_BUTTON_L1 5 // L1 / LB / L / L1 / 5 / P4
|
||||
#define PIN_BUTTON_R1 4 // R1 / RB / R / R1 / 6 / P3
|
||||
#define PIN_BUTTON_L2 6 // L2 / LT / ZL / L2 / 7 / K4
|
||||
#define PIN_BUTTON_R2 7 // R2 / RT / ZR / R2 / 8 / K3
|
||||
#define PIN_BUTTON_S1 8 // S1 / Back / Minus / Select / 9 / Coin
|
||||
#define PIN_BUTTON_S2 9 // S2 / Start / Plus / Start / 10 / Start
|
||||
#define PIN_BUTTON_L3 12 // L3 / LS / LS / L3 / 11 / LS
|
||||
#define PIN_BUTTON_R3 13 // R3 / RS / RS / R3 / 12 / RS
|
||||
#define PIN_BUTTON_A1 14 // A1 / Guide / Home / PS / 13 / ~
|
||||
#define PIN_BUTTON_A2 15 // A2 / ~ / Capture / ~ / 14 / ~
|
||||
#define PIN_BUTTON_TURBO -1 // Turbo
|
||||
#define PIN_BUTTON_REVERSE -1 // UDLR Reverse
|
||||
#define PIN_SLIDER_LS -1 // Left Stick Slider
|
||||
#define PIN_SLIDER_RS -1 // Right Stick Slider
|
||||
#define PIN_SLIDER_SOCD_ONE -1 // SOCD Slider Pin One
|
||||
#define PIN_SLIDER_SOCD_TWO -1 // SOCD Slider Pin Two
|
||||
|
||||
|
||||
// This is the SOCD section.
|
||||
// SOCD stands for `simultaneous opposing cardinal directions`.
|
||||
// There are three options for `DEFAULT_SOCD_MODE` currently:
|
||||
// 1 - `SOCD_MODE_NEUTRAL` - This is a neutral SOCD. EG. when you press `up` + `down` no input will be registered.
|
||||
// 2 - `SOCD_MODE_UP_PRIORITY` - This is up priority SOCD. EG. when you press `up` + `down` `up` will be registered.
|
||||
// 3 - `SOCD_MODE_SECOND_INPUT_PRIORITY` - This is last priority SOCD. EG. when you press and hold `up` then press `down` `down` will be registered.
|
||||
// 4 - `SOCD_MODE_FIRST_INPUT_PRIORITY` - This is first priority SOCD. EG. when you press and hold `up` then press `down` `up` will be registered.
|
||||
|
||||
#define DEFAULT_SOCD_MODE SOCD_MODE_NEUTRAL
|
||||
// SOCD Slider Slot Defaults
|
||||
#define SLIDER_SOCD_SLOT_ONE SOCD_MODE_UP_PRIORITY
|
||||
#define SLIDER_SOCD_SLOT_TWO SOCD_MODE_SECOND_INPUT_PRIORITY
|
||||
#define SLIDER_SOCD_SLOT_DEFAULT SOCD_MODE_NEUTRAL
|
||||
|
||||
#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
|
||||
|
||||
// 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.
|
||||
// It is recommended to disable the `TURBO_LED_PIN` by setting it to `-1` if you are sensitive of flashing lights.
|
||||
// The default `BOARD_LEDS_PIN` pin is set to `28`.
|
||||
// The board LED pin will allow you to connect addressible RGB LEDs on the Pico.
|
||||
// Addressible RGB LEDs should be connected to the `VBUS` pin (#40), an avalible ground pin and the defined `BOARD_LEDS_PIN`.
|
||||
// Special note - You should only ever use addressible RGB LEDs that are rated for 5v operation on the Pico.
|
||||
// The defualt `LED_BRIGHTNESS_MAXIMUM` value is `50`.
|
||||
// This will change how bright the LEDs are with `0` being off and `100` being full brightness.
|
||||
// The minimum `LED_BRIGHTNESS_MAXIMUM` value is `0`.
|
||||
// The maximum `LED_BRIGHTNESS_MAXIMUM` value is `100`.
|
||||
// The defualt `LED_BRIGHTNESS_STEPS` value is `5`.
|
||||
// This will change how many brightness steps there are when increasing or decreasing the brightness of the LEDs via the onboard shortcut.
|
||||
// It is recommend to keep this value at `5` or `10`.
|
||||
// The defualt `LED_FORMAT` is `LED_FORMAT_GRB`.
|
||||
// You can also choose the `LED_FORMAT` of `LED_FORMAT_RGB` if your addressible RGB LEDs are not working as intended.
|
||||
// The defualt `LEDS_PER_PIXEL` is set to `1`.
|
||||
// This will change how many addressible RGB LEDs there are per button.
|
||||
// The default LEDS_[BUTTON] is an order and has nothing to do with what GPIO pin something is connected to.
|
||||
// Unless you are planning on running custom animations I would recommmend you leave this as is.
|
||||
|
||||
#define TURBO_LED_PIN -1
|
||||
|
||||
#define BOARD_LEDS_PIN -1
|
||||
|
||||
#define LED_BRIGHTNESS_MAXIMUM 50
|
||||
#define LED_BRIGHTNESS_STEPS 5
|
||||
#define LED_FORMAT LED_FORMAT_GRB
|
||||
#define LEDS_PER_PIXEL 1
|
||||
|
||||
#define LEDS_DPAD_LEFT 0
|
||||
#define LEDS_DPAD_DOWN 1
|
||||
#define LEDS_DPAD_RIGHT 2
|
||||
#define LEDS_DPAD_UP 3
|
||||
#define LEDS_BUTTON_B3 4
|
||||
#define LEDS_BUTTON_B4 5
|
||||
#define LEDS_BUTTON_R1 6
|
||||
#define LEDS_BUTTON_L1 7
|
||||
#define LEDS_BUTTON_B1 8
|
||||
#define LEDS_BUTTON_B2 9
|
||||
#define LEDS_BUTTON_R2 10
|
||||
#define LEDS_BUTTON_L2 11
|
||||
|
||||
|
||||
// This is the Player LED section.
|
||||
// In this section you can specify if Player LEDs will be active, and, if active, which pins will be used for them.
|
||||
// The defualt is `PLED_TYPE_NONE` which will turn the Player LEDs off.
|
||||
// The default pin for each Player LED is `-1` which disables it.
|
||||
// To enable a `PLED#_PIN`, replace the `-1` with the GPIO pin number that is desired.
|
||||
// There are three options for `PLED_TYPE` currently:
|
||||
// 1 - `PLED_TYPE_NONE` - This will disable the Player LEDs
|
||||
// 2 - `PLED_TYPE_PWM` - This will enable the Player LEDs ( it is recommended to run through 3V3(OUT) with a resistor)
|
||||
// 3 - `PLED_TYPE_RGB` - This will enable the Player LEDs as addressible RGB LEDs (please not that this has not been implemented yet)
|
||||
|
||||
#define PLED_TYPE PLED_TYPE_NONE
|
||||
#define PLED1_PIN -1
|
||||
#define PLED2_PIN -1
|
||||
#define PLED3_PIN -1
|
||||
#define PLED4_PIN -1
|
||||
|
||||
|
||||
// This is the Analog section.
|
||||
// In this section you can specify if Analog is enabled, and, if endabled, which pins will be used for it.
|
||||
// The default for `ANALOG_ADC_VRX` and `ANALOG_ADC_VRY` is `-1` which disables them.
|
||||
// To enable a `ANALOG_ADC_VRX` and `ANALOG_ADC_VRY`, replace the `-1` with the GPIO pin numbers that are desired.
|
||||
|
||||
#define ANALOG_ADC_VRX -1
|
||||
#define ANALOG_ADC_VRY -1
|
||||
|
||||
// Reverse Button section
|
||||
#define REVERSE_LED_PIN -1
|
||||
|
||||
// This is the I2C Display section (commonly known as the OLED display section).
|
||||
// In this section you can specify if a display as been enabled, which pins are assined to it, the block address and speed.
|
||||
// The default for `HAS_I2C_DISPLAY` is `1` which enables it.
|
||||
// To disable the display you can change `HAS_I2C_DISPLAY` to `-1`.
|
||||
// The default `I2C_SDA_PIN` is `0`.
|
||||
// The defualt `I2C_SCL_PIN` is `1`.
|
||||
// The defualt `I2C_BLOCK` is `12c0`.
|
||||
// If you change the `I2C_SDA_PIN` and `I2C_SCL_PIN` pin mapping, you may need to change the `I2C_BLOCK` as well.
|
||||
// The defualt `I2C_SPEED` is `400000`.
|
||||
// This should be more than fast enough for most displays.
|
||||
// Some smaller displays (like 0.96" and 1.31") can go up to `800000` or even `1000000`.
|
||||
// The default `DISPLAY_FLIP` is `0`.
|
||||
// This can be changed to `1` to have the dispaly output flipped.
|
||||
// The default `DISPLAY_INVERY` is `0`.
|
||||
// This can be changed to `1` to have the color on the display inverted.
|
||||
// The default `BUTTON_LAYOUT` is `BUTTON_LAYOUT_STICK` which will show an arcade stick on the left hand side of the display.
|
||||
// There are seven options for `BUTTON_LAYOUT` currently:
|
||||
// 1 - BUTTON_LAYOUT_STICK - This is a basic joystick layout
|
||||
// 2 - BUTTON_LAYOUT_STICKLESS - This is a basic stickless (all button) layout
|
||||
// 3 - BUTTON_LAYOUT_BUTTONS_ANGLED - This a WASD button layout that is angled
|
||||
// 4 - BUTTON_LAYOUT_BUTTONS_BASIC - This a WASD button layout that is straight
|
||||
// 5 - BUTTON_LAYOUT_KEYBOARD_ANGLED - This is a WASD keyboard layout that is angled
|
||||
// 6 - BUTTON_LAYOUT_KEYBOARDA - This is a WASD keyboard layout that is straight
|
||||
// 7 - BUTTON_LAYOUT_DANCEPADA - This is a dance pad layout (must be used with `BUTTON_LAYOUT_DANCEPADB` in `BUTTON_LAYOUT_RIGHT`)
|
||||
// The default `BUTTON_LAYOUT_RIGHT` is `BUTTON_LAYOUT_NOIR8` which will show eight buttons on the right hand side of the display.
|
||||
// There are eleven options for `BUTTON_LAYOUT_RIGHT` currently:
|
||||
// 1 - BUTTON_LAYOUT_ARCADE - This is a standard 8 button arcade layout
|
||||
// 2 - BUTTON_LAYOUT_STICKLESSB - This is a basic stickless (all button) layout
|
||||
// 3 - BUTTON_LAYOUT_BUTTONS_ANGLEDB - This is a standard 8 button arcade layout that is angled
|
||||
// 4 - BUTTON_LAYOUT_VEWLIX - This is the standard 8 button Vewlix layout
|
||||
// 5 - BUTTON_LAYOUT_VEWLIX7 - This is the standard 7 button Vewlix layout
|
||||
// 6 - BUTTON_LAYOUT_CAPCOM - This is the standard 8 button Capcom layout
|
||||
// 7 - BUTTON_LAYOUT_CAPCOM6 - This is the stndard 6 button Capcom layout
|
||||
// 8 - BUTTON_LAYOUT_SEGA2P - This is the standard 8 button Sega2P layout
|
||||
// 9 - BUTTON_LAYOUT_NOIR8 - This is the standard 8 button Noir layout
|
||||
// 10 - BUTTON_LAYOUT_KEYBOARDB - This is a WASD keyboard layout that is straight
|
||||
// 11 - BUTTON_LAYOUT_DANCEPADB - This is a dance pad layout (must be used with `BUTTON_LAYOUT_DANCEPADA` in `BUTTON_LAYOUT`)
|
||||
// The default `SPLASH_MODE` is `NOSPLASH`.
|
||||
// There are four options for `SPLASH_MODE` currently:
|
||||
// 1 - `STATICSPLASH` - This will display the static splash image
|
||||
// 2 - `CLOSEIN` - This will display the static splash image as a top and bottom coming together animation
|
||||
// 3 - `CLOSEINCUSTOM` - This will display the custom splash image as a top and bottom coming together animation
|
||||
// 4 - `NOSPLASH` - This will not display a splash screen on boot
|
||||
// Special note - All of the splash screen images can be changed via `include/bitmaps.h`
|
||||
|
||||
#define HAS_I2C_DISPLAY -1
|
||||
#define I2C_SDA_PIN 0
|
||||
#define I2C_SCL_PIN 1
|
||||
#define I2C_BLOCK i2c0
|
||||
#define I2C_SPEED 400000
|
||||
#define DISPLAY_FLIP 0
|
||||
#define DISPLAY_INVERT 0
|
||||
|
||||
#define REVERSE_UP_DEFAULT 1
|
||||
#define REVERSE_DOWN_DEFAULT 1
|
||||
#define REVERSE_LEFT_DEFAULT 1
|
||||
#define REVERSE_RIGHT_DEFAULT 1
|
||||
|
||||
#define BUTTON_LAYOUT BUTTON_LAYOUT_STICK
|
||||
#define BUTTON_LAYOUT_RIGHT BUTTON_LAYOUT_VEWLIX
|
||||
#define SPLASH_MODE SPLASH_MODE_NONE
|
||||
#define SPLASH_CHOICE SPLASH_CHOICE_MAIN
|
||||
#define SPLASH_DURATION 7500 // Duration in milliseconds
|
||||
|
||||
// Board LED Add-on Setting
|
||||
// BOARD_LED_OFF - Turns the on-board LED off
|
||||
// MODE_INDICATOR - On-board LED blinks on various frequencies depending
|
||||
// on the current mode (config, normal, or no USB data)
|
||||
// INPUT_TEST - Blinks whenever any input is made
|
||||
|
||||
#define BOARD_LED_TYPE ON_BOARD_LED_MODE_OFF
|
||||
|
||||
// Dual Directional Add-on Options
|
||||
|
||||
#define PIN_DUAL_DIRECTIONAL_UP -1
|
||||
#define PIN_DUAL_DIRECTIONAL_DOWN -1
|
||||
#define PIN_DUAL_DIRECTIONAL_LEFT -1
|
||||
#define PIN_DUAL_DIRECTIONAL_RIGHT -1
|
||||
#define DUAL_DIRECTIONAL_STICK_MODE DPAD_MODE_DIGITAL
|
||||
#define DUAL_DIRECTIONAL_COMBINE_MODE DUAL_COMBINE_MODE_MIXED
|
||||
|
||||
// BOOTSEL Button Add-on setting
|
||||
#define BOOTSEL_BUTTON_MASK 0 // 0 means none, get other mask from GamepadState.h
|
||||
|
||||
// Extra Button Add-on setting
|
||||
#define EXTRA_BUTTON_MASK 0 // 0 means none, get other mask from GamepadState.h
|
||||
// For directions, use GAMEPAD_MASK_DU, GAMEPAD_MASK_DD, GAMEPAD_MASK_DL and GAMEPAD_MASK_DR
|
||||
#define EXTRA_BUTTON_PIN -1
|
||||
|
||||
// Keyboard Mapping Configuration
|
||||
// List of HID keycodes can be located here: https://github.com/hathach/tinyusb/blob/3623ba1884ddff23e9b64766cb6dd032f1425846/src/class/hid/hid.h#L356
|
||||
// Even for the modifier keys, HID_KEY entries should be used as the implementation expects those and will convert as necessary.
|
||||
#define KEY_DPAD_UP HID_KEY_ARROW_UP // UP
|
||||
#define KEY_DPAD_DOWN HID_KEY_ARROW_DOWN // DOWN
|
||||
#define KEY_DPAD_LEFT HID_KEY_ARROW_LEFT // LEFT
|
||||
#define KEY_DPAD_RIGHT HID_KEY_ARROW_RIGHT // RIGHT
|
||||
#define KEY_BUTTON_B1 HID_KEY_SHIFT_LEFT // B1 / A / B / Cross / 2 / K1
|
||||
#define KEY_BUTTON_B2 HID_KEY_Z // B2 / B / A / Circle / 3 / K2
|
||||
#define KEY_BUTTON_B3 HID_KEY_CONTROL_LEFT // B3 / X / Y / Square / 1 / P1
|
||||
#define KEY_BUTTON_B4 HID_KEY_ALT_LEFT // B4 / Y / X / Triangle / 4 / P2
|
||||
#define KEY_BUTTON_L1 HID_KEY_C // L1 / LB / L / L1 / 5 / P4
|
||||
#define KEY_BUTTON_R1 HID_KEY_SPACE // R1 / RB / R / R1 / 6 / P3
|
||||
#define KEY_BUTTON_L2 HID_KEY_V // L2 / LT / ZL / L2 / 7 / K4
|
||||
#define KEY_BUTTON_R2 HID_KEY_X // R2 / RT / ZR / R2 / 8 / K3
|
||||
#define KEY_BUTTON_S1 HID_KEY_5 // S1 / Back / Minus / Select / 9 / Coin
|
||||
#define KEY_BUTTON_S2 HID_KEY_1 // S2 / Start / Plus / Start / 10 / Start
|
||||
#define KEY_BUTTON_L3 HID_KEY_EQUAL // L3 / LS / LS / L3 / 11 / LS
|
||||
#define KEY_BUTTON_R3 HID_KEY_MINUS // R3 / RS / RS / R3 / 12 / RS
|
||||
#define KEY_BUTTON_A1 HID_KEY_9 // A1 / Guide / Home / PS / 13 / ~
|
||||
#define KEY_BUTTON_A2 HID_KEY_F2 // A2 / ~ / Capture / ~ / 14 / ~
|
||||
|
||||
// Hotkey Action Mapping
|
||||
// Find the list of hotkey actions in GamepadEnums.h
|
||||
#define HOTKEY_F1_UP_MASK GAMEPAD_MASK_UP
|
||||
#define HOTKEY_F1_UP_ACTION HOTKEY_HOME_BUTTON
|
||||
#define HOTKEY_F1_DOWN_MASK GAMEPAD_MASK_DOWN
|
||||
#define HOTKEY_F1_DOWN_ACTION HOTKEY_DPAD_DIGITAL
|
||||
#define HOTKEY_F1_LEFT_MASK GAMEPAD_MASK_LEFT
|
||||
#define HOTKEY_F1_LEFT_ACTION HOTKEY_DPAD_LEFT_ANALOG
|
||||
#define HOTKEY_F1_RIGHT_MASK GAMEPAD_MASK_RIGHT
|
||||
#define HOTKEY_F1_RIGHT_ACTION HOTKEY_DPAD_RIGHT_ANALOG
|
||||
|
||||
#define HOTKEY_F2_UP_MASK GAMEPAD_MASK_UP
|
||||
#define HOTKEY_F2_UP_ACTION HOTKEY_SOCD_UP_PRIORITY
|
||||
#define HOTKEY_F2_DOWN_MASK GAMEPAD_MASK_DOWN
|
||||
#define HOTKEY_F2_DOWN_ACTION HOTKEY_SOCD_NEUTRAL
|
||||
#define HOTKEY_F2_LEFT_MASK GAMEPAD_MASK_LEFT
|
||||
#define HOTKEY_F2_LEFT_ACTION HOTKEY_SOCD_LAST_INPUT
|
||||
#define HOTKEY_F2_RIGHT_MASK GAMEPAD_MASK_RIGHT
|
||||
#define HOTKEY_F2_RIGHT_ACTION HOTKEY_INVERT_Y_AXIS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GP2040 Configuration for the Stress Fightpad
|
||||
|
||||

|
||||
|
||||
Configuration for the [Stress Fightpad](https://github.com/GroooveBob/Stress). Configuration uses the same pinout as the Waveshare RP2040 Zero.
|
||||
|
||||
# GP2040 Configuration for the Stress Fightpad
|
||||
|
||||

|
||||
|
||||
Configuration for the [Stress Fightpad](https://github.com/GroooveBob/Stress). Configuration uses the same pinout as the Waveshare RP2040 Zero.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[env:Stress]
|
||||
upload_port = .pio/build/Stress/
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-I configs/Stress/
|
||||
[env:Stress]
|
||||
upload_port = .pio/build/Stress/
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-I configs/Stress/
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------
|
||||
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||
// -----------------------------------------------------
|
||||
|
||||
|
||||
#ifndef _BOARDS_STRESS_H
|
||||
#define _BOARDS_STRESS_H
|
||||
|
||||
// For board detection
|
||||
#define STRESS
|
||||
|
||||
//For crappy crystal
|
||||
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
|
||||
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
|
||||
#endif
|
||||
|
||||
// --- UART ---
|
||||
#ifndef PICO_DEFAULT_UART
|
||||
#define PICO_DEFAULT_UART 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||
#endif
|
||||
|
||||
// --- LED ---
|
||||
#ifndef PICO_DEFAULT_LED_PIN
|
||||
#define PICO_DEFAULT_LED_PIN 25
|
||||
#endif
|
||||
// no PICO_DEFAULT_WS2812_PIN
|
||||
|
||||
// --- I2C ---
|
||||
#ifndef PICO_DEFAULT_I2C
|
||||
#define PICO_DEFAULT_I2C 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||
#define PICO_DEFAULT_I2C_SDA_PIN 4
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
||||
#endif
|
||||
|
||||
// --- SPI ---
|
||||
#ifndef PICO_DEFAULT_SPI
|
||||
#define PICO_DEFAULT_SPI 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||
#define PICO_DEFAULT_SPI_SCK_PIN 18
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||
#define PICO_DEFAULT_SPI_TX_PIN 19
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||
#define PICO_DEFAULT_SPI_RX_PIN 16
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||
#define PICO_DEFAULT_SPI_CSN_PIN 17
|
||||
#endif
|
||||
|
||||
// --- FLASH ---
|
||||
|
||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||
|
||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||
#define PICO_FLASH_SPI_CLKDIV 2
|
||||
#endif
|
||||
|
||||
#ifndef PICO_FLASH_SIZE_BYTES
|
||||
#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
|
||||
#define PICO_SMPS_MODE_PIN 23
|
||||
|
||||
#ifndef PICO_RP2040_B0_SUPPORTED
|
||||
#define PICO_RP2040_B0_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------
|
||||
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||
// -----------------------------------------------------
|
||||
|
||||
|
||||
#ifndef _BOARDS_STRESS_H
|
||||
#define _BOARDS_STRESS_H
|
||||
|
||||
// For board detection
|
||||
#define STRESS
|
||||
|
||||
//For crappy crystal
|
||||
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
|
||||
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
|
||||
#endif
|
||||
|
||||
// --- UART ---
|
||||
#ifndef PICO_DEFAULT_UART
|
||||
#define PICO_DEFAULT_UART 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||
#endif
|
||||
|
||||
// --- LED ---
|
||||
#ifndef PICO_DEFAULT_LED_PIN
|
||||
#define PICO_DEFAULT_LED_PIN 25
|
||||
#endif
|
||||
// no PICO_DEFAULT_WS2812_PIN
|
||||
|
||||
// --- I2C ---
|
||||
#ifndef PICO_DEFAULT_I2C
|
||||
#define PICO_DEFAULT_I2C 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||
#define PICO_DEFAULT_I2C_SDA_PIN 4
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
||||
#endif
|
||||
|
||||
// --- SPI ---
|
||||
#ifndef PICO_DEFAULT_SPI
|
||||
#define PICO_DEFAULT_SPI 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||
#define PICO_DEFAULT_SPI_SCK_PIN 18
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||
#define PICO_DEFAULT_SPI_TX_PIN 19
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||
#define PICO_DEFAULT_SPI_RX_PIN 16
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||
#define PICO_DEFAULT_SPI_CSN_PIN 17
|
||||
#endif
|
||||
|
||||
// --- FLASH ---
|
||||
|
||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||
|
||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||
#define PICO_FLASH_SPI_CLKDIV 2
|
||||
#endif
|
||||
|
||||
#ifndef PICO_FLASH_SIZE_BYTES
|
||||
#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
|
||||
#define PICO_SMPS_MODE_PIN 23
|
||||
|
||||
#ifndef PICO_RP2040_B0_SUPPORTED
|
||||
#define PICO_RP2040_B0_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
#ifndef PS4MODE_H_
|
||||
#define PS4MODE_H_
|
||||
|
||||
#include "gpaddon.h"
|
||||
#include "storagemanager.h"
|
||||
|
||||
#include "mbedtls/rsa.h"
|
||||
|
||||
#ifndef PS4MODE_ADDON_ENABLED
|
||||
#define PS4MODE_ADDON_ENABLED 0
|
||||
#endif
|
||||
|
||||
// Turbo Module Name
|
||||
#define PS4ModeName "PS4Mode"
|
||||
|
||||
class PS4ModeAddon : public GPAddon {
|
||||
public:
|
||||
virtual bool available();
|
||||
virtual void setup(); // TURBO Button Setup
|
||||
virtual void preprocess() {}
|
||||
virtual void process(); // TURBO Setting of buttons (Enable/Disable)
|
||||
virtual std::string name() { return PS4ModeName; }
|
||||
private:
|
||||
struct mbedtls_rsa_context rsa_context;
|
||||
mbedtls_mpi_uint bytesN[64] = {};
|
||||
mbedtls_mpi_uint bytesE[1] = {};
|
||||
mbedtls_mpi_uint bytesD[64] = {};
|
||||
mbedtls_mpi_uint bytesP[32] = {};
|
||||
mbedtls_mpi_uint bytesQ[32] = {};
|
||||
mbedtls_mpi_uint bytesDP[32] = {};
|
||||
mbedtls_mpi_uint bytesDQ[32] = {};
|
||||
mbedtls_mpi_uint bytesQP[32] = {};
|
||||
mbedtls_mpi_uint bytesRN[64] = {};
|
||||
uint8_t hashed_nonce[32] = {};
|
||||
};
|
||||
|
||||
#endif // PS4MODE_H_
|
||||
#ifndef PS4MODE_H_
|
||||
#define PS4MODE_H_
|
||||
|
||||
#include "gpaddon.h"
|
||||
#include "storagemanager.h"
|
||||
|
||||
#include "mbedtls/rsa.h"
|
||||
|
||||
#ifndef PS4MODE_ADDON_ENABLED
|
||||
#define PS4MODE_ADDON_ENABLED 0
|
||||
#endif
|
||||
|
||||
// Turbo Module Name
|
||||
#define PS4ModeName "PS4Mode"
|
||||
|
||||
class PS4ModeAddon : public GPAddon {
|
||||
public:
|
||||
virtual bool available();
|
||||
virtual void setup(); // TURBO Button Setup
|
||||
virtual void preprocess() {}
|
||||
virtual void process(); // TURBO Setting of buttons (Enable/Disable)
|
||||
virtual std::string name() { return PS4ModeName; }
|
||||
private:
|
||||
struct mbedtls_rsa_context rsa_context;
|
||||
mbedtls_mpi_uint bytesN[64] = {};
|
||||
mbedtls_mpi_uint bytesE[1] = {};
|
||||
mbedtls_mpi_uint bytesD[64] = {};
|
||||
mbedtls_mpi_uint bytesP[32] = {};
|
||||
mbedtls_mpi_uint bytesQ[32] = {};
|
||||
mbedtls_mpi_uint bytesDP[32] = {};
|
||||
mbedtls_mpi_uint bytesDQ[32] = {};
|
||||
mbedtls_mpi_uint bytesQP[32] = {};
|
||||
mbedtls_mpi_uint bytesRN[64] = {};
|
||||
uint8_t hashed_nonce[32] = {};
|
||||
};
|
||||
|
||||
#endif // PS4MODE_H_
|
||||
|
||||
@@ -1,135 +1,135 @@
|
||||
#ifndef _BASE64_H_
|
||||
#define _BASE64_H_
|
||||
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2016 tomykaira
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
class Base64 {
|
||||
public:
|
||||
|
||||
static std::string Encode(const char* dataPtr, size_t dataLen) {
|
||||
static constexpr char sEncodingTable[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
size_t out_len = 4 * ((dataLen + 2) / 3);
|
||||
std::string ret;
|
||||
ret.resize(out_len);
|
||||
|
||||
size_t i = 0;
|
||||
char *p = ret.data();
|
||||
|
||||
if (dataLen >= 2) {
|
||||
for (; i < dataLen - 2; i += 3) {
|
||||
*p++ = sEncodingTable[(dataPtr[i] >> 2) & 0x3F];
|
||||
*p++ = sEncodingTable[((dataPtr[i] & 0x3) << 4) | ((int) (dataPtr[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = sEncodingTable[((dataPtr[i + 1] & 0xF) << 2) | ((int) (dataPtr[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = sEncodingTable[dataPtr[i + 2] & 0x3F];
|
||||
}
|
||||
}
|
||||
|
||||
if (i < dataLen) {
|
||||
*p++ = sEncodingTable[(dataPtr[i] >> 2) & 0x3F];
|
||||
if (i == (dataLen - 1)) {
|
||||
*p++ = sEncodingTable[((dataPtr[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
}
|
||||
else {
|
||||
*p++ = sEncodingTable[((dataPtr[i] & 0x3) << 4) | ((int) (dataPtr[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = sEncodingTable[((dataPtr[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string Encode(const std::string data) {
|
||||
return Encode(data.data(), data.length());
|
||||
}
|
||||
|
||||
static bool Decode(const char* dataPtr, size_t dataLen, std::string& out) {
|
||||
static constexpr unsigned char kDecodingTable[] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
if (dataLen % 4 != 0)
|
||||
{
|
||||
out.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t out_len = dataLen / 4 * 3;
|
||||
if (dataLen >= 1 && dataPtr[dataLen - 1] == '=') out_len--;
|
||||
if (dataLen >= 2 && dataPtr[dataLen - 2] == '=') out_len--;
|
||||
|
||||
out.resize(out_len);
|
||||
|
||||
for (size_t i = 0, j = 0; i < dataLen;) {
|
||||
uint32_t a = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
uint32_t b = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
uint32_t c = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
uint32_t d = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
|
||||
uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
|
||||
|
||||
if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF;
|
||||
if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF;
|
||||
if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Decode(const std::string& input, std::string& out) {
|
||||
return Decode(input.data(), input.length(), out);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#ifndef _BASE64_H_
|
||||
#define _BASE64_H_
|
||||
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2016 tomykaira
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
class Base64 {
|
||||
public:
|
||||
|
||||
static std::string Encode(const char* dataPtr, size_t dataLen) {
|
||||
static constexpr char sEncodingTable[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
size_t out_len = 4 * ((dataLen + 2) / 3);
|
||||
std::string ret;
|
||||
ret.resize(out_len);
|
||||
|
||||
size_t i = 0;
|
||||
char *p = ret.data();
|
||||
|
||||
if (dataLen >= 2) {
|
||||
for (; i < dataLen - 2; i += 3) {
|
||||
*p++ = sEncodingTable[(dataPtr[i] >> 2) & 0x3F];
|
||||
*p++ = sEncodingTable[((dataPtr[i] & 0x3) << 4) | ((int) (dataPtr[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = sEncodingTable[((dataPtr[i + 1] & 0xF) << 2) | ((int) (dataPtr[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = sEncodingTable[dataPtr[i + 2] & 0x3F];
|
||||
}
|
||||
}
|
||||
|
||||
if (i < dataLen) {
|
||||
*p++ = sEncodingTable[(dataPtr[i] >> 2) & 0x3F];
|
||||
if (i == (dataLen - 1)) {
|
||||
*p++ = sEncodingTable[((dataPtr[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
}
|
||||
else {
|
||||
*p++ = sEncodingTable[((dataPtr[i] & 0x3) << 4) | ((int) (dataPtr[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = sEncodingTable[((dataPtr[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string Encode(const std::string data) {
|
||||
return Encode(data.data(), data.length());
|
||||
}
|
||||
|
||||
static bool Decode(const char* dataPtr, size_t dataLen, std::string& out) {
|
||||
static constexpr unsigned char kDecodingTable[] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
if (dataLen % 4 != 0)
|
||||
{
|
||||
out.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t out_len = dataLen / 4 * 3;
|
||||
if (dataLen >= 1 && dataPtr[dataLen - 1] == '=') out_len--;
|
||||
if (dataLen >= 2 && dataPtr[dataLen - 2] == '=') out_len--;
|
||||
|
||||
out.resize(out_len);
|
||||
|
||||
for (size_t i = 0, j = 0; i < dataLen;) {
|
||||
uint32_t a = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
uint32_t b = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
uint32_t c = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
uint32_t d = dataPtr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(dataPtr[i++])];
|
||||
|
||||
uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
|
||||
|
||||
if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF;
|
||||
if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF;
|
||||
if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Decode(const std::string& input, std::string& out) {
|
||||
return Decode(input.data(), input.length(), out);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* _BASE64_H_ */
|
||||
@@ -1,305 +1,305 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define HID_ENDPOINT_SIZE 64
|
||||
|
||||
// Mayflash
|
||||
//#define PS4_VENDOR_ID 0x33df
|
||||
//#define PS4_PRODUCT_ID 0x0011
|
||||
|
||||
// Razer Panthera
|
||||
#define PS4_VENDOR_ID 0x1532
|
||||
#define PS4_PRODUCT_ID 0x0401
|
||||
|
||||
// Madcatz Fightstick Alpha PS4
|
||||
//#define PS4_VENDOR_ID 0x0738
|
||||
//#define PS4_PRODUCT_ID 0x8180
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Endpoint Buffer Configuration
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define ENDPOINT0_SIZE 64
|
||||
|
||||
#define GAMEPAD_INTERFACE 0
|
||||
#define GAMEPAD_ENDPOINT 1
|
||||
#define GAMEPAD_SIZE 64
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
// HAT report (4 bits)
|
||||
#define HID_HAT_UP 0x00
|
||||
#define HID_HAT_UPRIGHT 0x01
|
||||
#define HID_HAT_RIGHT 0x02
|
||||
#define HID_HAT_DOWNRIGHT 0x03
|
||||
#define HID_HAT_DOWN 0x04
|
||||
#define HID_HAT_DOWNLEFT 0x05
|
||||
#define HID_HAT_LEFT 0x06
|
||||
#define HID_HAT_UPLEFT 0x07
|
||||
#define HID_HAT_NOTHING 0x08
|
||||
|
||||
#define PS4_HAT_NOTHING 0x0F
|
||||
|
||||
// Button report (16 bits)
|
||||
#define HID_MASK_SQUARE (1U << 0)
|
||||
#define HID_MASK_CROSS (1U << 1)
|
||||
#define HID_MASK_CIRCLE (1U << 2)
|
||||
#define HID_MASK_TRIANGLE (1U << 3)
|
||||
#define HID_MASK_L1 (1U << 4)
|
||||
#define HID_MASK_R1 (1U << 5)
|
||||
#define HID_MASK_L2 (1U << 6)
|
||||
#define HID_MASK_R2 (1U << 7)
|
||||
#define HID_MASK_SELECT (1U << 8)
|
||||
#define HID_MASK_START (1U << 9)
|
||||
#define HID_MASK_L3 (1U << 10)
|
||||
#define HID_MASK_R3 (1U << 11)
|
||||
#define HID_MASK_PS (1U << 12)
|
||||
#define HID_MASK_TP (1U << 13)
|
||||
|
||||
// Switch analog sticks only report 8 bits
|
||||
#define HID_JOYSTICK_MIN 0x00
|
||||
#define HID_JOYSTICK_MID 0x80
|
||||
#define HID_JOYSTICK_MAX 0xFF
|
||||
|
||||
struct TouchpadXY {
|
||||
uint8_t counter : 7;
|
||||
uint8_t unpressed : 1;
|
||||
|
||||
// 12 bit X, followed by 12 bit Y
|
||||
uint8_t data[3];
|
||||
|
||||
void set_x(uint16_t x) {
|
||||
data[0] = x & 0xff;
|
||||
data[1] = (data[1] & 0xf0) | ((x >> 8) & 0xf);
|
||||
}
|
||||
|
||||
void set_y(uint16_t y) {
|
||||
data[1] = (data[1] & 0x0f) | ((y & 0xf) << 4);
|
||||
data[2] = y >> 4;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
struct TouchpadData {
|
||||
TouchpadXY p1;
|
||||
TouchpadXY p2;
|
||||
};
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t report_id;
|
||||
uint8_t left_stick_x;
|
||||
uint8_t left_stick_y;
|
||||
uint8_t right_stick_x;
|
||||
uint8_t right_stick_y;
|
||||
|
||||
// 4 bits for the d-pad.
|
||||
uint32_t dpad : 4;
|
||||
|
||||
// 14 bits for buttons.
|
||||
uint32_t button_west : 1;
|
||||
uint32_t button_south : 1;
|
||||
uint32_t button_east : 1;
|
||||
uint32_t button_north : 1;
|
||||
uint32_t button_l1 : 1;
|
||||
uint32_t button_r1 : 1;
|
||||
uint32_t button_l2 : 1;
|
||||
uint32_t button_r2 : 1;
|
||||
uint32_t button_select : 1;
|
||||
uint32_t button_start : 1;
|
||||
uint32_t button_l3 : 1;
|
||||
uint32_t button_r3 : 1;
|
||||
uint32_t button_home : 1;
|
||||
uint32_t button_touchpad : 1;
|
||||
|
||||
// 6 bit report counter.
|
||||
uint32_t report_counter : 6;
|
||||
|
||||
uint32_t left_trigger : 8;
|
||||
uint32_t right_trigger : 8;
|
||||
|
||||
uint32_t padding : 24;
|
||||
uint8_t mystery[22];
|
||||
TouchpadData touchpad_data;
|
||||
uint8_t mystery_2[21];
|
||||
} PS4Report;
|
||||
|
||||
static const uint8_t ps4_string_language[] = { 0x09, 0x04 };
|
||||
static const uint8_t ps4_string_manufacturer[] = "Open Stick Community";
|
||||
static const uint8_t ps4_string_product[] = "GP2040-CE (PS4)";
|
||||
static const uint8_t ps4_string_version[] = "1.0";
|
||||
|
||||
static const uint8_t *ps4_string_descriptors[] =
|
||||
{
|
||||
ps4_string_language,
|
||||
ps4_string_manufacturer,
|
||||
ps4_string_product,
|
||||
ps4_string_version
|
||||
};
|
||||
|
||||
static const uint8_t ps4_device_descriptor[] =
|
||||
{
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
0, // bDeviceClass
|
||||
0, // bDeviceSubClass
|
||||
0, // bDeviceProtocol
|
||||
ENDPOINT0_SIZE, // bMaxPacketSize0
|
||||
LSB(PS4_VENDOR_ID), MSB(PS4_VENDOR_ID), // idVendor
|
||||
LSB(PS4_PRODUCT_ID), MSB(PS4_PRODUCT_ID), // idProduct
|
||||
0x00, 0x01, // bcdDevice
|
||||
1, // iManufacturer
|
||||
2, // iProduct
|
||||
0, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
|
||||
static const uint8_t ps4_report_descriptor[] =
|
||||
{
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, // Usage (Game Pad)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x85, 0x01, // Report ID (1)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x07, // Logical Maximum (7)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
||||
|
||||
0x65, 0x00, // Unit (None)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x0E, // Usage Maximum (0x0E)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x0E, // Report Count (14)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x75, 0x06, // Report Size (6)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x33, // Usage (Rx)
|
||||
0x09, 0x34, // Usage (Ry)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x95, 0x36, // Report Count (54)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x85, 0x05, // Report ID (5)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x95, 0x1F, // Report Count (31)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
|
||||
0x85, 0x03, // Report ID (3)
|
||||
0x0A, 0x21, 0x27, // Usage (0x2721)
|
||||
0x95, 0x2F, // Report Count (47)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
|
||||
0x06, 0xF0, 0xFF, // Usage Page (Vendor Defined 0xFFF0)
|
||||
0x09, 0x40, // Usage (0x40)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x85, 0xF0, // Report ID (-16) AUTH F0
|
||||
0x09, 0x47, // Usage (0x47)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF1, // Report ID (-15) AUTH F1
|
||||
0x09, 0x48, // Usage (0x48)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF2, // Report ID (-14) AUTH F2
|
||||
0x09, 0x49, // Usage (0x49)
|
||||
0x95, 0x0F, // Report Count (15)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF3, // Report ID (-13) Auth F3 (Reset)
|
||||
0x0A, 0x01, 0x47, // Usage (0x4701)
|
||||
0x95, 0x07, // Report Count (7)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
static const uint8_t ps4_hid_descriptor[] =
|
||||
{
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x11, 0x01, // bcdHID 1.11
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
sizeof(ps4_report_descriptor), 0x00, // wDescriptorLength[0] 90
|
||||
};
|
||||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
||||
static const uint8_t ps4_configuration_descriptor[] =
|
||||
{
|
||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
|
||||
9, // bLength;
|
||||
2, // bDescriptorType;
|
||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength
|
||||
MSB(CONFIG1_DESC_SIZE),
|
||||
1, // bNumInterfaces
|
||||
1, // bConfigurationValue
|
||||
0, // iConfiguration
|
||||
0x80, // bmAttributes
|
||||
50, // bMaxPower
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
9, // bLength
|
||||
4, // bDescriptorType
|
||||
GAMEPAD_INTERFACE, // bInterfaceNumber
|
||||
0, // bAlternateSetting
|
||||
1, // bNumEndpoints
|
||||
0x03, // bInterfaceClass (0x03 = HID)
|
||||
0x00, // bInterfaceSubClass (0x00 = No Boot)
|
||||
0x00, // bInterfaceProtocol (0x00 = No Protocol)
|
||||
0, // iInterface
|
||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1
|
||||
9, // bLength
|
||||
0x21, // bDescriptorType
|
||||
0x11, 0x01, // bcdHID
|
||||
0, // bCountryCode
|
||||
1, // bNumDescriptors
|
||||
0x22, // bDescriptorType
|
||||
sizeof(ps4_report_descriptor), // wDescriptorLength
|
||||
0,
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
GAMEPAD_ENDPOINT | 0x80, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
GAMEPAD_SIZE, 0, // wMaxPacketSize
|
||||
1 // bInterval (1 ms)
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define HID_ENDPOINT_SIZE 64
|
||||
|
||||
// Mayflash
|
||||
//#define PS4_VENDOR_ID 0x33df
|
||||
//#define PS4_PRODUCT_ID 0x0011
|
||||
|
||||
// Razer Panthera
|
||||
#define PS4_VENDOR_ID 0x1532
|
||||
#define PS4_PRODUCT_ID 0x0401
|
||||
|
||||
// Madcatz Fightstick Alpha PS4
|
||||
//#define PS4_VENDOR_ID 0x0738
|
||||
//#define PS4_PRODUCT_ID 0x8180
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Endpoint Buffer Configuration
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define ENDPOINT0_SIZE 64
|
||||
|
||||
#define GAMEPAD_INTERFACE 0
|
||||
#define GAMEPAD_ENDPOINT 1
|
||||
#define GAMEPAD_SIZE 64
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
// HAT report (4 bits)
|
||||
#define HID_HAT_UP 0x00
|
||||
#define HID_HAT_UPRIGHT 0x01
|
||||
#define HID_HAT_RIGHT 0x02
|
||||
#define HID_HAT_DOWNRIGHT 0x03
|
||||
#define HID_HAT_DOWN 0x04
|
||||
#define HID_HAT_DOWNLEFT 0x05
|
||||
#define HID_HAT_LEFT 0x06
|
||||
#define HID_HAT_UPLEFT 0x07
|
||||
#define HID_HAT_NOTHING 0x08
|
||||
|
||||
#define PS4_HAT_NOTHING 0x0F
|
||||
|
||||
// Button report (16 bits)
|
||||
#define HID_MASK_SQUARE (1U << 0)
|
||||
#define HID_MASK_CROSS (1U << 1)
|
||||
#define HID_MASK_CIRCLE (1U << 2)
|
||||
#define HID_MASK_TRIANGLE (1U << 3)
|
||||
#define HID_MASK_L1 (1U << 4)
|
||||
#define HID_MASK_R1 (1U << 5)
|
||||
#define HID_MASK_L2 (1U << 6)
|
||||
#define HID_MASK_R2 (1U << 7)
|
||||
#define HID_MASK_SELECT (1U << 8)
|
||||
#define HID_MASK_START (1U << 9)
|
||||
#define HID_MASK_L3 (1U << 10)
|
||||
#define HID_MASK_R3 (1U << 11)
|
||||
#define HID_MASK_PS (1U << 12)
|
||||
#define HID_MASK_TP (1U << 13)
|
||||
|
||||
// Switch analog sticks only report 8 bits
|
||||
#define HID_JOYSTICK_MIN 0x00
|
||||
#define HID_JOYSTICK_MID 0x80
|
||||
#define HID_JOYSTICK_MAX 0xFF
|
||||
|
||||
struct TouchpadXY {
|
||||
uint8_t counter : 7;
|
||||
uint8_t unpressed : 1;
|
||||
|
||||
// 12 bit X, followed by 12 bit Y
|
||||
uint8_t data[3];
|
||||
|
||||
void set_x(uint16_t x) {
|
||||
data[0] = x & 0xff;
|
||||
data[1] = (data[1] & 0xf0) | ((x >> 8) & 0xf);
|
||||
}
|
||||
|
||||
void set_y(uint16_t y) {
|
||||
data[1] = (data[1] & 0x0f) | ((y & 0xf) << 4);
|
||||
data[2] = y >> 4;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
struct TouchpadData {
|
||||
TouchpadXY p1;
|
||||
TouchpadXY p2;
|
||||
};
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t report_id;
|
||||
uint8_t left_stick_x;
|
||||
uint8_t left_stick_y;
|
||||
uint8_t right_stick_x;
|
||||
uint8_t right_stick_y;
|
||||
|
||||
// 4 bits for the d-pad.
|
||||
uint32_t dpad : 4;
|
||||
|
||||
// 14 bits for buttons.
|
||||
uint32_t button_west : 1;
|
||||
uint32_t button_south : 1;
|
||||
uint32_t button_east : 1;
|
||||
uint32_t button_north : 1;
|
||||
uint32_t button_l1 : 1;
|
||||
uint32_t button_r1 : 1;
|
||||
uint32_t button_l2 : 1;
|
||||
uint32_t button_r2 : 1;
|
||||
uint32_t button_select : 1;
|
||||
uint32_t button_start : 1;
|
||||
uint32_t button_l3 : 1;
|
||||
uint32_t button_r3 : 1;
|
||||
uint32_t button_home : 1;
|
||||
uint32_t button_touchpad : 1;
|
||||
|
||||
// 6 bit report counter.
|
||||
uint32_t report_counter : 6;
|
||||
|
||||
uint32_t left_trigger : 8;
|
||||
uint32_t right_trigger : 8;
|
||||
|
||||
uint32_t padding : 24;
|
||||
uint8_t mystery[22];
|
||||
TouchpadData touchpad_data;
|
||||
uint8_t mystery_2[21];
|
||||
} PS4Report;
|
||||
|
||||
static const uint8_t ps4_string_language[] = { 0x09, 0x04 };
|
||||
static const uint8_t ps4_string_manufacturer[] = "Open Stick Community";
|
||||
static const uint8_t ps4_string_product[] = "GP2040-CE (PS4)";
|
||||
static const uint8_t ps4_string_version[] = "1.0";
|
||||
|
||||
static const uint8_t *ps4_string_descriptors[] =
|
||||
{
|
||||
ps4_string_language,
|
||||
ps4_string_manufacturer,
|
||||
ps4_string_product,
|
||||
ps4_string_version
|
||||
};
|
||||
|
||||
static const uint8_t ps4_device_descriptor[] =
|
||||
{
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
0, // bDeviceClass
|
||||
0, // bDeviceSubClass
|
||||
0, // bDeviceProtocol
|
||||
ENDPOINT0_SIZE, // bMaxPacketSize0
|
||||
LSB(PS4_VENDOR_ID), MSB(PS4_VENDOR_ID), // idVendor
|
||||
LSB(PS4_PRODUCT_ID), MSB(PS4_PRODUCT_ID), // idProduct
|
||||
0x00, 0x01, // bcdDevice
|
||||
1, // iManufacturer
|
||||
2, // iProduct
|
||||
0, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
|
||||
static const uint8_t ps4_report_descriptor[] =
|
||||
{
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, // Usage (Game Pad)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x85, 0x01, // Report ID (1)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x07, // Logical Maximum (7)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
||||
|
||||
0x65, 0x00, // Unit (None)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x0E, // Usage Maximum (0x0E)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x0E, // Report Count (14)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x75, 0x06, // Report Size (6)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x33, // Usage (Rx)
|
||||
0x09, 0x34, // Usage (Ry)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x95, 0x36, // Report Count (54)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
|
||||
0x85, 0x05, // Report ID (5)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x95, 0x1F, // Report Count (31)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
|
||||
0x85, 0x03, // Report ID (3)
|
||||
0x0A, 0x21, 0x27, // Usage (0x2721)
|
||||
0x95, 0x2F, // Report Count (47)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
|
||||
0x06, 0xF0, 0xFF, // Usage Page (Vendor Defined 0xFFF0)
|
||||
0x09, 0x40, // Usage (0x40)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x85, 0xF0, // Report ID (-16) AUTH F0
|
||||
0x09, 0x47, // Usage (0x47)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF1, // Report ID (-15) AUTH F1
|
||||
0x09, 0x48, // Usage (0x48)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF2, // Report ID (-14) AUTH F2
|
||||
0x09, 0x49, // Usage (0x49)
|
||||
0x95, 0x0F, // Report Count (15)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF3, // Report ID (-13) Auth F3 (Reset)
|
||||
0x0A, 0x01, 0x47, // Usage (0x4701)
|
||||
0x95, 0x07, // Report Count (7)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
static const uint8_t ps4_hid_descriptor[] =
|
||||
{
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x11, 0x01, // bcdHID 1.11
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
sizeof(ps4_report_descriptor), 0x00, // wDescriptorLength[0] 90
|
||||
};
|
||||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
||||
static const uint8_t ps4_configuration_descriptor[] =
|
||||
{
|
||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
|
||||
9, // bLength;
|
||||
2, // bDescriptorType;
|
||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength
|
||||
MSB(CONFIG1_DESC_SIZE),
|
||||
1, // bNumInterfaces
|
||||
1, // bConfigurationValue
|
||||
0, // iConfiguration
|
||||
0x80, // bmAttributes
|
||||
50, // bMaxPower
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
9, // bLength
|
||||
4, // bDescriptorType
|
||||
GAMEPAD_INTERFACE, // bInterfaceNumber
|
||||
0, // bAlternateSetting
|
||||
1, // bNumEndpoints
|
||||
0x03, // bInterfaceClass (0x03 = HID)
|
||||
0x00, // bInterfaceSubClass (0x00 = No Boot)
|
||||
0x00, // bInterfaceProtocol (0x00 = No Protocol)
|
||||
0, // iInterface
|
||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1
|
||||
9, // bLength
|
||||
0x21, // bDescriptorType
|
||||
0x11, 0x01, // bcdHID
|
||||
0, // bCountryCode
|
||||
1, // bNumDescriptors
|
||||
0x22, // bDescriptorType
|
||||
sizeof(ps4_report_descriptor), // wDescriptorLength
|
||||
0,
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
GAMEPAD_ENDPOINT | 0x80, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
GAMEPAD_SIZE, 0, // wMaxPacketSize
|
||||
1 // bInterval (1 ms)
|
||||
};
|
||||
@@ -1,27 +1,27 @@
|
||||
/* This can be enabled lated when we use SNTP */
|
||||
#undef MBEDTLS_HAVE_TIME_DATE
|
||||
|
||||
#define MBEDTLS_CHECK_PARAMS
|
||||
#define MBEDTLS_CHECK_PARAMS_ASSERT
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
#define MBEDTLS_CAMELLIA_SMALL_MEMORY
|
||||
#define MBEDTLS_CHECK_RETURN_WARNING
|
||||
#undef MBEDTLS_FS_IO
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_PSA_CRYPTO_CLIENT
|
||||
#define MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_SSL_ASYNC_PRIVATE
|
||||
#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
|
||||
#define MBEDTLS_USE_PSA_CRYPTO
|
||||
#undef MBEDTLS_NET_C
|
||||
#undef MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||
#undef MBEDTLS_PSA_ITS_FILE_C
|
||||
#undef MBEDTLS_TIMING_C
|
||||
/* This can be enabled lated when we use SNTP */
|
||||
#undef MBEDTLS_HAVE_TIME_DATE
|
||||
|
||||
#define MBEDTLS_CHECK_PARAMS
|
||||
#define MBEDTLS_CHECK_PARAMS_ASSERT
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
#define MBEDTLS_CAMELLIA_SMALL_MEMORY
|
||||
#define MBEDTLS_CHECK_RETURN_WARNING
|
||||
#undef MBEDTLS_FS_IO
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_PSA_CRYPTO_CLIENT
|
||||
#define MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_SSL_ASYNC_PRIVATE
|
||||
#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
|
||||
#define MBEDTLS_USE_PSA_CRYPTO
|
||||
#undef MBEDTLS_NET_C
|
||||
#undef MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||
#undef MBEDTLS_PSA_ITS_FILE_C
|
||||
#undef MBEDTLS_TIMING_C
|
||||
|
||||
@@ -1,114 +1,114 @@
|
||||
// -------------------------------------------------- //
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
|
||||
// ------ //
|
||||
// ws2812 //
|
||||
// ------ //
|
||||
|
||||
#define ws2812_wrap_target 0
|
||||
#define ws2812_wrap 3
|
||||
|
||||
#define ws2812_T1 2
|
||||
#define ws2812_T2 5
|
||||
#define ws2812_T3 3
|
||||
|
||||
static const uint16_t ws2812_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6221, // 0: out x, 1 side 0 [2]
|
||||
0x1123, // 1: jmp !x, 3 side 1 [1]
|
||||
0x1400, // 2: jmp 0 side 1 [4]
|
||||
0xa442, // 3: nop side 0 [4]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program ws2812_program = {
|
||||
.instructions = ws2812_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + ws2812_wrap_target, offset + ws2812_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
#include "hardware/clocks.h"
|
||||
static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
pio_sm_config c = ws2812_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
|
||||
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// --------------- //
|
||||
// ws2812_parallel //
|
||||
// --------------- //
|
||||
|
||||
#define ws2812_parallel_wrap_target 0
|
||||
#define ws2812_parallel_wrap 3
|
||||
|
||||
#define ws2812_parallel_T1 2
|
||||
#define ws2812_parallel_T2 5
|
||||
#define ws2812_parallel_T3 3
|
||||
|
||||
static const uint16_t ws2812_parallel_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6020, // 0: out x, 32
|
||||
0xa10b, // 1: mov pins, !null [1]
|
||||
0xa401, // 2: mov pins, x [4]
|
||||
0xa103, // 3: mov pins, null [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program ws2812_parallel_program = {
|
||||
.instructions = ws2812_parallel_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config ws2812_parallel_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + ws2812_parallel_wrap_target, offset + ws2812_parallel_wrap);
|
||||
return c;
|
||||
}
|
||||
|
||||
#include "hardware/clocks.h"
|
||||
static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) {
|
||||
for(uint i=pin_base; i<pin_base+pin_count; i++) {
|
||||
pio_gpio_init(pio, i);
|
||||
}
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin_base, pin_count, true);
|
||||
pio_sm_config c = ws2812_parallel_program_get_default_config(offset);
|
||||
sm_config_set_out_shift(&c, true, true, 32);
|
||||
sm_config_set_out_pins(&c, pin_base, pin_count);
|
||||
sm_config_set_set_pins(&c, pin_base, pin_count);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
int cycles_per_bit = ws2812_parallel_T1 + ws2812_parallel_T2 + ws2812_parallel_T3;
|
||||
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
|
||||
// ------ //
|
||||
// ws2812 //
|
||||
// ------ //
|
||||
|
||||
#define ws2812_wrap_target 0
|
||||
#define ws2812_wrap 3
|
||||
|
||||
#define ws2812_T1 2
|
||||
#define ws2812_T2 5
|
||||
#define ws2812_T3 3
|
||||
|
||||
static const uint16_t ws2812_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6221, // 0: out x, 1 side 0 [2]
|
||||
0x1123, // 1: jmp !x, 3 side 1 [1]
|
||||
0x1400, // 2: jmp 0 side 1 [4]
|
||||
0xa442, // 3: nop side 0 [4]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program ws2812_program = {
|
||||
.instructions = ws2812_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + ws2812_wrap_target, offset + ws2812_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
#include "hardware/clocks.h"
|
||||
static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
pio_sm_config c = ws2812_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
|
||||
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// --------------- //
|
||||
// ws2812_parallel //
|
||||
// --------------- //
|
||||
|
||||
#define ws2812_parallel_wrap_target 0
|
||||
#define ws2812_parallel_wrap 3
|
||||
|
||||
#define ws2812_parallel_T1 2
|
||||
#define ws2812_parallel_T2 5
|
||||
#define ws2812_parallel_T3 3
|
||||
|
||||
static const uint16_t ws2812_parallel_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x6020, // 0: out x, 32
|
||||
0xa10b, // 1: mov pins, !null [1]
|
||||
0xa401, // 2: mov pins, x [4]
|
||||
0xa103, // 3: mov pins, null [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program ws2812_parallel_program = {
|
||||
.instructions = ws2812_parallel_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config ws2812_parallel_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + ws2812_parallel_wrap_target, offset + ws2812_parallel_wrap);
|
||||
return c;
|
||||
}
|
||||
|
||||
#include "hardware/clocks.h"
|
||||
static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) {
|
||||
for(uint i=pin_base; i<pin_base+pin_count; i++) {
|
||||
pio_gpio_init(pio, i);
|
||||
}
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin_base, pin_count, true);
|
||||
pio_sm_config c = ws2812_parallel_program_get_default_config(offset);
|
||||
sm_config_set_out_shift(&c, true, true, 32);
|
||||
sm_config_set_out_pins(&c, pin_base, pin_count);
|
||||
sm_config_set_set_pins(&c, pin_base, pin_count);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
int cycles_per_bit = ws2812_parallel_T1 + ws2812_parallel_T2 + ws2812_parallel_T3;
|
||||
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,217 +1,217 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#include "ps4_driver.h"
|
||||
|
||||
#include "CRC32.h"
|
||||
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
uint8_t ps4_endpoint_in = 0;
|
||||
uint8_t ps4_endpoint_out = 0;
|
||||
uint8_t ps4_out_buffer[PS4_OUT_SIZE] = {};
|
||||
|
||||
// Alternative version
|
||||
static constexpr uint8_t output_0x03[] = {
|
||||
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,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
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 };
|
||||
|
||||
static uint8_t cur_nonce_id = 1;
|
||||
|
||||
// debug
|
||||
static int rss_error = 0;
|
||||
|
||||
static uint8_t send_nonce_part = 0;
|
||||
|
||||
struct PS4Key {
|
||||
unsigned char serial[16];
|
||||
unsigned char signature[256];
|
||||
struct mbedtls_rsa_context* rsa_context;
|
||||
};
|
||||
|
||||
struct SignaturePart {
|
||||
size_t length;
|
||||
size_t (*function)(uint8_t * buf, size_t offset, const void* arg, size_t expected_size);
|
||||
const void* arg;
|
||||
};
|
||||
|
||||
ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen)
|
||||
{
|
||||
uint8_t data[64] = {};
|
||||
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:
|
||||
if (reqlen != sizeof(output_0x03)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, output_0x03, reqlen);
|
||||
return reqlen;
|
||||
// Use our private RSA key to sign the nonce and return chunks
|
||||
case PS4AuthReport::PS4_GET_SIGNATURE_NONCE:
|
||||
// We send 56 byte chunks back to the PS4, we've already calculated these
|
||||
data[0] = 0xF1;
|
||||
data[1] = cur_nonce_id; // nonce_id
|
||||
data[2] = send_nonce_part; // next_part
|
||||
data[3] = 0;
|
||||
|
||||
// 56 byte chunks
|
||||
memcpy(&data[4], &PS4Data::getInstance().ps4_auth_buffer[send_nonce_part*56], 56);
|
||||
|
||||
// calculate the CRC32 of the buffer and write it back
|
||||
crc32 = CRC32::calculate(data, 60);
|
||||
memcpy(&data[60], &crc32, sizeof(uint32_t));
|
||||
memcpy(buf, &data[1], 63); // move data over to buffer
|
||||
if ( (++send_nonce_part) == 19 ) {
|
||||
PS4Data::getInstance().ps4State = PS4State::no_nonce;
|
||||
PS4Data::getInstance().authsent = true;
|
||||
send_nonce_part = 0;
|
||||
}
|
||||
return 63;
|
||||
// Are we ready to sign?
|
||||
case PS4AuthReport::PS4_GET_SIGNING_STATE:
|
||||
data[0] = 0xF2;
|
||||
data[1] = cur_nonce_id;
|
||||
data[2] = PS4Data::getInstance().ps4State == PS4State::signed_nonce_ready ? 0 : 16; // 0 means auth is ready, 16 means we're still signing
|
||||
memset(&data[3], 0, 9);
|
||||
crc32 = CRC32::calculate(data, 12);
|
||||
memcpy(&data[12], &crc32, sizeof(uint32_t));
|
||||
memcpy(buf, &data[1], 15); // move data over to buffer
|
||||
return 15;
|
||||
case PS4AuthReport::PS4_RESET_AUTH: // Reset the Authentication
|
||||
if (reqlen != sizeof(output_0xf3)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, output_0xf3, reqlen);
|
||||
PS4Data::getInstance().ps4State = PS4State::no_nonce;
|
||||
return reqlen;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return -1;
|
||||
}
|
||||
|
||||
void set_ps4_report(uint8_t report_id, uint8_t const * data, uint16_t reqlen)
|
||||
{
|
||||
uint8_t nonce_id;
|
||||
uint8_t nonce_page;
|
||||
uint32_t crc32;
|
||||
uint8_t buffer[64];
|
||||
uint8_t nonce[56]; // max nonce data
|
||||
uint16_t noncelen;
|
||||
uint16_t buflen;
|
||||
|
||||
if (report_id == PS4AuthReport::PS4_SET_AUTH_PAYLOAD) {
|
||||
if (reqlen != 63 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup CRC32 buffer
|
||||
buffer[0] = report_id;
|
||||
memcpy(&buffer[1], data, reqlen);
|
||||
buflen = reqlen + 1;
|
||||
|
||||
nonce_id = data[0];
|
||||
nonce_page = data[1];
|
||||
// data[2] is zero padding
|
||||
|
||||
crc32 = CRC32::calculate(buffer, buflen-sizeof(uint32_t));
|
||||
if ( crc32 != *((unsigned int*)&buffer[buflen-sizeof(uint32_t)])) {
|
||||
return; // CRC32 failed on set report
|
||||
}
|
||||
|
||||
// 256 byte nonce, with 56 byte packets leaves 24 extra bytes on the last packet?
|
||||
if ( nonce_page == 4 ) {
|
||||
// Copy/append data from buffer[4:64-28] into our nonce
|
||||
noncelen = 32; // from 4 to 64 - 24 - 4
|
||||
} else {
|
||||
// Copy/append data from buffer[4:64-4] into our nonce
|
||||
noncelen = 56;
|
||||
// from 4 to 64 - 4
|
||||
}
|
||||
|
||||
memcpy(nonce, &buffer[4], noncelen);
|
||||
save_nonce(nonce_id, nonce_page, nonce, noncelen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void save_nonce(uint8_t nonce_id, uint8_t nonce_page, uint8_t * buffer, uint16_t buflen) {
|
||||
if ( nonce_page != 0 && nonce_id != cur_nonce_id ) {
|
||||
PS4Data::getInstance().ps4State = PS4State::no_nonce;
|
||||
return; // setting nonce with mismatched id
|
||||
}
|
||||
|
||||
memcpy(&PS4Data::getInstance().nonce_buffer[nonce_page*56], buffer, buflen);
|
||||
if ( nonce_page == 4 ) {
|
||||
PS4Data::getInstance().ps4State = PS4State::nonce_ready;
|
||||
} else if ( nonce_page == 0 ) {
|
||||
cur_nonce_id = nonce_id;
|
||||
PS4Data::getInstance().ps4State = PS4State::receiving_nonce;
|
||||
}
|
||||
}
|
||||
|
||||
void receive_ps4_report(void)
|
||||
{
|
||||
if (
|
||||
tud_ready() &&
|
||||
(ps4_endpoint_out != 0) && (!usbd_edpt_busy(0, ps4_endpoint_out)))
|
||||
{
|
||||
usbd_edpt_claim(0, ps4_endpoint_out); // Take control of OUT endpoint
|
||||
usbd_edpt_xfer(0, ps4_endpoint_out, ps4_out_buffer, PS4_OUT_SIZE); // Retrieve report buffer
|
||||
usbd_edpt_release(0, ps4_endpoint_out); // Release control of OUT endpoint
|
||||
}
|
||||
}
|
||||
|
||||
bool send_ps4_report(void *report, uint8_t report_size)
|
||||
{
|
||||
bool sent = false;
|
||||
|
||||
if (
|
||||
tud_ready() && // Is the device ready?
|
||||
(ps4_endpoint_in != 0) && (!usbd_edpt_busy(0, ps4_endpoint_in)) // Is the IN endpoint available?
|
||||
)
|
||||
{
|
||||
usbd_edpt_claim(0, ps4_endpoint_in); // Take control of IN endpoint
|
||||
usbd_edpt_xfer(0, ps4_endpoint_in, (uint8_t *)report, report_size); // Send report buffer
|
||||
usbd_edpt_release(0, ps4_endpoint_in); // Release control of IN endpoint
|
||||
sent = true;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
const usbd_class_driver_t ps4_driver =
|
||||
{
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
.name = "PS4",
|
||||
#endif
|
||||
.init = hidd_init,
|
||||
.reset = hidd_reset,
|
||||
.open = hidd_open,
|
||||
.control_xfer_cb = hidd_control_xfer_cb,
|
||||
.xfer_cb = hidd_xfer_cb,
|
||||
.sof = NULL};
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#include "ps4_driver.h"
|
||||
|
||||
#include "CRC32.h"
|
||||
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
uint8_t ps4_endpoint_in = 0;
|
||||
uint8_t ps4_endpoint_out = 0;
|
||||
uint8_t ps4_out_buffer[PS4_OUT_SIZE] = {};
|
||||
|
||||
// Alternative version
|
||||
static constexpr uint8_t output_0x03[] = {
|
||||
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,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
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 };
|
||||
|
||||
static uint8_t cur_nonce_id = 1;
|
||||
|
||||
// debug
|
||||
static int rss_error = 0;
|
||||
|
||||
static uint8_t send_nonce_part = 0;
|
||||
|
||||
struct PS4Key {
|
||||
unsigned char serial[16];
|
||||
unsigned char signature[256];
|
||||
struct mbedtls_rsa_context* rsa_context;
|
||||
};
|
||||
|
||||
struct SignaturePart {
|
||||
size_t length;
|
||||
size_t (*function)(uint8_t * buf, size_t offset, const void* arg, size_t expected_size);
|
||||
const void* arg;
|
||||
};
|
||||
|
||||
ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen)
|
||||
{
|
||||
uint8_t data[64] = {};
|
||||
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:
|
||||
if (reqlen != sizeof(output_0x03)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, output_0x03, reqlen);
|
||||
return reqlen;
|
||||
// Use our private RSA key to sign the nonce and return chunks
|
||||
case PS4AuthReport::PS4_GET_SIGNATURE_NONCE:
|
||||
// We send 56 byte chunks back to the PS4, we've already calculated these
|
||||
data[0] = 0xF1;
|
||||
data[1] = cur_nonce_id; // nonce_id
|
||||
data[2] = send_nonce_part; // next_part
|
||||
data[3] = 0;
|
||||
|
||||
// 56 byte chunks
|
||||
memcpy(&data[4], &PS4Data::getInstance().ps4_auth_buffer[send_nonce_part*56], 56);
|
||||
|
||||
// calculate the CRC32 of the buffer and write it back
|
||||
crc32 = CRC32::calculate(data, 60);
|
||||
memcpy(&data[60], &crc32, sizeof(uint32_t));
|
||||
memcpy(buf, &data[1], 63); // move data over to buffer
|
||||
if ( (++send_nonce_part) == 19 ) {
|
||||
PS4Data::getInstance().ps4State = PS4State::no_nonce;
|
||||
PS4Data::getInstance().authsent = true;
|
||||
send_nonce_part = 0;
|
||||
}
|
||||
return 63;
|
||||
// Are we ready to sign?
|
||||
case PS4AuthReport::PS4_GET_SIGNING_STATE:
|
||||
data[0] = 0xF2;
|
||||
data[1] = cur_nonce_id;
|
||||
data[2] = PS4Data::getInstance().ps4State == PS4State::signed_nonce_ready ? 0 : 16; // 0 means auth is ready, 16 means we're still signing
|
||||
memset(&data[3], 0, 9);
|
||||
crc32 = CRC32::calculate(data, 12);
|
||||
memcpy(&data[12], &crc32, sizeof(uint32_t));
|
||||
memcpy(buf, &data[1], 15); // move data over to buffer
|
||||
return 15;
|
||||
case PS4AuthReport::PS4_RESET_AUTH: // Reset the Authentication
|
||||
if (reqlen != sizeof(output_0xf3)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, output_0xf3, reqlen);
|
||||
PS4Data::getInstance().ps4State = PS4State::no_nonce;
|
||||
return reqlen;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return -1;
|
||||
}
|
||||
|
||||
void set_ps4_report(uint8_t report_id, uint8_t const * data, uint16_t reqlen)
|
||||
{
|
||||
uint8_t nonce_id;
|
||||
uint8_t nonce_page;
|
||||
uint32_t crc32;
|
||||
uint8_t buffer[64];
|
||||
uint8_t nonce[56]; // max nonce data
|
||||
uint16_t noncelen;
|
||||
uint16_t buflen;
|
||||
|
||||
if (report_id == PS4AuthReport::PS4_SET_AUTH_PAYLOAD) {
|
||||
if (reqlen != 63 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup CRC32 buffer
|
||||
buffer[0] = report_id;
|
||||
memcpy(&buffer[1], data, reqlen);
|
||||
buflen = reqlen + 1;
|
||||
|
||||
nonce_id = data[0];
|
||||
nonce_page = data[1];
|
||||
// data[2] is zero padding
|
||||
|
||||
crc32 = CRC32::calculate(buffer, buflen-sizeof(uint32_t));
|
||||
if ( crc32 != *((unsigned int*)&buffer[buflen-sizeof(uint32_t)])) {
|
||||
return; // CRC32 failed on set report
|
||||
}
|
||||
|
||||
// 256 byte nonce, with 56 byte packets leaves 24 extra bytes on the last packet?
|
||||
if ( nonce_page == 4 ) {
|
||||
// Copy/append data from buffer[4:64-28] into our nonce
|
||||
noncelen = 32; // from 4 to 64 - 24 - 4
|
||||
} else {
|
||||
// Copy/append data from buffer[4:64-4] into our nonce
|
||||
noncelen = 56;
|
||||
// from 4 to 64 - 4
|
||||
}
|
||||
|
||||
memcpy(nonce, &buffer[4], noncelen);
|
||||
save_nonce(nonce_id, nonce_page, nonce, noncelen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void save_nonce(uint8_t nonce_id, uint8_t nonce_page, uint8_t * buffer, uint16_t buflen) {
|
||||
if ( nonce_page != 0 && nonce_id != cur_nonce_id ) {
|
||||
PS4Data::getInstance().ps4State = PS4State::no_nonce;
|
||||
return; // setting nonce with mismatched id
|
||||
}
|
||||
|
||||
memcpy(&PS4Data::getInstance().nonce_buffer[nonce_page*56], buffer, buflen);
|
||||
if ( nonce_page == 4 ) {
|
||||
PS4Data::getInstance().ps4State = PS4State::nonce_ready;
|
||||
} else if ( nonce_page == 0 ) {
|
||||
cur_nonce_id = nonce_id;
|
||||
PS4Data::getInstance().ps4State = PS4State::receiving_nonce;
|
||||
}
|
||||
}
|
||||
|
||||
void receive_ps4_report(void)
|
||||
{
|
||||
if (
|
||||
tud_ready() &&
|
||||
(ps4_endpoint_out != 0) && (!usbd_edpt_busy(0, ps4_endpoint_out)))
|
||||
{
|
||||
usbd_edpt_claim(0, ps4_endpoint_out); // Take control of OUT endpoint
|
||||
usbd_edpt_xfer(0, ps4_endpoint_out, ps4_out_buffer, PS4_OUT_SIZE); // Retrieve report buffer
|
||||
usbd_edpt_release(0, ps4_endpoint_out); // Release control of OUT endpoint
|
||||
}
|
||||
}
|
||||
|
||||
bool send_ps4_report(void *report, uint8_t report_size)
|
||||
{
|
||||
bool sent = false;
|
||||
|
||||
if (
|
||||
tud_ready() && // Is the device ready?
|
||||
(ps4_endpoint_in != 0) && (!usbd_edpt_busy(0, ps4_endpoint_in)) // Is the IN endpoint available?
|
||||
)
|
||||
{
|
||||
usbd_edpt_claim(0, ps4_endpoint_in); // Take control of IN endpoint
|
||||
usbd_edpt_xfer(0, ps4_endpoint_in, (uint8_t *)report, report_size); // Send report buffer
|
||||
usbd_edpt_release(0, ps4_endpoint_in); // Release control of IN endpoint
|
||||
sent = true;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
const usbd_class_driver_t ps4_driver =
|
||||
{
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
.name = "PS4",
|
||||
#endif
|
||||
.init = hidd_init,
|
||||
.reset = hidd_reset,
|
||||
.open = hidd_open,
|
||||
.control_xfer_cb = hidd_control_xfer_cb,
|
||||
.xfer_cb = hidd_xfer_cb,
|
||||
.sof = NULL};
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb.h"
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include "gamepad/descriptors/PS4Descriptors.h"
|
||||
|
||||
#define PS4_OUT_SIZE 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PS4_UNKNOWN_0X03 = 0x03, // Unknown (PS4 Report 0x03)
|
||||
PS4_SET_AUTH_PAYLOAD = 0xF0, // Set Auth Payload
|
||||
PS4_GET_SIGNATURE_NONCE = 0xF1, // Get Signature Nonce
|
||||
PS4_GET_SIGNING_STATE = 0xF2, // Get Signing State
|
||||
PS4_RESET_AUTH = 0xF3 // Unknown (PS4 Report 0xF3)
|
||||
} PS4AuthReport;
|
||||
|
||||
// USB endpoint state vars
|
||||
extern const usbd_class_driver_t ps4_driver;
|
||||
|
||||
ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen);
|
||||
void set_ps4_report(uint8_t report_id, uint8_t const * buf, uint16_t reqlen);
|
||||
void receive_ps4_report(void);
|
||||
bool send_ps4_report(void *report, uint8_t report_size);
|
||||
void save_nonce(uint8_t nonce_id, uint8_t nonce_page, uint8_t * data, uint16_t size);
|
||||
|
||||
typedef enum {
|
||||
no_nonce = 0,
|
||||
receiving_nonce = 1,
|
||||
nonce_ready = 2,
|
||||
signed_nonce_ready = 3
|
||||
} PS4State;
|
||||
|
||||
// Storage manager for board, LED options, and thread-safe settings
|
||||
class PS4Data {
|
||||
public:
|
||||
PS4Data(PS4Data const&) = delete;
|
||||
void operator=(PS4Data const&) = delete;
|
||||
static PS4Data& getInstance() // Thread-safe storage ensures cross-thread talk
|
||||
{
|
||||
static PS4Data instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
PS4State ps4State;
|
||||
bool authsent;
|
||||
uint8_t nonce_buffer[256];
|
||||
|
||||
// Send back in 56 byte chunks:
|
||||
// 256 byte - nonce signature
|
||||
// 16 byte - ps4 serial
|
||||
// 256 byte - RSA N
|
||||
// 256 byte - RSA E
|
||||
// 256 byte - ps4 signature
|
||||
// 24 byte - zero padding
|
||||
|
||||
// buffer = 256 + 16 + 256 + 256 + 256 + 24
|
||||
// == 1064 bytes (almost 1 kb)
|
||||
uint8_t ps4_auth_buffer[1064];
|
||||
private:
|
||||
PS4Data() {
|
||||
ps4State = PS4State::no_nonce;
|
||||
authsent = false;
|
||||
memset(nonce_buffer, 0, 256);
|
||||
memset(ps4_auth_buffer, 0, 1064);
|
||||
}
|
||||
};
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb.h"
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include "gamepad/descriptors/PS4Descriptors.h"
|
||||
|
||||
#define PS4_OUT_SIZE 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PS4_UNKNOWN_0X03 = 0x03, // Unknown (PS4 Report 0x03)
|
||||
PS4_SET_AUTH_PAYLOAD = 0xF0, // Set Auth Payload
|
||||
PS4_GET_SIGNATURE_NONCE = 0xF1, // Get Signature Nonce
|
||||
PS4_GET_SIGNING_STATE = 0xF2, // Get Signing State
|
||||
PS4_RESET_AUTH = 0xF3 // Unknown (PS4 Report 0xF3)
|
||||
} PS4AuthReport;
|
||||
|
||||
// USB endpoint state vars
|
||||
extern const usbd_class_driver_t ps4_driver;
|
||||
|
||||
ssize_t get_ps4_report(uint8_t report_id, uint8_t * buf, uint16_t reqlen);
|
||||
void set_ps4_report(uint8_t report_id, uint8_t const * buf, uint16_t reqlen);
|
||||
void receive_ps4_report(void);
|
||||
bool send_ps4_report(void *report, uint8_t report_size);
|
||||
void save_nonce(uint8_t nonce_id, uint8_t nonce_page, uint8_t * data, uint16_t size);
|
||||
|
||||
typedef enum {
|
||||
no_nonce = 0,
|
||||
receiving_nonce = 1,
|
||||
nonce_ready = 2,
|
||||
signed_nonce_ready = 3
|
||||
} PS4State;
|
||||
|
||||
// Storage manager for board, LED options, and thread-safe settings
|
||||
class PS4Data {
|
||||
public:
|
||||
PS4Data(PS4Data const&) = delete;
|
||||
void operator=(PS4Data const&) = delete;
|
||||
static PS4Data& getInstance() // Thread-safe storage ensures cross-thread talk
|
||||
{
|
||||
static PS4Data instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
PS4State ps4State;
|
||||
bool authsent;
|
||||
uint8_t nonce_buffer[256];
|
||||
|
||||
// Send back in 56 byte chunks:
|
||||
// 256 byte - nonce signature
|
||||
// 16 byte - ps4 serial
|
||||
// 256 byte - RSA N
|
||||
// 256 byte - RSA E
|
||||
// 256 byte - ps4 signature
|
||||
// 24 byte - zero padding
|
||||
|
||||
// buffer = 256 + 16 + 256 + 256 + 256 + 24
|
||||
// == 1064 bytes (almost 1 kb)
|
||||
uint8_t ps4_auth_buffer[1064];
|
||||
private:
|
||||
PS4Data() {
|
||||
ps4State = PS4State::no_nonce;
|
||||
authsent = false;
|
||||
memset(nonce_buffer, 0, 256);
|
||||
memset(ps4_auth_buffer, 0, 1064);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,117 +1,117 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#include "addons/ps4mode.h"
|
||||
#include "helper.h"
|
||||
#include "config.pb.h"
|
||||
|
||||
#include "ps4_driver.h"
|
||||
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
bool PS4ModeAddon::available() {
|
||||
const PS4Options& options = Storage::getInstance().getAddonOptions().ps4Options;
|
||||
return options.enabled
|
||||
&& options.serial.size == sizeof(options.serial.bytes)
|
||||
&& options.signature.size == sizeof(options.signature.bytes)
|
||||
&& options.rsaN.size == sizeof(options.rsaN.bytes)
|
||||
&& options.rsaE.size == sizeof(options.rsaE.bytes)
|
||||
&& options.rsaD.size == sizeof(options.rsaD.bytes)
|
||||
&& options.rsaP.size == sizeof(options.rsaP.bytes)
|
||||
&& options.rsaQ.size == sizeof(options.rsaQ.bytes)
|
||||
&& options.rsaDP.size == sizeof(options.rsaDP.bytes)
|
||||
&& options.rsaDQ.size == sizeof(options.rsaDQ.bytes)
|
||||
&& options.rsaQP.size == sizeof(options.rsaQP.bytes)
|
||||
&& options.rsaRN.size == sizeof(options.rsaRN.bytes);
|
||||
}
|
||||
|
||||
void PS4ModeAddon::setup() {
|
||||
const PS4Options& options = Storage::getInstance().getAddonOptions().ps4Options;
|
||||
|
||||
memcpy(bytesN, options.rsaN.bytes, options.rsaN.size);
|
||||
memcpy(bytesE, options.rsaE.bytes, options.rsaE.size);
|
||||
memcpy(bytesD, options.rsaD.bytes, options.rsaD.size);
|
||||
memcpy(bytesP, options.rsaP.bytes, options.rsaP.size);
|
||||
memcpy(bytesQ, options.rsaQ.bytes, options.rsaQ.size);
|
||||
memcpy(bytesDP, options.rsaDP.bytes, options.rsaDP.size);
|
||||
memcpy(bytesDQ, options.rsaDQ.bytes, options.rsaDQ.size);
|
||||
memcpy(bytesQP, options.rsaQP.bytes, options.rsaQP.size);
|
||||
memcpy(bytesRN, options.rsaRN.bytes, options.rsaRN.size);
|
||||
|
||||
rsa_context = {
|
||||
.ver = 0,
|
||||
.len = 256,
|
||||
.N = { .s=1, .n=64, .p=bytesN },
|
||||
.E = { .s=1, .n=1, .p=bytesE },
|
||||
.D = { .s=1, .n=64, .p=bytesD },
|
||||
.P = { .s=1, .n=32, .p=bytesP },
|
||||
.Q = { .s=1, .n=32, .p=bytesQ },
|
||||
.DP = { .s=1, .n=32, .p=bytesDP },
|
||||
.DQ = { .s=1, .n=32, .p=bytesDQ },
|
||||
.QP = { .s=1, .n=32, .p=bytesQP },
|
||||
.RN = { .s=1, .n=64, .p=bytesRN },
|
||||
.RP = { .s=0, .n=0, .p=nullptr },
|
||||
.RQ = { .s=0, .n=0, .p=nullptr },
|
||||
.Vi = { .s=0, .n=0, .p=nullptr },
|
||||
.Vf = { .s=0, .n=0, .p=nullptr },
|
||||
.padding = MBEDTLS_RSA_PKCS_V21, .hash_id = MBEDTLS_MD_SHA256,
|
||||
};
|
||||
}
|
||||
|
||||
void PS4ModeAddon::process() {
|
||||
const PS4Options& options = Storage::getInstance().getAddonOptions().ps4Options;
|
||||
|
||||
int rss_error = 0;
|
||||
|
||||
// Check to see if the PS4 Authentication needs work
|
||||
if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready ) {
|
||||
|
||||
// Generate some random for RNG
|
||||
srand(getMillis());
|
||||
auto rng = [](void*p_rng, unsigned char* p, size_t len) {
|
||||
(void) p_rng;
|
||||
p[0] = rand();
|
||||
return 0;
|
||||
};
|
||||
|
||||
uint8_t nonce_signature[256];
|
||||
uint8_t * nonce_buffer = PS4Data::getInstance().nonce_buffer;
|
||||
uint8_t * ps4_auth_buffer = PS4Data::getInstance().ps4_auth_buffer;
|
||||
|
||||
// Sign the nonce now that we got it!
|
||||
//
|
||||
if ( mbedtls_sha256_ret(nonce_buffer, 256, hashed_nonce, 0) < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
rss_error = mbedtls_rsa_rsassa_pss_sign(&rsa_context, rng, nullptr,
|
||||
MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
|
||||
32, hashed_nonce,
|
||||
nonce_signature);
|
||||
|
||||
if ( rss_error < 0 ) {
|
||||
return;
|
||||
}
|
||||
// copy the parts into our authentication buffer
|
||||
int offset = 0;
|
||||
memcpy(&ps4_auth_buffer[offset], nonce_signature, 256);
|
||||
offset += 256;
|
||||
memcpy(&ps4_auth_buffer[offset], options.serial.bytes, 16);
|
||||
offset += 16;
|
||||
mbedtls_mpi* mpi = static_cast<mbedtls_mpi*>(&rsa_context.N);
|
||||
mbedtls_mpi_write_binary(mpi, &ps4_auth_buffer[offset], 256);
|
||||
offset += 256;
|
||||
mpi = static_cast<mbedtls_mpi*>(&rsa_context.E);
|
||||
mbedtls_mpi_write_binary(mpi, &ps4_auth_buffer[offset], 256);
|
||||
offset += 256;
|
||||
memcpy(&ps4_auth_buffer[offset], options.signature.bytes, 256);
|
||||
offset += 256;
|
||||
memset(&ps4_auth_buffer[offset], 0, 24);
|
||||
|
||||
PS4Data::getInstance().ps4State = PS4State::signed_nonce_ready; // signed and ready to party
|
||||
}
|
||||
}
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 Jason Skuby (mytechtoybox.com)
|
||||
*/
|
||||
|
||||
#include "addons/ps4mode.h"
|
||||
#include "helper.h"
|
||||
#include "config.pb.h"
|
||||
|
||||
#include "ps4_driver.h"
|
||||
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
bool PS4ModeAddon::available() {
|
||||
const PS4Options& options = Storage::getInstance().getAddonOptions().ps4Options;
|
||||
return options.enabled
|
||||
&& options.serial.size == sizeof(options.serial.bytes)
|
||||
&& options.signature.size == sizeof(options.signature.bytes)
|
||||
&& options.rsaN.size == sizeof(options.rsaN.bytes)
|
||||
&& options.rsaE.size == sizeof(options.rsaE.bytes)
|
||||
&& options.rsaD.size == sizeof(options.rsaD.bytes)
|
||||
&& options.rsaP.size == sizeof(options.rsaP.bytes)
|
||||
&& options.rsaQ.size == sizeof(options.rsaQ.bytes)
|
||||
&& options.rsaDP.size == sizeof(options.rsaDP.bytes)
|
||||
&& options.rsaDQ.size == sizeof(options.rsaDQ.bytes)
|
||||
&& options.rsaQP.size == sizeof(options.rsaQP.bytes)
|
||||
&& options.rsaRN.size == sizeof(options.rsaRN.bytes);
|
||||
}
|
||||
|
||||
void PS4ModeAddon::setup() {
|
||||
const PS4Options& options = Storage::getInstance().getAddonOptions().ps4Options;
|
||||
|
||||
memcpy(bytesN, options.rsaN.bytes, options.rsaN.size);
|
||||
memcpy(bytesE, options.rsaE.bytes, options.rsaE.size);
|
||||
memcpy(bytesD, options.rsaD.bytes, options.rsaD.size);
|
||||
memcpy(bytesP, options.rsaP.bytes, options.rsaP.size);
|
||||
memcpy(bytesQ, options.rsaQ.bytes, options.rsaQ.size);
|
||||
memcpy(bytesDP, options.rsaDP.bytes, options.rsaDP.size);
|
||||
memcpy(bytesDQ, options.rsaDQ.bytes, options.rsaDQ.size);
|
||||
memcpy(bytesQP, options.rsaQP.bytes, options.rsaQP.size);
|
||||
memcpy(bytesRN, options.rsaRN.bytes, options.rsaRN.size);
|
||||
|
||||
rsa_context = {
|
||||
.ver = 0,
|
||||
.len = 256,
|
||||
.N = { .s=1, .n=64, .p=bytesN },
|
||||
.E = { .s=1, .n=1, .p=bytesE },
|
||||
.D = { .s=1, .n=64, .p=bytesD },
|
||||
.P = { .s=1, .n=32, .p=bytesP },
|
||||
.Q = { .s=1, .n=32, .p=bytesQ },
|
||||
.DP = { .s=1, .n=32, .p=bytesDP },
|
||||
.DQ = { .s=1, .n=32, .p=bytesDQ },
|
||||
.QP = { .s=1, .n=32, .p=bytesQP },
|
||||
.RN = { .s=1, .n=64, .p=bytesRN },
|
||||
.RP = { .s=0, .n=0, .p=nullptr },
|
||||
.RQ = { .s=0, .n=0, .p=nullptr },
|
||||
.Vi = { .s=0, .n=0, .p=nullptr },
|
||||
.Vf = { .s=0, .n=0, .p=nullptr },
|
||||
.padding = MBEDTLS_RSA_PKCS_V21, .hash_id = MBEDTLS_MD_SHA256,
|
||||
};
|
||||
}
|
||||
|
||||
void PS4ModeAddon::process() {
|
||||
const PS4Options& options = Storage::getInstance().getAddonOptions().ps4Options;
|
||||
|
||||
int rss_error = 0;
|
||||
|
||||
// Check to see if the PS4 Authentication needs work
|
||||
if ( PS4Data::getInstance().ps4State == PS4State::nonce_ready ) {
|
||||
|
||||
// Generate some random for RNG
|
||||
srand(getMillis());
|
||||
auto rng = [](void*p_rng, unsigned char* p, size_t len) {
|
||||
(void) p_rng;
|
||||
p[0] = rand();
|
||||
return 0;
|
||||
};
|
||||
|
||||
uint8_t nonce_signature[256];
|
||||
uint8_t * nonce_buffer = PS4Data::getInstance().nonce_buffer;
|
||||
uint8_t * ps4_auth_buffer = PS4Data::getInstance().ps4_auth_buffer;
|
||||
|
||||
// Sign the nonce now that we got it!
|
||||
//
|
||||
if ( mbedtls_sha256_ret(nonce_buffer, 256, hashed_nonce, 0) < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
rss_error = mbedtls_rsa_rsassa_pss_sign(&rsa_context, rng, nullptr,
|
||||
MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
|
||||
32, hashed_nonce,
|
||||
nonce_signature);
|
||||
|
||||
if ( rss_error < 0 ) {
|
||||
return;
|
||||
}
|
||||
// copy the parts into our authentication buffer
|
||||
int offset = 0;
|
||||
memcpy(&ps4_auth_buffer[offset], nonce_signature, 256);
|
||||
offset += 256;
|
||||
memcpy(&ps4_auth_buffer[offset], options.serial.bytes, 16);
|
||||
offset += 16;
|
||||
mbedtls_mpi* mpi = static_cast<mbedtls_mpi*>(&rsa_context.N);
|
||||
mbedtls_mpi_write_binary(mpi, &ps4_auth_buffer[offset], 256);
|
||||
offset += 256;
|
||||
mpi = static_cast<mbedtls_mpi*>(&rsa_context.E);
|
||||
mbedtls_mpi_write_binary(mpi, &ps4_auth_buffer[offset], 256);
|
||||
offset += 256;
|
||||
memcpy(&ps4_auth_buffer[offset], options.signature.bytes, 256);
|
||||
offset += 256;
|
||||
memset(&ps4_auth_buffer[offset], 0, 24);
|
||||
|
||||
PS4Data::getInstance().ps4State = PS4State::signed_nonce_ready; // signed and ready to party
|
||||
}
|
||||
}
|
||||
|
||||
6
www/.env
6
www/.env
@@ -1,3 +1,3 @@
|
||||
VITE_CURRENT_VERSION=v0.7.2
|
||||
VITE_GP2040_BOARD=pico
|
||||
VITE_GP2040_CONTROLLER=pico
|
||||
VITE_CURRENT_VERSION=v0.7.2
|
||||
VITE_GP2040_BOARD=pico
|
||||
VITE_GP2040_CONTROLLER=pico
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
env:
|
||||
node: true
|
||||
browser: true
|
||||
es2021: true
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:react/recommended
|
||||
- plugin:react-hooks/recommended
|
||||
overrides: []
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
settings:
|
||||
react:
|
||||
version: "18.2"
|
||||
plugins:
|
||||
- react-refresh
|
||||
rules:
|
||||
react-refresh/only-export-components: warn
|
||||
react/prop-types: off
|
||||
no-template-curly-in-string: off
|
||||
no-unused-vars: off
|
||||
react-hooks/exhaustive-deps: off
|
||||
no-extra-boolean-cast: off
|
||||
env:
|
||||
node: true
|
||||
browser: true
|
||||
es2021: true
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:react/recommended
|
||||
- plugin:react-hooks/recommended
|
||||
overrides: []
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
settings:
|
||||
react:
|
||||
version: "18.2"
|
||||
plugins:
|
||||
- react-refresh
|
||||
rules:
|
||||
react-refresh/only-export-components: warn
|
||||
react/prop-types: off
|
||||
no-template-curly-in-string: off
|
||||
no-unused-vars: off
|
||||
react-hooks/exhaustive-deps: off
|
||||
no-extra-boolean-cast: off
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web configuration application for GP2040-CE gamepad firmware"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/logo.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
|
||||
<title>GP2040-CE Configurator</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web configuration application for GP2040-CE gamepad firmware"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/logo.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
|
||||
<title>GP2040-CE Configurator</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,305 +1,305 @@
|
||||
/**
|
||||
* GP2040-CE Configurator Development Server
|
||||
*/
|
||||
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import mapValues from "lodash/mapValues.js";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const { pico: picoController } = JSON.parse(
|
||||
readFileSync(path.resolve(__dirname, "../src/Data/Controllers.json"), "utf8")
|
||||
);
|
||||
const { keyboard: keyboardMapping } = JSON.parse(
|
||||
readFileSync(path.resolve(__dirname, "../src/Data/Keyboard.json"), "utf8")
|
||||
);
|
||||
const port = process.env.PORT || 8080;
|
||||
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use((req, res, next) => {
|
||||
console.log("Request:", req.method, req.url);
|
||||
next();
|
||||
});
|
||||
|
||||
app.get("/api/getUsedPins", (req, res) => {
|
||||
return res.send({ usedPins: Object.values(picoController) });
|
||||
});
|
||||
|
||||
app.get("/api/resetSettings", (req, res) => {
|
||||
return res.send({ success: true });
|
||||
});
|
||||
|
||||
app.get("/api/getDisplayOptions", (req, res) => {
|
||||
const data = {
|
||||
enabled: 1,
|
||||
sdaPin: 0,
|
||||
sclPin: 1,
|
||||
i2cAddress: "0x3D",
|
||||
i2cBlock: 0,
|
||||
i2cSpeed: 400000,
|
||||
flipDisplay: 0,
|
||||
invertDisplay: 1,
|
||||
buttonLayout: 0,
|
||||
buttonLayoutRight: 3,
|
||||
splashMode: 3,
|
||||
splashChoice: 0,
|
||||
splashDuration: 0,
|
||||
splashImage: Array(16 * 64).fill(255),
|
||||
buttonLayoutCustomOptions: {
|
||||
params: {
|
||||
layout: 2,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
paramsRight: {
|
||||
layout: 9,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
},
|
||||
|
||||
displaySaverTimeout: 0,
|
||||
};
|
||||
console.log("data", data);
|
||||
return res.send(data);
|
||||
});
|
||||
|
||||
app.get("/api/getSplashImage", (req, res) => {
|
||||
const data = {
|
||||
splashImage: Array(16 * 64).fill(255),
|
||||
};
|
||||
console.log("data", data);
|
||||
return res.send(data);
|
||||
});
|
||||
|
||||
app.get("/api/getGamepadOptions", (req, res) => {
|
||||
return res.send({
|
||||
dpadMode: 0,
|
||||
inputMode: 4,
|
||||
socdMode: 2,
|
||||
switchTpShareForDs4: 0,
|
||||
forcedSetupMode: 0,
|
||||
lockHotkeys: 0,
|
||||
hotkeyF1: [
|
||||
{ action: 1, mask: 1 << 0 },
|
||||
{ action: 2, mask: 1 << 1 },
|
||||
{ action: 3, mask: 1 << 2 },
|
||||
{ action: 4, mask: 1 << 3 },
|
||||
],
|
||||
hotkeyF2: [
|
||||
{ action: 5, mask: 1 << 0 },
|
||||
{ action: 6, mask: 1 << 1 },
|
||||
{ action: 7, mask: 1 << 2 },
|
||||
{ action: 8, mask: 1 << 3 },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getLedOptions", (req, res) => {
|
||||
return res.send({
|
||||
brightnessMaximum: 255,
|
||||
brightnessSteps: 5,
|
||||
dataPin: 15,
|
||||
ledFormat: 0,
|
||||
ledLayout: 1,
|
||||
ledsPerButton: 2,
|
||||
ledButtonMap: {
|
||||
Up: 3,
|
||||
Down: 1,
|
||||
Left: 0,
|
||||
Right: 2,
|
||||
B1: 8,
|
||||
B2: 9,
|
||||
B3: 4,
|
||||
B4: 5,
|
||||
L1: 7,
|
||||
R1: 6,
|
||||
L2: 11,
|
||||
R2: 10,
|
||||
S1: null,
|
||||
S2: null,
|
||||
L3: null,
|
||||
R3: null,
|
||||
A1: null,
|
||||
A2: null,
|
||||
},
|
||||
usedPins: Object.values(picoController),
|
||||
pledType: 1,
|
||||
pledPin1: 12,
|
||||
pledPin2: 13,
|
||||
pledPin3: 14,
|
||||
pledPin4: 15,
|
||||
pledColor: 65280,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getCustomTheme", (req, res) => {
|
||||
console.log("/api/getCustomTheme");
|
||||
return res.send({
|
||||
enabled: true,
|
||||
Up: { u: 16711680, d: 255 },
|
||||
Down: { u: 16711680, d: 255 },
|
||||
Left: { u: 16711680, d: 255 },
|
||||
Right: { u: 16711680, d: 255 },
|
||||
B1: { u: 65280, d: 16711680 },
|
||||
B2: { u: 65280, d: 16711680 },
|
||||
B3: { u: 255, d: 65280 },
|
||||
B4: { u: 255, d: 65280 },
|
||||
L1: { u: 255, d: 65280 },
|
||||
R1: { u: 255, d: 65280 },
|
||||
L2: { u: 65280, d: 16711680 },
|
||||
R2: { u: 65280, d: 16711680 },
|
||||
S1: { u: 65535, d: 16776960 },
|
||||
S2: { u: 65535, d: 16776960 },
|
||||
L3: { u: 65416, d: 16746496 },
|
||||
R3: { u: 65416, d: 16746496 },
|
||||
A1: { u: 8913151, d: 65416 },
|
||||
A2: { u: 8913151, d: 65416 },
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getPinMappings", (req, res) => {
|
||||
return res.send(picoController);
|
||||
});
|
||||
|
||||
app.get("/api/getKeyMappings", (req, res) =>
|
||||
res.send(mapValues(keyboardMapping))
|
||||
);
|
||||
|
||||
app.get("/api/getAddonsOptions", (req, res) => {
|
||||
return res.send({
|
||||
turboPin: -1,
|
||||
turboPinLED: -1,
|
||||
sliderLSPin: -1,
|
||||
sliderRSPin: -1,
|
||||
sliderSOCDPinOne: -1,
|
||||
sliderSOCDPinTwo: -1,
|
||||
turboShotCount: 20,
|
||||
reversePin: -1,
|
||||
reversePinLED: -1,
|
||||
reverseActionUp: 1,
|
||||
reverseActionDown: 1,
|
||||
reverseActionLeft: 1,
|
||||
reverseActionRight: 1,
|
||||
i2cAnalog1219SDAPin: -1,
|
||||
i2cAnalog1219SCLPin: -1,
|
||||
i2cAnalog1219Block: 0,
|
||||
i2cAnalog1219Speed: 400000,
|
||||
i2cAnalog1219Address: 0x40,
|
||||
onBoardLedMode: 0,
|
||||
dualDirUpPin: -1,
|
||||
dualDirDownPin: -1,
|
||||
dualDirLeftPin: -1,
|
||||
dualDirRightPin: -1,
|
||||
dualDirDpadMode: 0,
|
||||
dualDirCombineMode: 0,
|
||||
analogAdcPinX: -1,
|
||||
analogAdcPinY: -1,
|
||||
bootselButtonMap: 0,
|
||||
buzzerPin: -1,
|
||||
buzzerVolume: 100,
|
||||
extraButtonPin: -1,
|
||||
extraButtonMap: 0,
|
||||
playerNumber: 1,
|
||||
shmupMode: 0,
|
||||
shmupMixMode: 0,
|
||||
shmupAlwaysOn1: 0,
|
||||
shmupAlwaysOn2: 0,
|
||||
shmupAlwaysOn3: 0,
|
||||
shmupAlwaysOn4: 0,
|
||||
pinShmupBtn1: -1,
|
||||
pinShmupBtn2: -1,
|
||||
pinShmupBtn3: -1,
|
||||
pinShmupBtn4: -1,
|
||||
shmupBtnMask1: 0,
|
||||
shmupBtnMask2: 0,
|
||||
shmupBtnMask3: 0,
|
||||
shmupBtnMask4: 0,
|
||||
pinShmupDial: -1,
|
||||
sliderSOCDModeOne: 0,
|
||||
sliderSOCDModeTwo: 2,
|
||||
sliderSOCDModeDefault: 1,
|
||||
wiiExtensionSDAPin: -1,
|
||||
wiiExtensionSCLPin: -1,
|
||||
wiiExtensionBlock: 0,
|
||||
wiiExtensionSpeed: 400000,
|
||||
snesPadClockPin: -1,
|
||||
snesPadLatchPin: -1,
|
||||
snesPadDataPin: -1,
|
||||
AnalogInputEnabled: 1,
|
||||
BoardLedAddonEnabled: 1,
|
||||
BuzzerSpeakerAddonEnabled: 1,
|
||||
BootselButtonAddonEnabled: 1,
|
||||
DualDirectionalInputEnabled: 1,
|
||||
ExtraButtonAddonEnabled: 1,
|
||||
I2CAnalog1219InputEnabled: 1,
|
||||
JSliderInputEnabled: 1,
|
||||
PlayerNumAddonEnabled: 1,
|
||||
PS4ModeAddonEnabled: 1,
|
||||
ReverseInputEnabled: 1,
|
||||
SliderSOCDInputEnabled: 1,
|
||||
TurboInputEnabled: 1,
|
||||
WiiExtensionAddonEnabled: 1,
|
||||
SNESpadAddonEnabled: 1,
|
||||
usedPins: Object.values(picoController),
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getFirmwareVersion", (req, res) => {
|
||||
return res.send({
|
||||
version: process.env.VITE_CURRENT_VERSION,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getButtonLayoutCustomOptions", (req, res) => {
|
||||
return res.send({
|
||||
params: {
|
||||
layout: 2,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
paramsRight: {
|
||||
layout: 9,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/reboot", (req, res) => {
|
||||
return res.send({});
|
||||
});
|
||||
|
||||
app.get("/api/getMemoryReport", (req, res) => {
|
||||
return res.send({
|
||||
totalFlash: 2048,
|
||||
usedFlash: 1048,
|
||||
staticAllocs: 200,
|
||||
totalHeap: 2048,
|
||||
usedHeap: 1048,
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/api/*", (req, res) => {
|
||||
console.log(req.body);
|
||||
return res.send(req.body);
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Dev app listening at http://localhost:${port}`);
|
||||
});
|
||||
/**
|
||||
* GP2040-CE Configurator Development Server
|
||||
*/
|
||||
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import mapValues from "lodash/mapValues.js";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const { pico: picoController } = JSON.parse(
|
||||
readFileSync(path.resolve(__dirname, "../src/Data/Controllers.json"), "utf8")
|
||||
);
|
||||
const { keyboard: keyboardMapping } = JSON.parse(
|
||||
readFileSync(path.resolve(__dirname, "../src/Data/Keyboard.json"), "utf8")
|
||||
);
|
||||
const port = process.env.PORT || 8080;
|
||||
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use((req, res, next) => {
|
||||
console.log("Request:", req.method, req.url);
|
||||
next();
|
||||
});
|
||||
|
||||
app.get("/api/getUsedPins", (req, res) => {
|
||||
return res.send({ usedPins: Object.values(picoController) });
|
||||
});
|
||||
|
||||
app.get("/api/resetSettings", (req, res) => {
|
||||
return res.send({ success: true });
|
||||
});
|
||||
|
||||
app.get("/api/getDisplayOptions", (req, res) => {
|
||||
const data = {
|
||||
enabled: 1,
|
||||
sdaPin: 0,
|
||||
sclPin: 1,
|
||||
i2cAddress: "0x3D",
|
||||
i2cBlock: 0,
|
||||
i2cSpeed: 400000,
|
||||
flipDisplay: 0,
|
||||
invertDisplay: 1,
|
||||
buttonLayout: 0,
|
||||
buttonLayoutRight: 3,
|
||||
splashMode: 3,
|
||||
splashChoice: 0,
|
||||
splashDuration: 0,
|
||||
splashImage: Array(16 * 64).fill(255),
|
||||
buttonLayoutCustomOptions: {
|
||||
params: {
|
||||
layout: 2,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
paramsRight: {
|
||||
layout: 9,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
},
|
||||
|
||||
displaySaverTimeout: 0,
|
||||
};
|
||||
console.log("data", data);
|
||||
return res.send(data);
|
||||
});
|
||||
|
||||
app.get("/api/getSplashImage", (req, res) => {
|
||||
const data = {
|
||||
splashImage: Array(16 * 64).fill(255),
|
||||
};
|
||||
console.log("data", data);
|
||||
return res.send(data);
|
||||
});
|
||||
|
||||
app.get("/api/getGamepadOptions", (req, res) => {
|
||||
return res.send({
|
||||
dpadMode: 0,
|
||||
inputMode: 4,
|
||||
socdMode: 2,
|
||||
switchTpShareForDs4: 0,
|
||||
forcedSetupMode: 0,
|
||||
lockHotkeys: 0,
|
||||
hotkeyF1: [
|
||||
{ action: 1, mask: 1 << 0 },
|
||||
{ action: 2, mask: 1 << 1 },
|
||||
{ action: 3, mask: 1 << 2 },
|
||||
{ action: 4, mask: 1 << 3 },
|
||||
],
|
||||
hotkeyF2: [
|
||||
{ action: 5, mask: 1 << 0 },
|
||||
{ action: 6, mask: 1 << 1 },
|
||||
{ action: 7, mask: 1 << 2 },
|
||||
{ action: 8, mask: 1 << 3 },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getLedOptions", (req, res) => {
|
||||
return res.send({
|
||||
brightnessMaximum: 255,
|
||||
brightnessSteps: 5,
|
||||
dataPin: 15,
|
||||
ledFormat: 0,
|
||||
ledLayout: 1,
|
||||
ledsPerButton: 2,
|
||||
ledButtonMap: {
|
||||
Up: 3,
|
||||
Down: 1,
|
||||
Left: 0,
|
||||
Right: 2,
|
||||
B1: 8,
|
||||
B2: 9,
|
||||
B3: 4,
|
||||
B4: 5,
|
||||
L1: 7,
|
||||
R1: 6,
|
||||
L2: 11,
|
||||
R2: 10,
|
||||
S1: null,
|
||||
S2: null,
|
||||
L3: null,
|
||||
R3: null,
|
||||
A1: null,
|
||||
A2: null,
|
||||
},
|
||||
usedPins: Object.values(picoController),
|
||||
pledType: 1,
|
||||
pledPin1: 12,
|
||||
pledPin2: 13,
|
||||
pledPin3: 14,
|
||||
pledPin4: 15,
|
||||
pledColor: 65280,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getCustomTheme", (req, res) => {
|
||||
console.log("/api/getCustomTheme");
|
||||
return res.send({
|
||||
enabled: true,
|
||||
Up: { u: 16711680, d: 255 },
|
||||
Down: { u: 16711680, d: 255 },
|
||||
Left: { u: 16711680, d: 255 },
|
||||
Right: { u: 16711680, d: 255 },
|
||||
B1: { u: 65280, d: 16711680 },
|
||||
B2: { u: 65280, d: 16711680 },
|
||||
B3: { u: 255, d: 65280 },
|
||||
B4: { u: 255, d: 65280 },
|
||||
L1: { u: 255, d: 65280 },
|
||||
R1: { u: 255, d: 65280 },
|
||||
L2: { u: 65280, d: 16711680 },
|
||||
R2: { u: 65280, d: 16711680 },
|
||||
S1: { u: 65535, d: 16776960 },
|
||||
S2: { u: 65535, d: 16776960 },
|
||||
L3: { u: 65416, d: 16746496 },
|
||||
R3: { u: 65416, d: 16746496 },
|
||||
A1: { u: 8913151, d: 65416 },
|
||||
A2: { u: 8913151, d: 65416 },
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getPinMappings", (req, res) => {
|
||||
return res.send(picoController);
|
||||
});
|
||||
|
||||
app.get("/api/getKeyMappings", (req, res) =>
|
||||
res.send(mapValues(keyboardMapping))
|
||||
);
|
||||
|
||||
app.get("/api/getAddonsOptions", (req, res) => {
|
||||
return res.send({
|
||||
turboPin: -1,
|
||||
turboPinLED: -1,
|
||||
sliderLSPin: -1,
|
||||
sliderRSPin: -1,
|
||||
sliderSOCDPinOne: -1,
|
||||
sliderSOCDPinTwo: -1,
|
||||
turboShotCount: 20,
|
||||
reversePin: -1,
|
||||
reversePinLED: -1,
|
||||
reverseActionUp: 1,
|
||||
reverseActionDown: 1,
|
||||
reverseActionLeft: 1,
|
||||
reverseActionRight: 1,
|
||||
i2cAnalog1219SDAPin: -1,
|
||||
i2cAnalog1219SCLPin: -1,
|
||||
i2cAnalog1219Block: 0,
|
||||
i2cAnalog1219Speed: 400000,
|
||||
i2cAnalog1219Address: 0x40,
|
||||
onBoardLedMode: 0,
|
||||
dualDirUpPin: -1,
|
||||
dualDirDownPin: -1,
|
||||
dualDirLeftPin: -1,
|
||||
dualDirRightPin: -1,
|
||||
dualDirDpadMode: 0,
|
||||
dualDirCombineMode: 0,
|
||||
analogAdcPinX: -1,
|
||||
analogAdcPinY: -1,
|
||||
bootselButtonMap: 0,
|
||||
buzzerPin: -1,
|
||||
buzzerVolume: 100,
|
||||
extraButtonPin: -1,
|
||||
extraButtonMap: 0,
|
||||
playerNumber: 1,
|
||||
shmupMode: 0,
|
||||
shmupMixMode: 0,
|
||||
shmupAlwaysOn1: 0,
|
||||
shmupAlwaysOn2: 0,
|
||||
shmupAlwaysOn3: 0,
|
||||
shmupAlwaysOn4: 0,
|
||||
pinShmupBtn1: -1,
|
||||
pinShmupBtn2: -1,
|
||||
pinShmupBtn3: -1,
|
||||
pinShmupBtn4: -1,
|
||||
shmupBtnMask1: 0,
|
||||
shmupBtnMask2: 0,
|
||||
shmupBtnMask3: 0,
|
||||
shmupBtnMask4: 0,
|
||||
pinShmupDial: -1,
|
||||
sliderSOCDModeOne: 0,
|
||||
sliderSOCDModeTwo: 2,
|
||||
sliderSOCDModeDefault: 1,
|
||||
wiiExtensionSDAPin: -1,
|
||||
wiiExtensionSCLPin: -1,
|
||||
wiiExtensionBlock: 0,
|
||||
wiiExtensionSpeed: 400000,
|
||||
snesPadClockPin: -1,
|
||||
snesPadLatchPin: -1,
|
||||
snesPadDataPin: -1,
|
||||
AnalogInputEnabled: 1,
|
||||
BoardLedAddonEnabled: 1,
|
||||
BuzzerSpeakerAddonEnabled: 1,
|
||||
BootselButtonAddonEnabled: 1,
|
||||
DualDirectionalInputEnabled: 1,
|
||||
ExtraButtonAddonEnabled: 1,
|
||||
I2CAnalog1219InputEnabled: 1,
|
||||
JSliderInputEnabled: 1,
|
||||
PlayerNumAddonEnabled: 1,
|
||||
PS4ModeAddonEnabled: 1,
|
||||
ReverseInputEnabled: 1,
|
||||
SliderSOCDInputEnabled: 1,
|
||||
TurboInputEnabled: 1,
|
||||
WiiExtensionAddonEnabled: 1,
|
||||
SNESpadAddonEnabled: 1,
|
||||
usedPins: Object.values(picoController),
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getFirmwareVersion", (req, res) => {
|
||||
return res.send({
|
||||
version: process.env.VITE_CURRENT_VERSION,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/getButtonLayoutCustomOptions", (req, res) => {
|
||||
return res.send({
|
||||
params: {
|
||||
layout: 2,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
paramsRight: {
|
||||
layout: 9,
|
||||
startX: 8,
|
||||
startY: 28,
|
||||
buttonRadius: 8,
|
||||
buttonPadding: 2,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/reboot", (req, res) => {
|
||||
return res.send({});
|
||||
});
|
||||
|
||||
app.get("/api/getMemoryReport", (req, res) => {
|
||||
return res.send({
|
||||
totalFlash: 2048,
|
||||
usedFlash: 1048,
|
||||
staticAllocs: 200,
|
||||
totalHeap: 2048,
|
||||
usedHeap: 1048,
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/api/*", (req, res) => {
|
||||
console.log(req.body);
|
||||
return res.send(req.body);
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Dev app listening at http://localhost:${port}`);
|
||||
});
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
import React, { useContext } from "react";
|
||||
import { Dropdown } from "react-bootstrap";
|
||||
import { AppContext } from "../Contexts/AppContext";
|
||||
import SunIcon from "../Icons/Sun";
|
||||
import MoonStarsIcon from "../Icons/MoonStars";
|
||||
import CircleHalfIcon from "../Icons/CircleHalf";
|
||||
|
||||
const dropdownOptions = [
|
||||
{ scheme: "light", icon: SunIcon, label: "Light" },
|
||||
{ scheme: "dark", icon: MoonStarsIcon, label: "Dark" },
|
||||
{ scheme: "auto", icon: CircleHalfIcon, label: "Auto" },
|
||||
];
|
||||
|
||||
const setTheme = function (theme) {
|
||||
const rootElement = document.documentElement;
|
||||
const prefersDarkMode = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)"
|
||||
).matches;
|
||||
|
||||
if (theme === "auto") {
|
||||
rootElement.setAttribute(
|
||||
"data-bs-theme",
|
||||
prefersDarkMode ? "dark" : "light"
|
||||
);
|
||||
} else {
|
||||
rootElement.setAttribute("data-bs-theme", theme);
|
||||
}
|
||||
};
|
||||
|
||||
const ColorScheme = () => {
|
||||
const { savedColorScheme, setSavedColorScheme } = useContext(AppContext);
|
||||
|
||||
setTheme(savedColorScheme);
|
||||
|
||||
const setThemeAndState = (newColorScheme) => {
|
||||
setTheme(newColorScheme);
|
||||
setSavedColorScheme(newColorScheme);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle variant="secondary" style={{ marginRight: "7px" }}>
|
||||
<MoonStarsIcon />
|
||||
</Dropdown.Toggle>
|
||||
|
||||
<Dropdown.Menu>
|
||||
{dropdownOptions.map((option) => (
|
||||
<Dropdown.Item
|
||||
key={option.theme}
|
||||
as={"button"}
|
||||
className={savedColorScheme === option.scheme ? "active" : ""}
|
||||
onClick={() => setThemeAndState(option.scheme)}
|
||||
>
|
||||
<option.icon /> {option.label}
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColorScheme;
|
||||
import React, { useContext } from "react";
|
||||
import { Dropdown } from "react-bootstrap";
|
||||
import { AppContext } from "../Contexts/AppContext";
|
||||
import SunIcon from "../Icons/Sun";
|
||||
import MoonStarsIcon from "../Icons/MoonStars";
|
||||
import CircleHalfIcon from "../Icons/CircleHalf";
|
||||
|
||||
const dropdownOptions = [
|
||||
{ scheme: "light", icon: SunIcon, label: "Light" },
|
||||
{ scheme: "dark", icon: MoonStarsIcon, label: "Dark" },
|
||||
{ scheme: "auto", icon: CircleHalfIcon, label: "Auto" },
|
||||
];
|
||||
|
||||
const setTheme = function (theme) {
|
||||
const rootElement = document.documentElement;
|
||||
const prefersDarkMode = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)"
|
||||
).matches;
|
||||
|
||||
if (theme === "auto") {
|
||||
rootElement.setAttribute(
|
||||
"data-bs-theme",
|
||||
prefersDarkMode ? "dark" : "light"
|
||||
);
|
||||
} else {
|
||||
rootElement.setAttribute("data-bs-theme", theme);
|
||||
}
|
||||
};
|
||||
|
||||
const ColorScheme = () => {
|
||||
const { savedColorScheme, setSavedColorScheme } = useContext(AppContext);
|
||||
|
||||
setTheme(savedColorScheme);
|
||||
|
||||
const setThemeAndState = (newColorScheme) => {
|
||||
setTheme(newColorScheme);
|
||||
setSavedColorScheme(newColorScheme);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle variant="secondary" style={{ marginRight: "7px" }}>
|
||||
<MoonStarsIcon />
|
||||
</Dropdown.Toggle>
|
||||
|
||||
<Dropdown.Menu>
|
||||
{dropdownOptions.map((option) => (
|
||||
<Dropdown.Item
|
||||
key={option.theme}
|
||||
as={"button"}
|
||||
className={savedColorScheme === option.scheme ? "active" : ""}
|
||||
onClick={() => setThemeAndState(option.scheme)}
|
||||
>
|
||||
<option.icon /> {option.label}
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColorScheme;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from "react";
|
||||
|
||||
const CircleHalf = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z" />
|
||||
</svg>
|
||||
);
|
||||
export default CircleHalf;
|
||||
import React from "react";
|
||||
|
||||
const CircleHalf = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z" />
|
||||
</svg>
|
||||
);
|
||||
export default CircleHalf;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React from "react";
|
||||
|
||||
const MoonStars = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z" />
|
||||
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z" />
|
||||
</svg>
|
||||
);
|
||||
export default MoonStars;
|
||||
import React from "react";
|
||||
|
||||
const MoonStars = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z" />
|
||||
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z" />
|
||||
</svg>
|
||||
);
|
||||
export default MoonStars;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from "react";
|
||||
|
||||
const Sun = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z" />
|
||||
</svg>
|
||||
);
|
||||
export default Sun;
|
||||
import React from "react";
|
||||
|
||||
const Sun = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z" />
|
||||
</svg>
|
||||
);
|
||||
export default Sun;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App";
|
||||
|
||||
import "./index.scss";
|
||||
import "bootstrap/dist/js/bootstrap.bundle.min.js";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App";
|
||||
|
||||
import "./index.scss";
|
||||
import "bootstrap/dist/js/bootstrap.bundle.min.js";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
build: {
|
||||
outDir: path.join(__dirname, "build"),
|
||||
sourcemap: false,
|
||||
},
|
||||
server: {
|
||||
open: true,
|
||||
port: 3000,
|
||||
},
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"~bootstrap": path.resolve(__dirname, "node_modules/bootstrap"),
|
||||
},
|
||||
},
|
||||
});
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
build: {
|
||||
outDir: path.join(__dirname, "build"),
|
||||
sourcemap: false,
|
||||
},
|
||||
server: {
|
||||
open: true,
|
||||
port: 3000,
|
||||
},
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"~bootstrap": path.resolve(__dirname, "node_modules/bootstrap"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user