9 Commits

Author SHA1 Message Date
wiredopposite
b9038483ce update to tusb_gamepad lib 2024-05-01 22:13:43 -06:00
wiredopposite
e57de52cc4 new libs 2024-04-24 17:01:51 -06:00
wiredopposite
ee05f9516a use tusb_xinput fork 2024-04-24 16:58:05 -06:00
wiredopposite
a87ed08a63 Update issue templates 2024-04-19 22:19:40 -06:00
wiredopposite
e3acca6d5c add PowerA Enhanced controller 2024-04-19 17:07:27 -06:00
wiredopposite
2c601723f1 update readme 2024-04-17 21:54:00 -06:00
wiredopposite
d6dcbc52a7 update readme 2024-04-17 21:42:59 -06:00
wiredopposite
e210b50c1a update readme 2024-04-17 21:42:05 -06:00
wiredopposite
ae59b5e0c9 update readme 2024-04-17 21:38:43 -06:00
43 changed files with 845 additions and 797 deletions

28
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**What type of controller do you have the issue with?**
Please include the model, even better to include the PID/VID.
You can get the PID and VID like this:
- plug the controller into your computer
- open Device Manager
- right click the controller (probably listed under Human Interface Devices)
- select Properties
- go to the Details tab
- select Hardware IDs from the dropdown menu
It will look like this: HID\VID_046D&PID_C05A
**What platform are you using the OGX-Mini on?**
OG Xbox, PS3, Switch, etc.
**What board are you using?**
Pi Pico, Adafruit Feather, RP2040-Zero...

View File

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Additional context**
Add any other context or screenshots about the feature request here.

8
.gitmodules vendored
View File

@@ -4,9 +4,9 @@
[submodule "lib/tinyusb"] [submodule "lib/tinyusb"]
path = lib/tinyusb path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git url = https://github.com/hathach/tinyusb.git
[submodule "src/usbd"] [submodule "lib/tusb_gamepad"]
path = src/usbd path = lib/tusb_gamepad
url = https://github.com/wiredopposite/usbd.git url = https://github.com/wiredopposite/tusb_gamepad.git
[submodule "lib/tusb_xinput"] [submodule "lib/tusb_xinput"]
path = lib/tusb_xinput path = lib/tusb_xinput
url = https://github.com/Ryzee119/tusb_xinput.git url = https://github.com/wiredopposite/tusb_xinput.git

View File

@@ -1,17 +1,18 @@
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.12)
set(CMAKE_BUILD_TYPE Release)
message("Build type: \"${CMAKE_BUILD_TYPE}\"") message("Build type: \"${CMAKE_BUILD_TYPE}\"")
# Project name
set(NAME OGX-Mini) set(NAME OGX-Mini)
# Board type
set(PICO_BOARD none) set(PICO_BOARD none)
# Fixes that allow some MCH2022 badges with a slowly starting oscillator to boot properly # Fixes that allow some MCH2022 badges with a slowly starting oscillator to boot properly
add_compile_definitions(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H=1 PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) # add_compile_definitions(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H=1 PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64)
# add_compile_options(-Wno-unused-parameter -Wno-unused-variable -Wno-missing-field-initializers -Wno-unused-function)
add_compile_options(-Wno-missing-field-initializers)
# SDK
include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake) include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake)
project(${NAME} C CXX ASM) project(${NAME} C CXX ASM)
@@ -22,66 +23,48 @@ if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif() endif()
set(PICO_PIO_USB_PATH "${CMAKE_CURRENT_LIST_DIR}/lib/Pico-PIO-USB") set(ROOT ${CMAKE_CURRENT_LIST_DIR})
set(PICO_TINYUSB_PATH "${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb")
set(TUSB_XINPUT_PATH "${CMAKE_CURRENT_LIST_DIR}/lib/tusb_xinput") set(PICO_PIO_USB_PATH ${ROOT}/lib/Pico-PIO-USB)
add_subdirectory(${TUSB_XINPUT_PATH} xinput_host) set(PICO_TINYUSB_PATH ${ROOT}/lib/tinyusb)
set(TUSB_GAMEPAD_PATH ${ROOT}/lib/tusb_gamepad)
set(XINPUT_HOST_PATH ${ROOT}/lib/tusb_xinput)
pico_sdk_init() pico_sdk_init()
add_subdirectory(lib/Pico-PIO-USB) # add_subdirectory(${ROOT}/lib)
add_subdirectory(lib) add_subdirectory(${ROOT}/lib/CRC32 CRC32)
add_subdirectory(${XINPUT_HOST_PATH} xinput_host)
add_subdirectory(${PICO_PIO_USB_PATH})
add_subdirectory(${TUSB_GAMEPAD_PATH})
target_include_directories(tusb_gamepad PRIVATE ${ROOT}/src) # so tusb_gamepad can see tusb_config.h
set(SRC_DIR ${ROOT}/src)
file(GLOB_RECURSE SOURCES file(GLOB_RECURSE SOURCES
"src/main.cpp" ${SRC_DIR}/main.cpp
"src/input_mode.cpp" ${SRC_DIR}/input_mode.cpp
"src/Gamepad.cpp"
"src/utilities/log.cpp" ${SRC_DIR}/usbh/tusb_host_manager.cpp
${SRC_DIR}/usbh/tusb_host.cpp
"src/usbh/tusb_host_manager.cpp" ${SRC_DIR}/usbh/n64usb/N64USB.cpp
"src/usbh/tusb_host.cpp" ${SRC_DIR}/usbh/ps3/Dualshock3.cpp
"src/usbh/n64usb/N64USB.cpp" ${SRC_DIR}/usbh/ps3/DInput.cpp
"src/usbh/ps3/Dualshock3.cpp" ${SRC_DIR}/usbh/ps4/Dualshock4.cpp
"src/usbh/ps3/DInput.cpp" ${SRC_DIR}/usbh/ps5/Dualsense.cpp
"src/usbh/ps4/Dualshock4.cpp" ${SRC_DIR}/usbh/psclassic/PSClassic.cpp
"src/usbh/ps5/Dualsense.cpp" ${SRC_DIR}/usbh/switch/SwitchPro.cpp
"src/usbh/psclassic/PSClassic.cpp" ${SRC_DIR}/usbh/switch/SwitchWired.cpp
"src/usbh/switch/SwitchPro.cpp" ${SRC_DIR}/usbh/xinput/XInput.cpp
"src/usbh/switch/SwitchWired.cpp" ${SRC_DIR}/usbh/shared/hid_class_driver.c
"src/usbh/xinput/XInput.cpp" ${SRC_DIR}/usbh/shared/scaling.cpp
"src/usbh/shared/hid_class_driver.c"
"src/usbh/shared/scaling.cpp"
"src/usbd/usbdriver.cpp"
"src/usbd/drivermanager.cpp"
"src/usbd/drivers/shared/driverhelper.h"
"src/usbd/drivers/shared/scaling.cpp"
"src/usbd/drivers/dinput/DInputDriver.cpp"
# "src/usbd/drivers/hid/HIDDriver.cpp"
# "src/usbd/drivers/ps3/PS3Driver.cpp"
"src/usbd/drivers/psclassic/PSClassicDriver.cpp"
"src/usbd/drivers/switch/SwitchDriver.cpp"
"src/usbd/drivers/usbserial/USBSerialDriver.cpp"
"src/usbd/drivers/xinput/XInputDriver.cpp"
"src/usbd/drivers/xboxog/XboxOriginalDriver.cpp"
"src/usbd/drivers/xboxog/xid/xid.c"
"src/usbd/drivers/xboxog/xid/xid_driver.c"
"src/usbd/drivers/xboxog/xid/xid_gamepad.c"
"src/usbd/drivers/xboxog/xid/xid_remote.c"
"src/usbd/drivers/xboxog/xid/xid_steelbattalion.c"
) )
# Firmware # Firmware
add_executable(${NAME} add_executable(${NAME} ${SOURCES})
${SOURCES}
)
target_include_directories(${NAME} PUBLIC target_include_directories(${NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/lib) ${ROOT}/src
${ROOT}/lib)
include_directories(
lib/)
target_link_libraries(${NAME} target_link_libraries(${NAME}
pico_stdlib pico_stdlib
@@ -102,6 +85,7 @@ target_link_libraries(${NAME}
CRC32 CRC32
cmsis_core cmsis_core
xinput_host xinput_host
tusb_gamepad
) )
pico_add_extra_outputs(${NAME}) pico_add_extra_outputs(${NAME})

View File

@@ -1,40 +0,0 @@
# Copyright (c) 2022 Nicolai Electronics
# SPDX-License-Identifier: MIT
INSTALL_PREFIX := $PWD
BUILD_DIR := build
GENERATED_DIR := generated
.PHONY: all firmware flash clean install_rules $(BUILD_DIR) format
all: build flash
@echo "All tasks completed"
build:
mkdir -p $(BUILD_DIR)
mkdir -p $(GENERATED_DIR)
cd $(BUILD_DIR); cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX -DCMAKE_BUILD_TYPE=Release ..
$(MAKE) -C $(BUILD_DIR) --no-print-directory all
debug:
mkdir -p $(BUILD_DIR)
mkdir -p $(GENERATED_DIR)
cd $(BUILD_DIR); cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX -DCMAKE_BUILD_TYPE=Debug ..
$(MAKE) -C $(BUILD_DIR) --no-print-directory all
flash:
picotool load $(BUILD_DIR)/i2c_adapter.bin
picotool reboot
clean:
rm -rf $(BUILD_DIR)
rm -rf $(GENERATED_DIR)
install_rules:
cp tools/99-pico.rules /etc/udev/rules.d/
@echo "reload rules with:"
@echo "\tudevadm control --reload-rules"
@echo "\tudevadm trigger"
format:
find . -iname '*.h' -o -iname '*.c' -o -iname '*.cpp' | grep -v '$(BUILD_DIR)' | xargs clang-format -i

View File

@@ -49,7 +49,7 @@ Start + A (Cross for PlayStation and B for Switch gamepads)
After a new mode is stored, the RP2040 will reset itself so you don't need to unplug it. After a new mode is stored, the RP2040 will reset itself so you don't need to unplug it.
## Hardware ## Hardware
I've created an interposer board for the RP2040-Zero so you can make a small form-factor adapter yourself. The gerber files, schematic, and BOM are in Hardware folder. I've designed a PCB for the RP2040-Zero so you can make a small form-factor adapter yourself. The gerber files, schematic, and BOM are in Hardware folder.
![OGX-Mini Boards](images/OGX-Mini-rpzero-int.jpg "OGX-Mini Boards") ![OGX-Mini Boards](images/OGX-Mini-rpzero-int.jpg "OGX-Mini Boards")
@@ -65,7 +65,7 @@ For the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723)
If your third party controller isn't working, but the original version is listed above, send me the device's VID and PID and I'll add it so it's recognized properly. If your third party controller isn't working, but the original version is listed above, send me the device's VID and PID and I'll add it so it's recognized properly.
## Compiling ## Compiling
You can compile this for different boards by changing USBD_BOARD in the usbd_config.h file, you can also adjust USBD_MAX_GAMEPADS to enable more controllers on Switch and PlayStation 3. You can compile this for different boards by changing USBD_BOARD in the usbd_config.h file, you can also adjust USBD_MAX_GAMEPADS to enable more controllers on PlayStation 3 (this is experimental).
Choosing OGXM_PI_PICO will set the D+ and D- host pins to GPIO 0 and 1. Choosing OGXM_PI_PICO will set the D+ and D- host pins to GPIO 0 and 1.

View File

@@ -1,3 +1,5 @@
Gerber, BOM, and schematic for an RP2040-Zero interposer board you can make yourself. LED1 and R3 are both optional. Gerber, BOM, and schematic for an RP2040-Zero interposer board you can make yourself. LED1 and R3 are both optional.
The RP2040-Zero board can be found on Amazon and AliExpress. The RP2040-Zero board can be found on Amazon and AliExpress.
![OGX-Mini Boards](../images/OGX-Mini-rpzero-int.jpg "OGX-Mini Boards")

1
lib/tusb_gamepad Submodule

Submodule lib/tusb_gamepad added at 5e5ee00ee8

View File

@@ -1,62 +0,0 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})

View File

@@ -1,39 +0,0 @@
#include "Gamepad.h"
#include "usbd/board_config.h"
void Gamepad::reset_pad()
{
buttons.up = buttons.down = buttons.left = buttons.right = false;
buttons.a = buttons.b = buttons.x = buttons.y = false;
buttons.l3 = buttons.r3 = buttons.back = buttons.start = false;
buttons.rb = buttons.lb = buttons.sys = buttons.misc = false;
triggers.l = triggers.r = 0;
joysticks.lx = joysticks.ly = joysticks.rx = joysticks.ry = 0;
}
void Gamepad::reset_rumble()
{
rumble.r = rumble.l = 0;
}
void Gamepad::reset_hid_rumble()
{
if (rumble.l != UINT8_MAX)
{
rumble.l = 0;
}
if (rumble.r != UINT8_MAX)
{
rumble.r = 0;
}
}
Gamepad& gamepad(int idx)
{
static Gamepad gamepad[MAX_GAMEPADS];
return gamepad[idx];
}

View File

@@ -1,71 +0,0 @@
#pragma once
#ifndef _GAMEPAD_H_
#define _GAMEPAD_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <cstdint>
struct GamepadButtons
{
bool up {false};
bool down {false};
bool left {false};
bool right {false};
bool a {false};
bool b {false};
bool x {false};
bool y {false};
bool l3 {false};
bool r3 {false};
bool back {false};
bool start {false};
bool rb {false};
bool lb {false};
bool sys {false};
bool misc {false};
};
struct GamepadTriggers
{
uint8_t l {0};
uint8_t r {0};
};
struct GamepadJoysticks
{
int16_t lx {0};
int16_t ly {0};
int16_t rx {0};
int16_t ry {0};
};
struct GamepadRumble
{
uint8_t l {0};
uint8_t r {0};
};
class Gamepad
{
public:
GamepadButtons buttons;
GamepadTriggers triggers;
GamepadJoysticks joysticks;
GamepadRumble rumble;
void reset_pad();
void reset_rumble();
void reset_hid_rumble();
};
Gamepad& gamepad(int idx);
#ifdef __cplusplus
}
#endif
#endif // _GAMEPAD_H_

View File

@@ -6,7 +6,6 @@
#include "tusb.h" #include "tusb.h"
#include "usbd/board_config.h"
#include "input_mode.h" #include "input_mode.h"
#define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) // Address of the AIRCR register #define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) // Address of the AIRCR register
@@ -16,6 +15,8 @@
#define FLASH_TARGET_OFFSET (256 * 1024) #define FLASH_TARGET_OFFSET (256 * 1024)
#define FLASH_SIZE_BYTES (2 * 1024 * 1024) #define FLASH_SIZE_BYTES (2 * 1024 * 1024)
InputMode current_input_mode;
void system_reset() void system_reset()
{ {
AIRCR_REG = AIRCR_VECTKEY | AIRCR_SYSRESETREQ; AIRCR_REG = AIRCR_VECTKEY | AIRCR_SYSRESETREQ;
@@ -54,7 +55,7 @@ bool change_input_mode(GamepadButtons buttons)
return false; return false;
} }
InputMode new_mode; InputMode new_mode = current_input_mode;
if (buttons.up) if (buttons.up)
{ {
@@ -62,7 +63,7 @@ bool change_input_mode(GamepadButtons buttons)
} }
else if (buttons.left) else if (buttons.left)
{ {
new_mode = INPUT_MODE_HID; new_mode = INPUT_MODE_DINPUT;
} }
else if (buttons.right) else if (buttons.right)
{ {
@@ -104,22 +105,24 @@ enum InputMode get_input_mode()
const uint8_t *stored_value = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE); const uint8_t *stored_value = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
#if (MAX_GAMEPADS < 1) #if (MAX_GAMEPADS < 1)
if ((*stored_value == INPUT_MODE_HID) || (*stored_value == INPUT_MODE_SWITCH)) if ((*stored_value == INPUT_MODE_DINPUT) || (*stored_value == INPUT_MODE_SWITCH))
{ {
return(enum InputMode)*stored_value; current_input_mode = (enum InputMode)*stored_value;
} }
else else
{ {
return INPUT_MODE_HID; current_input_mode = INPUT_MODE_DINPUT;
} }
#else #else
if (*stored_value >= INPUT_MODE_XINPUT && *stored_value <= INPUT_MODE_XBOXORIGINAL) if (*stored_value >= INPUT_MODE_XINPUT && *stored_value <= INPUT_MODE_XBOXORIGINAL)
{ {
return(enum InputMode)*stored_value; current_input_mode = (enum InputMode)*stored_value;
} }
else else
{ {
return INPUT_MODE_XBOXORIGINAL; current_input_mode = INPUT_MODE_XBOXORIGINAL;
} }
#endif #endif
return current_input_mode;
} }

View File

@@ -5,8 +5,7 @@
extern "C" { extern "C" {
#endif #endif
#include "Gamepad.h" #include "tusb_gamepad.h"
#include "usbd/inputmodes.h"
enum InputMode get_input_mode(); enum InputMode get_input_mode();
bool change_input_mode(GamepadButtons buttons); bool change_input_mode(GamepadButtons buttons);

View File

@@ -6,13 +6,12 @@
#include "tusb.h" #include "tusb.h"
#include "bsp/board_api.h" #include "bsp/board_api.h"
#include "tusb_gamepad.h"
#include "drivermanager.h"
#include "drivers/gpdriver.h"
#include "usbh/tusb_host.h" #include "usbh/tusb_host.h"
#include "usbd/drivermanager.h"
#include "usbd/drivers/gpdriver.h"
#include "Gamepad.h"
#include "input_mode.h" #include "input_mode.h"
#include "usbd/board_config.h"
int main(void) int main(void)
{ {
@@ -29,7 +28,7 @@ int main(void)
multicore_reset_core1(); multicore_reset_core1();
multicore_launch_core1(usbh_main); multicore_launch_core1(usbh_main);
GamepadButtons prev_gamepad_buttons = gamepad(0).buttons; GamepadButtons prev_gamepad_buttons = gamepad(0)->buttons;
absolute_time_t last_time_gamepad_changed = get_absolute_time(); absolute_time_t last_time_gamepad_changed = get_absolute_time();
absolute_time_t last_time_gamepad_checked = get_absolute_time(); absolute_time_t last_time_gamepad_checked = get_absolute_time();
@@ -39,16 +38,16 @@ int main(void)
{ {
uint8_t outBuffer[64]; uint8_t outBuffer[64];
GPDriver* driver = driverManager.getDriver(); GPDriver* driver = driverManager.getDriver();
driver->process(i, &gamepad(i), outBuffer); driver->process(i, gamepad(i), outBuffer);
driver->update_rumble(i, &gamepad(i)); driver->update_rumble(i, gamepad(i));
} }
if (absolute_time_diff_us(last_time_gamepad_checked, get_absolute_time()) >= 500000) if (absolute_time_diff_us(last_time_gamepad_checked, get_absolute_time()) >= 500000)
{ {
// check if digital buttons have changed // check if digital buttons have changed
if (memcmp(&gamepad(0).buttons, &prev_gamepad_buttons, sizeof(GamepadButtons)) != 0) if (memcmp(&gamepad(0)->buttons, &prev_gamepad_buttons, sizeof(GamepadButtons)) != 0)
{ {
memcpy(&prev_gamepad_buttons, &gamepad(0).buttons, sizeof(GamepadButtons)); memcpy(&prev_gamepad_buttons, &gamepad(0)->buttons, sizeof(GamepadButtons));
last_time_gamepad_changed = get_absolute_time(); last_time_gamepad_changed = get_absolute_time();
} }
// haven't changed for 3 seconds // haven't changed for 3 seconds

39
src/ogxm_config.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef _OGXM_CONFIG_H_
#define _OGXM_CONFIG_H_
#define ADAFRUIT_FEATHER_USBH 1
#define PI_PICO 2
#define RP2040_ZERO_INTERPOSER 3
// Options //
#define OGXM_BOARD ADAFRUIT_FEATHER_USBH
#define CDC_DEBUG 0
// ------- //
#if OGXM_BOARD == ADAFRUIT_FEATHER_USBH
#define PIO_USB_DP_PIN 16 // DM = 17
#define LED_INDICATOR_PIN 13
#define VCC_EN_PIN 18
// #define NEOPIXEL_PWR_PIN 20
// #define NEOPIXEL_CTRL_PIN 21
#elif OGXM_BOARD == PI_PICO
#define PIO_USB_DP_PIN 0 // DM = 1
#define LED_INDICATOR_PIN 25
#elif OGXM_BOARD == RP2040_ZERO_INTERPOSER
#define PIO_USB_DP_PIN 10 // DM = 11
#define LED_INDICATOR_PIN 13
#endif
#ifndef OGXM_BOARD
#error OGXM_BOARD must be defined in ogxm_config.h
#endif
#ifndef CDC_DEBUG
#define CDC_DEBUG 0
#endif
#endif // _OGXM_CONFIG_H_

View File

@@ -26,7 +26,9 @@
#ifndef _TUSB_CONFIG_H_ #ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_ #define _TUSB_CONFIG_H_
#include "usbd/board_config.h" #include "board_config.h"
#define MAX_GAMEPADS 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -89,7 +91,7 @@
#define CFG_TUD_ENABLED 1 #define CFG_TUD_ENABLED 1
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build // CFG_TUSB_DEBUG is defined by compiler in DEBUG build
// #define CFG_TUSB_DEBUG 1 #define CFG_TUSB_DEBUG 0
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put * Tinyusb use follows macros to declare transferring memory so that they can be put
@@ -128,7 +130,7 @@
//-------------------------------------------------------------------- //--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE #ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64 #define CFG_TUD_ENDPOINT0_SIZE 64
#endif #endif
#define CFG_TUD_CDC_RX_BUFSIZE 256 #define CFG_TUD_CDC_RX_BUFSIZE 256

Submodule src/usbd deleted from f7bdb97a37

View File

@@ -1,19 +0,0 @@
#ifndef USBD_CONFIG_H_
#define USBD_CONFIG_H_
#include "usbd/usbd_boards.h"
// Boards
// OGXM_PI_PICO
// OGXM_ADA_FEATHER_USBH
// OGXM_RPZERO_INTERPOSER
// OGXW_RETAIL_1CH
// OGXW_RPZERO_1CH
// OGXW_RPZERO_2CH
// OGXW_LITE
#define USBD_BOARD OGXM_RPZERO_INTERPOSER
#define USBD_MAX_GAMEPADS 1 // This is set by idf.py menuconfig for wireless boards, number here is ignored in that case.
#define CDC_DEBUG 0 // Set to 1 for CDC device, helpful for debugging USB host. Include utilities/log.h and use log() as you would printf()
#endif // USBD_CONFIG_H_

View File

@@ -3,19 +3,21 @@
#include <stdint.h> #include <stdint.h>
#include "host/usbh.h" // needed so xinput_host will build #include "host/usbh.h" // needed so xinput_host will build
#include "xinput_host.h"
#include "tusb_gamepad.h"
#include "usbh/shared/shared.h" #include "usbh/shared/shared.h"
#include "xinput_host.h"
#include "Gamepad.h"
class GPHostDriver class GPHostDriver
{ {
public: public:
virtual ~GPHostDriver() = default;
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) = 0; virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) = 0;
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) = 0; virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) = 0;
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) = 0; virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) = 0;
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) = 0; virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) = 0;
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) = 0; virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance) = 0;
}; };
#endif // _GPHOSTDRIVER_H_ #endif // _GPHOSTDRIVER_H_

View File

@@ -11,64 +11,66 @@ void N64USB::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void N64USB::update_gamepad(Gamepad& gamepad, const N64USBReport* n64_data) void N64USB::update_gamepad(Gamepad* gamepad, const N64USBReport* n64_data)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
uint8_t n64_dpad = n64_data->buttons & N64_DPAD_MASK; uint8_t n64_dpad = n64_data->buttons & N64_DPAD_MASK;
switch(n64_dpad) switch(n64_dpad)
{ {
case N64_DPAD_MASK_UP: case N64_DPAD_MASK_UP:
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
case N64_DPAD_MASK_UP_RIGHT: case N64_DPAD_MASK_UP_RIGHT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case N64_DPAD_MASK_RIGHT: case N64_DPAD_MASK_RIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case N64_DPAD_MASK_RIGHT_DOWN: case N64_DPAD_MASK_RIGHT_DOWN:
gamepad.buttons.right = true; gamepad->buttons.right = true;
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case N64_DPAD_MASK_DOWN: case N64_DPAD_MASK_DOWN:
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case N64_DPAD_MASK_DOWN_LEFT: case N64_DPAD_MASK_DOWN_LEFT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case N64_DPAD_MASK_LEFT: case N64_DPAD_MASK_LEFT:
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case N64_DPAD_MASK_LEFT_UP: case N64_DPAD_MASK_LEFT_UP:
gamepad.buttons.left = true; gamepad->buttons.left = true;
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
} }
if (n64_data->buttons & N64_C_UP_MASK) gamepad.joysticks.ry = INT16_MAX; if (n64_data->buttons & N64_C_UP_MASK) gamepad->joysticks.ry = INT16_MAX;
if (n64_data->buttons & N64_C_DOWN_MASK) gamepad.joysticks.ry = INT16_MIN; if (n64_data->buttons & N64_C_DOWN_MASK) gamepad->joysticks.ry = INT16_MIN;
if (n64_data->buttons & N64_C_LEFT_MASK) gamepad.joysticks.rx = INT16_MIN; if (n64_data->buttons & N64_C_LEFT_MASK) gamepad->joysticks.rx = INT16_MIN;
if (n64_data->buttons & N64_C_RIGHT_MASK) gamepad.joysticks.rx = INT16_MAX; if (n64_data->buttons & N64_C_RIGHT_MASK) gamepad->joysticks.rx = INT16_MAX;
if (n64_data->buttons & N64_A_MASK) gamepad.buttons.a = true; if (n64_data->buttons & N64_A_MASK) gamepad->buttons.a = true;
if (n64_data->buttons & N64_B_MASK) gamepad.buttons.b = true; if (n64_data->buttons & N64_B_MASK) gamepad->buttons.b = true;
if (n64_data->buttons & N64_START_MASK) gamepad.buttons.start = true; if (n64_data->buttons & N64_START_MASK) gamepad->buttons.start = true;
if (n64_data->buttons & N64_L_MASK) gamepad.buttons.lb = true; if (n64_data->buttons & N64_L_MASK) gamepad->buttons.lb = true;
if (n64_data->buttons & N64_R_MASK) gamepad.buttons.rb = true; if (n64_data->buttons & N64_R_MASK) gamepad->buttons.rb = true;
if (n64_data->buttons & N64_Z_MASK) gamepad.triggers.r = 0xFF; if (n64_data->buttons & N64_Z_MASK) gamepad->triggers.r = 0xFF;
gamepad.joysticks.ly = scale_uint8_to_int16(n64_data->y, true); gamepad->joysticks.ly = scale_uint8_to_int16(n64_data->y, true);
gamepad.joysticks.lx = scale_uint8_to_int16(n64_data->x, false); gamepad->joysticks.lx = scale_uint8_to_int16(n64_data->x, false);
} }
void N64USB::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void N64USB::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
static N64USBReport prev_report = { 0 }; (void)len;
static N64USBReport prev_report = {};
N64USBReport n64_report; N64USBReport n64_report;
memcpy(&n64_report, report, sizeof(n64_report)); memcpy(&n64_report, report, sizeof(n64_report));
@@ -83,11 +85,29 @@ void N64USB::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t inst
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void N64USB::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void N64USB::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
void N64USB::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {}
bool N64USB::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{ {
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void N64USB::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool N64USB::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{
(void)gamepad;
(void)dev_addr;
(void)instance;
return true; return true;
} }

View File

@@ -1,5 +1,3 @@
#pragma once
#ifndef _N64USB_H_ #ifndef _N64USB_H_
#define _N64USB_H_ #define _N64USB_H_
@@ -54,14 +52,16 @@ struct N64USBState
class N64USB: public GPHostDriver class N64USB: public GPHostDriver
{ {
public: public:
~N64USB() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
N64USBState n64usb; N64USBState n64usb;
void update_gamepad(Gamepad& gp, const N64USBReport* n64_data); void update_gamepad(Gamepad* gp, const N64USBReport* n64_data);
}; };
#endif // _N64USB_H_ #endif // _N64USB_H_

View File

@@ -13,84 +13,99 @@ void DInput::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void DInput::update_gamepad(Gamepad& gamepad, const DInputReport* dinput_report) void DInput::update_gamepad(Gamepad* gamepad, const DInputReport* dinput_report)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
switch (dinput_report->direction) switch (dinput_report->direction)
{ {
case DINPUT_HAT_UP: case DINPUT_HAT_UP:
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
case DINPUT_HAT_UPRIGHT: case DINPUT_HAT_UPRIGHT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case DINPUT_HAT_RIGHT: case DINPUT_HAT_RIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case DINPUT_HAT_DOWNRIGHT: case DINPUT_HAT_DOWNRIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case DINPUT_HAT_DOWN: case DINPUT_HAT_DOWN:
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case DINPUT_HAT_DOWNLEFT: case DINPUT_HAT_DOWNLEFT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case DINPUT_HAT_LEFT: case DINPUT_HAT_LEFT:
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case DINPUT_HAT_UPLEFT: case DINPUT_HAT_UPLEFT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
} }
if (dinput_report->square_btn) gamepad.buttons.x = true; if (dinput_report->square_btn) gamepad->buttons.x = true;
if (dinput_report->triangle_btn) gamepad.buttons.y = true; if (dinput_report->triangle_btn) gamepad->buttons.y = true;
if (dinput_report->cross_btn) gamepad.buttons.a = true; if (dinput_report->cross_btn) gamepad->buttons.a = true;
if (dinput_report->circle_btn) gamepad.buttons.b = true; if (dinput_report->circle_btn) gamepad->buttons.b = true;
if (dinput_report->select_btn) gamepad.buttons.back = true; if (dinput_report->select_btn) gamepad->buttons.back = true;
if (dinput_report->start_btn) gamepad.buttons.start = true; if (dinput_report->start_btn) gamepad->buttons.start = true;
if (dinput_report->ps_btn) gamepad.buttons.sys = true; if (dinput_report->ps_btn) gamepad->buttons.sys = true;
if (dinput_report->l3_btn) gamepad.buttons.l3 = true; if (dinput_report->l3_btn) gamepad->buttons.l3 = true;
if (dinput_report->r3_btn) gamepad.buttons.r3 = true; if (dinput_report->r3_btn) gamepad->buttons.r3 = true;
if (dinput_report->l1_btn) gamepad.buttons.lb = true; if (dinput_report->l1_btn) gamepad->buttons.lb = true;
if (dinput_report->r1_btn) gamepad.buttons.rb = true; if (dinput_report->r1_btn) gamepad->buttons.rb = true;
if (dinput_report->l2_axis > 0) if (dinput_report->l2_axis > 0)
{ {
gamepad.triggers.l = dinput_report->l2_axis; gamepad->triggers.l = dinput_report->l2_axis;
} }
else if (dinput_report->l2_btn) else if (dinput_report->l2_btn)
{ {
gamepad.triggers.l = 0xFF; gamepad->triggers.l = 0xFF;
} }
if (dinput_report->r2_axis > 0) if (dinput_report->r2_axis > 0)
{ {
gamepad.triggers.r = dinput_report->r2_axis; gamepad->triggers.r = dinput_report->r2_axis;
} }
else if (dinput_report->r2_btn) else if (dinput_report->r2_btn)
{ {
gamepad.triggers.r = 0xFF; gamepad->triggers.r = 0xFF;
} }
gamepad.joysticks.lx = scale_uint8_to_int16(dinput_report->l_x_axis, false); gamepad->analog_buttons.up = dinput_report->up_axis;
gamepad.joysticks.ly = scale_uint8_to_int16(dinput_report->l_y_axis, true); gamepad->analog_buttons.down = dinput_report->down_axis;
gamepad.joysticks.rx = scale_uint8_to_int16(dinput_report->r_x_axis, false); gamepad->analog_buttons.left = dinput_report->left_axis;
gamepad.joysticks.ry = scale_uint8_to_int16(dinput_report->r_y_axis, true); gamepad->analog_buttons.right = dinput_report->right_axis;
gamepad->analog_buttons.x = dinput_report->square_axis;
gamepad->analog_buttons.y = dinput_report->triangle_axis;
gamepad->analog_buttons.a = dinput_report->cross_axis;
gamepad->analog_buttons.b = dinput_report->circle_axis;
gamepad->analog_buttons.lb = dinput_report->l1_axis;
gamepad->analog_buttons.rb = dinput_report->r1_axis;
gamepad->joysticks.lx = scale_uint8_to_int16(dinput_report->l_x_axis, false);
gamepad->joysticks.ly = scale_uint8_to_int16(dinput_report->l_y_axis, true);
gamepad->joysticks.rx = scale_uint8_to_int16(dinput_report->r_x_axis, false);
gamepad->joysticks.ry = scale_uint8_to_int16(dinput_report->r_y_axis, true);
} }
void DInput::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void DInput::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
static DInputReport prev_report = {0}; (void)len;
static DInputReport prev_report = {};
DInputReport dinput_report; DInputReport dinput_report;
memcpy(&dinput_report, report, sizeof(dinput_report)); memcpy(&dinput_report, report, sizeof(dinput_report));
@@ -103,11 +118,29 @@ void DInput::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t inst
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void DInput::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void DInput::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
void DInput::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {}
bool DInput::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{ {
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void DInput::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool DInput::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{
(void)gamepad;
(void)dev_addr;
(void)instance;
return true; return true;
} }

View File

@@ -2,9 +2,9 @@
#define _DINPUT_H_ #define _DINPUT_H_
#include <stdint.h> #include <stdint.h>
#include "descriptors/DInputDescriptors.h"
#include "usbh/GPHostDriver.h" #include "usbh/GPHostDriver.h"
#include "usbd/descriptors/DInputDescriptors.h"
const usb_vid_pid_t dinput_devices[] = const usb_vid_pid_t dinput_devices[] =
{ {
@@ -23,14 +23,16 @@ struct DInputState
class DInput : public GPHostDriver class DInput : public GPHostDriver
{ {
public: public:
~DInput() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
DInputState dinput; DInputState dinput;
void update_gamepad(Gamepad& gp, const DInputReport* dinput_report); void update_gamepad(Gamepad* gp, const DInputReport* dinput_report);
}; };
#endif // _DINPUT_H_ #endif // _DINPUT_H_

View File

@@ -4,7 +4,6 @@
#include "class/hid/hid_host.h" #include "class/hid/hid_host.h"
#include "usbh/ps3/Dualshock3.h" #include "usbh/ps3/Dualshock3.h"
#include "usbh/shared/scaling.h" #include "usbh/shared/scaling.h"
void Dualshock3::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) void Dualshock3::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
@@ -148,6 +147,11 @@ void Dualshock3::get_report_complete_cb(uint8_t dev_addr, uint8_t instance)
void Dualshock3::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) void Dualshock3::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{ {
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
// if (dualshock3.response_count == 0) // if (dualshock3.response_count == 0)
// { // {
// if (tuh_hid_get_report(dev_addr, instance, 0xF2, HID_REPORT_TYPE_FEATURE, &dualshock3.en_buffer, 17)) // if (tuh_hid_get_report(dev_addr, instance, 0xF2, HID_REPORT_TYPE_FEATURE, &dualshock3.en_buffer, 17))
@@ -209,42 +213,57 @@ void Dualshock3::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance,
// } // }
} }
void Dualshock3::update_gamepad(Gamepad& gamepad, const Dualshock3Report* ds3_data) void Dualshock3::update_gamepad(Gamepad* gamepad, const Dualshock3Report* ds3_data)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
if (ds3_data->up) gamepad.buttons.up =true; if (ds3_data->up) gamepad->buttons.up =true;
if (ds3_data->down) gamepad.buttons.down =true; if (ds3_data->down) gamepad->buttons.down =true;
if (ds3_data->left) gamepad.buttons.left =true; if (ds3_data->left) gamepad->buttons.left =true;
if (ds3_data->right) gamepad.buttons.right =true; if (ds3_data->right) gamepad->buttons.right =true;
if (ds3_data->square) gamepad.buttons.x = true; if (ds3_data->square) gamepad->buttons.x = true;
if (ds3_data->triangle) gamepad.buttons.y = true; if (ds3_data->triangle) gamepad->buttons.y = true;
if (ds3_data->cross) gamepad.buttons.a = true; if (ds3_data->cross) gamepad->buttons.a = true;
if (ds3_data->circle) gamepad.buttons.b = true; if (ds3_data->circle) gamepad->buttons.b = true;
if (ds3_data->select) gamepad.buttons.back = true; if (ds3_data->select) gamepad->buttons.back = true;
if (ds3_data->start) gamepad.buttons.start = true; if (ds3_data->start) gamepad->buttons.start = true;
if (ds3_data->ps) gamepad.buttons.sys = true; if (ds3_data->ps) gamepad->buttons.sys = true;
if (ds3_data->l3) gamepad.buttons.l3 = true; if (ds3_data->l3) gamepad->buttons.l3 = true;
if (ds3_data->r3) gamepad.buttons.r3 = true; if (ds3_data->r3) gamepad->buttons.r3 = true;
if (ds3_data->l1) gamepad.buttons.lb = true; if (ds3_data->l1) gamepad->buttons.lb = true;
if (ds3_data->r1) gamepad.buttons.rb = true; if (ds3_data->r1) gamepad->buttons.rb = true;
gamepad.triggers.l = ds3_data->l2_axis; gamepad->analog_buttons.up = ds3_data->up_axis;
gamepad.triggers.r = ds3_data->r2_axis; gamepad->analog_buttons.down = ds3_data->down_axis;
gamepad->analog_buttons.left = ds3_data->left_axis;
gamepad->analog_buttons.right = ds3_data->right_axis;
gamepad.joysticks.lx = scale_uint8_to_int16(ds3_data->left_x, false); gamepad->analog_buttons.x = ds3_data->square_axis;
gamepad.joysticks.ly = scale_uint8_to_int16(ds3_data->left_y, true); gamepad->analog_buttons.y = ds3_data->triangle_axis;
gamepad.joysticks.rx = scale_uint8_to_int16(ds3_data->right_x, false); gamepad->analog_buttons.a = ds3_data->cross_axis;
gamepad.joysticks.ry = scale_uint8_to_int16(ds3_data->right_y, true); gamepad->analog_buttons.b = ds3_data->circle_axis;
gamepad->analog_buttons.lb = ds3_data->l1_axis;
gamepad->analog_buttons.rb = ds3_data->r1_axis;
gamepad->triggers.l = ds3_data->l2_axis;
gamepad->triggers.r = ds3_data->r2_axis;
gamepad->joysticks.lx = scale_uint8_to_int16(ds3_data->left_x, false);
gamepad->joysticks.ly = scale_uint8_to_int16(ds3_data->left_y, true);
gamepad->joysticks.rx = scale_uint8_to_int16(ds3_data->right_x, false);
gamepad->joysticks.ry = scale_uint8_to_int16(ds3_data->right_y, true);
} }
void Dualshock3::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void Dualshock3::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
static Dualshock3Report prev_report = { 0 }; (void)len;
static Dualshock3Report prev_report = {};
Dualshock3Report ds3_report; Dualshock3Report ds3_report;
memcpy(&ds3_report, report, sizeof(ds3_report)); memcpy(&ds3_report, report, sizeof(ds3_report));
@@ -257,10 +276,19 @@ void Dualshock3::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void Dualshock3::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void Dualshock3::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
bool Dualshock3::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{ {
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
bool Dualshock3::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{
(void)instance;
static absolute_time_t next_allowed_time = {0}; static absolute_time_t next_allowed_time = {0};
absolute_time_t current_time = get_absolute_time(); absolute_time_t current_time = get_absolute_time();
@@ -269,13 +297,13 @@ bool Dualshock3::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t
return false; return false;
} }
dualshock3.out_report.rumble.right_duration = (gamepad.rumble.r > 0) ? 20: 0; dualshock3.out_report.rumble.right_duration = (gamepad->rumble.r > 0) ? 20: 0;
dualshock3.out_report.rumble.right_motor_on = (gamepad.rumble.r > 0) ? 1 : 0; dualshock3.out_report.rumble.right_motor_on = (gamepad->rumble.r > 0) ? 1 : 0;
dualshock3.out_report.rumble.left_duration = (gamepad.rumble.l > 0) ? 20 : 0; dualshock3.out_report.rumble.left_duration = (gamepad->rumble.l > 0) ? 20 : 0;
dualshock3.out_report.rumble.left_motor_force = gamepad.rumble.l; dualshock3.out_report.rumble.left_motor_force = gamepad->rumble.l;
if (gamepad.rumble.l > 0 || gamepad.rumble.r > 0 || if (gamepad->rumble.l > 0 || gamepad->rumble.r > 0 ||
absolute_time_diff_us(current_time, next_allowed_time) < 0) absolute_time_diff_us(current_time, next_allowed_time) < 0)
{ {
tusb_control_request_t setup_packet = tusb_control_request_t setup_packet =
@@ -299,7 +327,7 @@ bool Dualshock3::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t
if (tuh_control_xfer(&transfer)) if (tuh_control_xfer(&transfer))
{ {
if (gamepad.rumble.l == 0 && gamepad.rumble.r == 0) if (gamepad->rumble.l == 0 && gamepad->rumble.r == 0)
{ {
next_allowed_time = delayed_by_us(get_absolute_time(), 500000); next_allowed_time = delayed_by_us(get_absolute_time(), 500000);
} }

View File

@@ -1,13 +1,10 @@
#pragma once
#ifndef _DUALSHOCK3_H_ #ifndef _DUALSHOCK3_H_
#define _DUALSHOCK3_H_ #define _DUALSHOCK3_H_
#include <stdint.h> #include <stdint.h>
#include "descriptors/PS3Descriptors.h"
#include "usbh/GPHostDriver.h" #include "usbh/GPHostDriver.h"
#include "usbd/descriptors/PS3Descriptors.h"
#include "usbd/descriptors/DInputDescriptors.h"
const usb_vid_pid_t ps3_devices[] = const usb_vid_pid_t ps3_devices[] =
{ {
@@ -26,14 +23,16 @@ struct Dualshock3State
class Dualshock3 : public GPHostDriver class Dualshock3 : public GPHostDriver
{ {
public: public:
~Dualshock3() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
Dualshock3State dualshock3; Dualshock3State dualshock3;
void update_gamepad(Gamepad& gp, const Dualshock3Report* ds3_data); void update_gamepad(Gamepad* gp, const Dualshock3Report* ds3_data);
void get_report_complete_cb(uint8_t dev_addr, uint8_t instance); void get_report_complete_cb(uint8_t dev_addr, uint8_t instance);
}; };

View File

@@ -44,70 +44,72 @@ bool Dualshock4::set_leds(uint8_t dev_addr, uint8_t instance)
return dualshock4.leds_set; return dualshock4.leds_set;
} }
void Dualshock4::update_gamepad(Gamepad& gamepad, const Dualshock4Report* ds4_data) void Dualshock4::update_gamepad(Gamepad* gamepad, const Dualshock4Report* ds4_data)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
switch(ds4_data->dpad) switch(ds4_data->dpad)
{ {
case PS4_DPAD_MASK_UP: case PS4_DPAD_MASK_UP:
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
case PS4_DPAD_MASK_UP_RIGHT: case PS4_DPAD_MASK_UP_RIGHT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case PS4_DPAD_MASK_RIGHT: case PS4_DPAD_MASK_RIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case PS4_DPAD_MASK_RIGHT_DOWN: case PS4_DPAD_MASK_RIGHT_DOWN:
gamepad.buttons.right = true; gamepad->buttons.right = true;
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case PS4_DPAD_MASK_DOWN: case PS4_DPAD_MASK_DOWN:
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case PS4_DPAD_MASK_DOWN_LEFT: case PS4_DPAD_MASK_DOWN_LEFT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PS4_DPAD_MASK_LEFT: case PS4_DPAD_MASK_LEFT:
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PS4_DPAD_MASK_LEFT_UP: case PS4_DPAD_MASK_LEFT_UP:
gamepad.buttons.left = true; gamepad->buttons.left = true;
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
} }
if (ds4_data->square) gamepad.buttons.x = true; if (ds4_data->square) gamepad->buttons.x = true;
if (ds4_data->cross) gamepad.buttons.a = true; if (ds4_data->cross) gamepad->buttons.a = true;
if (ds4_data->circle) gamepad.buttons.b = true; if (ds4_data->circle) gamepad->buttons.b = true;
if (ds4_data->triangle) gamepad.buttons.y = true; if (ds4_data->triangle) gamepad->buttons.y = true;
if (ds4_data->share) gamepad.buttons.back = true; if (ds4_data->share) gamepad->buttons.back = true;
if (ds4_data->option) gamepad.buttons.start = true; if (ds4_data->option) gamepad->buttons.start = true;
if (ds4_data->ps) gamepad.buttons.sys = true; if (ds4_data->ps) gamepad->buttons.sys = true;
if (ds4_data->tpad) gamepad.buttons.misc = true; if (ds4_data->tpad) gamepad->buttons.misc = true;
if (ds4_data->l1) gamepad.buttons.lb = true; if (ds4_data->l1) gamepad->buttons.lb = true;
if (ds4_data->r1) gamepad.buttons.rb = true; if (ds4_data->r1) gamepad->buttons.rb = true;
if (ds4_data->l3) gamepad.buttons.l3 = true; if (ds4_data->l3) gamepad->buttons.l3 = true;
if (ds4_data->r3) gamepad.buttons.r3 = true; if (ds4_data->r3) gamepad->buttons.r3 = true;
gamepad.triggers.l = ds4_data->l2_trigger; gamepad->triggers.l = ds4_data->l2_trigger;
gamepad.triggers.r = ds4_data->r2_trigger; gamepad->triggers.r = ds4_data->r2_trigger;
gamepad.joysticks.lx = scale_uint8_to_int16(ds4_data->lx, false); gamepad->joysticks.lx = scale_uint8_to_int16(ds4_data->lx, false);
gamepad.joysticks.ly = scale_uint8_to_int16(ds4_data->ly, true); gamepad->joysticks.ly = scale_uint8_to_int16(ds4_data->ly, true);
gamepad.joysticks.rx = scale_uint8_to_int16(ds4_data->rx, false); gamepad->joysticks.rx = scale_uint8_to_int16(ds4_data->rx, false);
gamepad.joysticks.ry = scale_uint8_to_int16(ds4_data->ry, true); gamepad->joysticks.ry = scale_uint8_to_int16(ds4_data->ry, true);
} }
void Dualshock4::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void Dualshock4::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
static Dualshock4Report prev_report = { 0 }; (void)len;
static Dualshock4Report prev_report = {};
Dualshock4Report ds4_report; Dualshock4Report ds4_report;
memcpy(&ds4_report, report, sizeof(ds4_report)); memcpy(&ds4_report, report, sizeof(ds4_report));
@@ -121,16 +123,30 @@ void Dualshock4::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void Dualshock4::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void Dualshock4::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
{
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void Dualshock4::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {} void Dualshock4::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool Dualshock4::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) bool Dualshock4::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{ {
Dualshock4OutReport out_report = {0}; Dualshock4OutReport out_report = {0};
out_report.set_rumble = 1; out_report.set_rumble = 1;
out_report.motor_left = gamepad.rumble.l; out_report.motor_left = gamepad->rumble.l;
out_report.motor_right = gamepad.rumble.r; out_report.motor_right = gamepad->rumble.r;
return tuh_hid_send_report(dev_addr, instance, 5, &out_report, sizeof(out_report)); return tuh_hid_send_report(dev_addr, instance, 5, &out_report, sizeof(out_report));
} }

View File

@@ -1,5 +1,3 @@
#pragma once
#ifndef _DUALSHOCK4_H_ #ifndef _DUALSHOCK4_H_
#define _DUALSHOCK4_H_ #define _DUALSHOCK4_H_
@@ -125,14 +123,16 @@ struct Dualshock4State
class Dualshock4 : public GPHostDriver class Dualshock4 : public GPHostDriver
{ {
public: public:
~Dualshock4() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
Dualshock4State dualshock4; Dualshock4State dualshock4;
void update_gamepad(Gamepad& gp, const Dualshock4Report* ds4_data); void update_gamepad(Gamepad* gp, const Dualshock4Report* ds4_data);
bool set_leds(uint8_t dev_addr, uint8_t instance); bool set_leds(uint8_t dev_addr, uint8_t instance);
}; };

View File

@@ -3,7 +3,6 @@
#include "tusb.h" #include "tusb.h"
#include "usbh/ps5/Dualsense.h" #include "usbh/ps5/Dualsense.h"
#include "usbh/shared/scaling.h" #include "usbh/shared/scaling.h"
void Dualsense::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) void Dualsense::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
@@ -12,89 +11,105 @@ void Dualsense::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void Dualsense::update_gamepad(Gamepad& gamepad, const DualsenseReport* ds_report) void Dualsense::update_gamepad(Gamepad* gamepad, const DualsenseReport* ds_report)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
switch(ds_report->dpad) switch(ds_report->dpad)
{ {
case PS5_MASK_DPAD_UP: case PS5_MASK_DPAD_UP:
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
case PS5_MASK_DPAD_UP_RIGHT: case PS5_MASK_DPAD_UP_RIGHT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case PS5_MASK_DPAD_RIGHT: case PS5_MASK_DPAD_RIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case PS5_MASK_DPAD_RIGHT_DOWN: case PS5_MASK_DPAD_RIGHT_DOWN:
gamepad.buttons.right = true; gamepad->buttons.right = true;
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case PS5_MASK_DPAD_DOWN: case PS5_MASK_DPAD_DOWN:
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case PS5_MASK_DPAD_DOWN_LEFT: case PS5_MASK_DPAD_DOWN_LEFT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PS5_MASK_DPAD_LEFT: case PS5_MASK_DPAD_LEFT:
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PS5_MASK_DPAD_LEFT_UP: case PS5_MASK_DPAD_LEFT_UP:
gamepad.buttons.left = true; gamepad->buttons.left = true;
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
} }
if (ds_report->square) gamepad.buttons.x = true; if (ds_report->square) gamepad->buttons.x = true;
if (ds_report->cross) gamepad.buttons.a = true; if (ds_report->cross) gamepad->buttons.a = true;
if (ds_report->circle) gamepad.buttons.b = true; if (ds_report->circle) gamepad->buttons.b = true;
if (ds_report->triangle) gamepad.buttons.y = true; if (ds_report->triangle) gamepad->buttons.y = true;
if (ds_report->buttons[0] & PS5_MASK_L1) gamepad.buttons.lb = true; if (ds_report->buttons[0] & PS5_MASK_L1) gamepad->buttons.lb = true;
if (ds_report->buttons[0] & PS5_MASK_R1) gamepad.buttons.rb = true; if (ds_report->buttons[0] & PS5_MASK_R1) gamepad->buttons.rb = true;
if (ds_report->buttons[0] & PS5_MASK_SHARE) gamepad.buttons.back = true; if (ds_report->buttons[0] & PS5_MASK_SHARE) gamepad->buttons.back = true;
if (ds_report->buttons[0] & PS5_MASK_OPTIONS) gamepad.buttons.start = true; if (ds_report->buttons[0] & PS5_MASK_OPTIONS) gamepad->buttons.start = true;
if (ds_report->buttons[0] & PS5_MASK_L3) gamepad.buttons.l3 = true; if (ds_report->buttons[0] & PS5_MASK_L3) gamepad->buttons.l3 = true;
if (ds_report->buttons[0] & PS5_MASK_R3) gamepad.buttons.r3 = true; if (ds_report->buttons[0] & PS5_MASK_R3) gamepad->buttons.r3 = true;
if (ds_report->buttons[1] & PS5_MASK_PS) gamepad.buttons.sys = true; if (ds_report->buttons[1] & PS5_MASK_PS) gamepad->buttons.sys = true;
if (ds_report->buttons[1] & PS5_MASK_MIC) gamepad.buttons.misc = true; if (ds_report->buttons[1] & PS5_MASK_MIC) gamepad->buttons.misc = true;
gamepad.triggers.l = ds_report->lt; gamepad->triggers.l = ds_report->lt;
gamepad.triggers.r = ds_report->rt; gamepad->triggers.r = ds_report->rt;
gamepad.joysticks.lx = scale_uint8_to_int16(ds_report->lx, false); gamepad->joysticks.lx = scale_uint8_to_int16(ds_report->lx, false);
gamepad.joysticks.ly = scale_uint8_to_int16(ds_report->ly, true); gamepad->joysticks.ly = scale_uint8_to_int16(ds_report->ly, true);
gamepad.joysticks.rx = scale_uint8_to_int16(ds_report->rx, false); gamepad->joysticks.rx = scale_uint8_to_int16(ds_report->rx, false);
gamepad.joysticks.ry = scale_uint8_to_int16(ds_report->ry, true); gamepad->joysticks.ry = scale_uint8_to_int16(ds_report->ry, true);
} }
void Dualsense::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void Dualsense::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
(void)len;
DualsenseReport ds_report; DualsenseReport ds_report;
memcpy(&ds_report, report, sizeof(ds_report)); memcpy(&ds_report, report, sizeof(ds_report));
update_gamepad(gamepad, &ds_report); update_gamepad(gamepad, &ds_report);
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void Dualsense::process_xinput_report(Gamepad& gp, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void Dualsense::process_xinput_report(Gamepad* gp, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
{
(void)gp;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void Dualsense::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {} void Dualsense::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool Dualsense::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) bool Dualsense::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{ {
// need to figure out if the flags are necessary and how the LEDs work // need to figure out if the flags are necessary and how the LEDs work
DualsenseOutReport out_report = {0}; DualsenseOutReport out_report = {0};
out_report.valid_flag0 = 0x02; // idk what this means out_report.valid_flag0 = 0x02; // idk what this means
out_report.valid_flag1 = 0x02; // this one either out_report.valid_flag1 = 0x02; // this one either
out_report.valid_flag2 = 0x04; // uhhhhh out_report.valid_flag2 = 0x04; // uhhhhh
out_report.motor_left = gamepad.rumble.l; out_report.motor_left = gamepad->rumble.l;
out_report.motor_right = gamepad.rumble.r; out_report.motor_right = gamepad->rumble.r;
return tuh_hid_send_report(dev_addr, instance, 5, &out_report, sizeof(out_report)); return tuh_hid_send_report(dev_addr, instance, 5, &out_report, sizeof(out_report));
} }

View File

@@ -138,13 +138,13 @@ class Dualsense : public GPHostDriver
{ {
public: public:
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
DualsenseState dualsense; DualsenseState dualsense;
void update_gamepad(Gamepad& gp, const DualsenseReport* ds_report); void update_gamepad(Gamepad* gp, const DualsenseReport* ds_report);
}; };
#endif // _DUALSENSE_H_ #endif // _DUALSENSE_H_

View File

@@ -10,59 +10,61 @@ void PSClassic::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void PSClassic::update_gamepad(Gamepad& gamepad, const PSClassicReport* psc_data) void PSClassic::update_gamepad(Gamepad* gamepad, const PSClassicReport* psc_data)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
switch (psc_data->buttons & 0x3C00) { switch (psc_data->buttons & 0x3C00) {
case PSCLASSIC_MASK_UP_LEFT: case PSCLASSIC_MASK_UP_LEFT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PSCLASSIC_MASK_UP: case PSCLASSIC_MASK_UP:
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
case PSCLASSIC_MASK_UP_RIGHT: case PSCLASSIC_MASK_UP_RIGHT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case PSCLASSIC_MASK_LEFT: case PSCLASSIC_MASK_LEFT:
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PSCLASSIC_MASK_RIGHT: case PSCLASSIC_MASK_RIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case PSCLASSIC_MASK_DOWN_LEFT: case PSCLASSIC_MASK_DOWN_LEFT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case PSCLASSIC_MASK_DOWN: case PSCLASSIC_MASK_DOWN:
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case PSCLASSIC_MASK_DOWN_RIGHT: case PSCLASSIC_MASK_DOWN_RIGHT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
} }
if (psc_data->buttons & PSCLASSIC_MASK_TRIANGLE) gamepad.buttons.y = true; if (psc_data->buttons & PSCLASSIC_MASK_TRIANGLE) gamepad->buttons.y = true;
if (psc_data->buttons & PSCLASSIC_MASK_CIRCLE) gamepad.buttons.b = true; if (psc_data->buttons & PSCLASSIC_MASK_CIRCLE) gamepad->buttons.b = true;
if (psc_data->buttons & PSCLASSIC_MASK_CROSS) gamepad.buttons.a = true; if (psc_data->buttons & PSCLASSIC_MASK_CROSS) gamepad->buttons.a = true;
if (psc_data->buttons & PSCLASSIC_MASK_SQUARE) gamepad.buttons.x = true; if (psc_data->buttons & PSCLASSIC_MASK_SQUARE) gamepad->buttons.x = true;
if (psc_data->buttons & PSCLASSIC_MASK_L2) gamepad.triggers.l = 0xFF; if (psc_data->buttons & PSCLASSIC_MASK_L2) gamepad->triggers.l = 0xFF;
if (psc_data->buttons & PSCLASSIC_MASK_R2) gamepad.triggers.r = 0xFF; if (psc_data->buttons & PSCLASSIC_MASK_R2) gamepad->triggers.r = 0xFF;
if (psc_data->buttons & PSCLASSIC_MASK_L1) gamepad.buttons.lb = true; if (psc_data->buttons & PSCLASSIC_MASK_L1) gamepad->buttons.lb = true;
if (psc_data->buttons & PSCLASSIC_MASK_R1) gamepad.buttons.rb = true; if (psc_data->buttons & PSCLASSIC_MASK_R1) gamepad->buttons.rb = true;
if (psc_data->buttons & PSCLASSIC_MASK_SELECT) gamepad.buttons.back = true; if (psc_data->buttons & PSCLASSIC_MASK_SELECT) gamepad->buttons.back = true;
if (psc_data->buttons & PSCLASSIC_MASK_START) gamepad.buttons.start = true; if (psc_data->buttons & PSCLASSIC_MASK_START) gamepad->buttons.start = true;
} }
void PSClassic::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void PSClassic::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
static PSClassicReport prev_report = { 0 }; (void)len;
static PSClassicReport prev_report = {};
PSClassicReport psc_report; PSClassicReport psc_report;
memcpy(&psc_report, report, sizeof(psc_report)); memcpy(&psc_report, report, sizeof(psc_report));
@@ -77,11 +79,29 @@ void PSClassic::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t i
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void PSClassic::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void PSClassic::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
void PSClassic::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {}
bool PSClassic::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{ {
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void PSClassic::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool PSClassic::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{
(void)gamepad;
(void)dev_addr;
(void)instance;
return true; return true;
} }

View File

@@ -1,12 +1,10 @@
#pragma once
#ifndef _PSCLASSIC_H_ #ifndef _PSCLASSIC_H_
#define _PSCLASSIC_H_ #define _PSCLASSIC_H_
#include <stdint.h> #include <stdint.h>
#include "descriptors/PSClassicDescriptors.h"
#include "usbh/GPHostDriver.h" #include "usbh/GPHostDriver.h"
#include "usbd/descriptors/PSClassicDescriptors.h"
const usb_vid_pid_t psc_devices[] = const usb_vid_pid_t psc_devices[] =
{ {
@@ -21,14 +19,16 @@ struct PSClassicState
class PSClassic : public GPHostDriver class PSClassic : public GPHostDriver
{ {
public: public:
~PSClassic() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
PSClassicState psclassic; PSClassicState psclassic;
void update_gamepad(Gamepad& gp, const PSClassicReport* psc_data); void update_gamepad(Gamepad* gp, const PSClassicReport* psc_data);
}; };
#endif // _PSCLASSIC_H_ #endif // _PSCLASSIC_H_

View File

@@ -7,12 +7,15 @@
void SwitchPro::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) void SwitchPro::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
{ {
(void)dev_addr;
(void)instance;
switch_pro.player_id = player_id; switch_pro.player_id = player_id;
} }
void SwitchPro::send_handshake(uint8_t dev_addr, uint8_t instance) void SwitchPro::send_handshake(uint8_t dev_addr, uint8_t instance)
{ {
if (tuh_hid_send_ready) if (tuh_hid_send_ready(dev_addr, instance))
{ {
uint8_t handshake_command[2] = {CMD_HID, SUBCMD_HANDSHAKE}; uint8_t handshake_command[2] = {CMD_HID, SUBCMD_HANDSHAKE};
switch_pro.handshake_sent = tuh_hid_send_report(dev_addr, instance, 0, handshake_command, sizeof(handshake_command)); switch_pro.handshake_sent = tuh_hid_send_report(dev_addr, instance, 0, handshake_command, sizeof(handshake_command));
@@ -31,15 +34,17 @@ uint8_t SwitchPro::get_output_sequence_counter()
void SwitchPro::disable_timeout(uint8_t dev_addr, uint8_t instance) void SwitchPro::disable_timeout(uint8_t dev_addr, uint8_t instance)
{ {
if (tuh_hid_send_ready) if (tuh_hid_send_ready(dev_addr, instance))
{ {
uint8_t disable_timeout_cmd[2] = {CMD_HID, SUBCMD_DISABLE_TIMEOUT}; uint8_t disable_timeout_cmd[2] = {CMD_HID, SUBCMD_DISABLE_TIMEOUT};
switch_pro.timeout_disabled = tuh_hid_send_report(dev_addr, instance, 0, disable_timeout_cmd, sizeof(disable_timeout_cmd)); switch_pro.timeout_disabled = tuh_hid_send_report(dev_addr, instance, 0, disable_timeout_cmd, sizeof(disable_timeout_cmd));
} }
} }
void SwitchPro::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void SwitchPro::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
(void)len;
if (!switch_pro.handshake_sent) if (!switch_pro.handshake_sent)
{ {
return; return;
@@ -51,7 +56,7 @@ void SwitchPro::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t i
return; return;
} }
static SwitchProReport prev_report = {0}; static SwitchProReport prev_report = {};
SwitchProReport switch_report; SwitchProReport switch_report;
memcpy(&switch_report, report, sizeof(switch_report)); memcpy(&switch_report, report, sizeof(switch_report));
@@ -86,45 +91,59 @@ int16_t SwitchPro::normalize_axes(uint16_t value)
return (int16_t)normalized_value; return (int16_t)normalized_value;
} }
void SwitchPro::update_gamepad(Gamepad& gamepad, const SwitchProReport* switch_report) void SwitchPro::update_gamepad(Gamepad* gamepad, const SwitchProReport* switch_report)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
if (switch_report->up) gamepad.buttons.up =true; if (switch_report->up) gamepad->buttons.up =true;
if (switch_report->down) gamepad.buttons.down =true; if (switch_report->down) gamepad->buttons.down =true;
if (switch_report->left) gamepad.buttons.left =true; if (switch_report->left) gamepad->buttons.left =true;
if (switch_report->right) gamepad.buttons.right =true; if (switch_report->right) gamepad->buttons.right =true;
if (switch_report->y) gamepad.buttons.x = true; if (switch_report->y) gamepad->buttons.x = true;
if (switch_report->x) gamepad.buttons.y = true; if (switch_report->x) gamepad->buttons.y = true;
if (switch_report->b) gamepad.buttons.a = true; if (switch_report->b) gamepad->buttons.a = true;
if (switch_report->a) gamepad.buttons.b = true; if (switch_report->a) gamepad->buttons.b = true;
if (switch_report->minus) gamepad.buttons.back = true; if (switch_report->minus) gamepad->buttons.back = true;
if (switch_report->plus) gamepad.buttons.start = true; if (switch_report->plus) gamepad->buttons.start = true;
if (switch_report->home) gamepad.buttons.sys = true; if (switch_report->home) gamepad->buttons.sys = true;
if (switch_report->capture) gamepad.buttons.misc = true; if (switch_report->capture) gamepad->buttons.misc = true;
if (switch_report->stickL) gamepad.buttons.l3 = true; if (switch_report->stickL) gamepad->buttons.l3 = true;
if (switch_report->stickR) gamepad.buttons.r3 = true; if (switch_report->stickR) gamepad->buttons.r3 = true;
if (switch_report->l) gamepad.buttons.lb = true; if (switch_report->l) gamepad->buttons.lb = true;
if (switch_report->r) gamepad.buttons.rb = true; if (switch_report->r) gamepad->buttons.rb = true;
if (switch_report->zl) gamepad.triggers.l = 0xFF; if (switch_report->zl) gamepad->triggers.l = 0xFF;
if (switch_report->zr) gamepad.triggers.r = 0xFF; if (switch_report->zr) gamepad->triggers.r = 0xFF;
gamepad.joysticks.lx = normalize_axes(switch_report->leftX ); gamepad->joysticks.lx = normalize_axes(switch_report->leftX );
gamepad.joysticks.ly = normalize_axes(switch_report->leftY ); gamepad->joysticks.ly = normalize_axes(switch_report->leftY );
gamepad.joysticks.rx = normalize_axes(switch_report->rightX); gamepad->joysticks.rx = normalize_axes(switch_report->rightX);
gamepad.joysticks.ry = normalize_axes(switch_report->rightY); gamepad->joysticks.ry = normalize_axes(switch_report->rightY);
} }
void SwitchPro::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void SwitchPro::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
{
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void SwitchPro::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {} void SwitchPro::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool SwitchPro::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) bool SwitchPro::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{ {
if (!switch_pro.handshake_sent) if (!switch_pro.handshake_sent)
{ {
@@ -145,9 +164,9 @@ bool SwitchPro::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t i
report.command = CMD_RUMBLE_ONLY; report.command = CMD_RUMBLE_ONLY;
report.sequence_counter = get_output_sequence_counter(); report.sequence_counter = get_output_sequence_counter();
if (gamepad.rumble.l > 0) if (gamepad->rumble.l > 0)
{ {
uint8_t amplitude_l = static_cast<uint8_t>(((gamepad.rumble.l / 255.0f) * 0.8f + 0.5f) * (0xC0 - 0x40) + 0x40); uint8_t amplitude_l = static_cast<uint8_t>(((gamepad->rumble.l / 255.0f) * 0.8f + 0.5f) * (0xC0 - 0x40) + 0x40);
report.rumble_l[0] = amplitude_l; report.rumble_l[0] = amplitude_l;
report.rumble_l[1] = 0x88; report.rumble_l[1] = 0x88;
@@ -162,9 +181,9 @@ bool SwitchPro::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t i
report.rumble_l[3] = 0x40; report.rumble_l[3] = 0x40;
} }
if (gamepad.rumble.r > 0) if (gamepad->rumble.r > 0)
{ {
uint8_t amplitude_r = static_cast<uint8_t>(((gamepad.rumble.r / 255.0f) * 0.8f + 0.5f) * (0xC0 - 0x40) + 0x40); uint8_t amplitude_r = static_cast<uint8_t>(((gamepad->rumble.r / 255.0f) * 0.8f + 0.5f) * (0xC0 - 0x40) + 0x40);
report.rumble_r[0] = amplitude_r; report.rumble_r[0] = amplitude_r;
report.rumble_r[1] = 0x88; report.rumble_r[1] = 0x88;

View File

@@ -1,11 +1,9 @@
#pragma once
#ifndef _SWITCHPRO_H_ #ifndef _SWITCHPRO_H_
#define _SWITCHPRO_H_ #define _SWITCHPRO_H_
#include <stdint.h> #include <stdint.h>
#include "descriptors/SwitchProDescriptors.h"
#include "usbd/descriptors/SwitchProDescriptors.h"
#include "usbh/GPHostDriver.h" #include "usbh/GPHostDriver.h"
const usb_vid_pid_t switch_pro_devices[] = const usb_vid_pid_t switch_pro_devices[] =
@@ -29,18 +27,20 @@ struct SwitchProState
class SwitchPro : public GPHostDriver class SwitchPro : public GPHostDriver
{ {
public: public:
~SwitchPro() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
SwitchProState switch_pro; SwitchProState switch_pro;
void send_handshake(uint8_t dev_addr, uint8_t instance); void send_handshake(uint8_t dev_addr, uint8_t instance);
void disable_timeout(uint8_t dev_addr, uint8_t instance); void disable_timeout(uint8_t dev_addr, uint8_t instance);
uint8_t get_output_sequence_counter(); uint8_t get_output_sequence_counter();
int16_t normalize_axes(uint16_t value); int16_t normalize_axes(uint16_t value);
void update_gamepad(Gamepad& gp, const SwitchProReport* switch_pro_data); void update_gamepad(Gamepad* gp, const SwitchProReport* switch_pro_data);
}; };
#endif // _SWITCHPRO_H_ #endif // _SWITCHPRO_H_

View File

@@ -2,11 +2,10 @@
#include "pico/stdlib.h" #include "pico/stdlib.h"
#include "pico/time.h" #include "pico/time.h"
#include "tusb.h" #include "tusb.h"
#include "descriptors/SwitchDescriptors.h"
#include "usbh/switch/SwitchWired.h" #include "usbh/switch/SwitchWired.h"
#include "usbh/shared/scaling.h" #include "usbh/shared/scaling.h"
#include "usbd/descriptors/SwitchDescriptors.h"
void SwitchWired::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) void SwitchWired::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
{ {
@@ -14,9 +13,11 @@ void SwitchWired::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void SwitchWired::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void SwitchWired::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
static SwitchWiredReport prev_report = {0}; (void)len;
static SwitchWiredReport prev_report = {};
SwitchWiredReport switch_report; SwitchWiredReport switch_report;
memcpy(&switch_report, report, sizeof(switch_report)); memcpy(&switch_report, report, sizeof(switch_report));
@@ -31,72 +32,90 @@ void SwitchWired::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t
tuh_hid_receive_report(dev_addr, instance); tuh_hid_receive_report(dev_addr, instance);
} }
void SwitchWired::update_gamepad(Gamepad& gamepad, const SwitchWiredReport* switch_report) void SwitchWired::update_gamepad(Gamepad* gamepad, const SwitchWiredReport* switch_report)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
switch (switch_report->dpad) switch (switch_report->dpad)
{ {
case SWITCH_HAT_UP: case SWITCH_HAT_UP:
gamepad.buttons.up = true; gamepad->buttons.up = true;
break; break;
case SWITCH_HAT_UPRIGHT: case SWITCH_HAT_UPRIGHT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case SWITCH_HAT_RIGHT: case SWITCH_HAT_RIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
break; break;
case SWITCH_HAT_DOWNRIGHT: case SWITCH_HAT_DOWNRIGHT:
gamepad.buttons.right = true; gamepad->buttons.right = true;
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case SWITCH_HAT_DOWN: case SWITCH_HAT_DOWN:
gamepad.buttons.down = true; gamepad->buttons.down = true;
break; break;
case SWITCH_HAT_DOWNLEFT: case SWITCH_HAT_DOWNLEFT:
gamepad.buttons.down = true; gamepad->buttons.down = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case SWITCH_HAT_LEFT: case SWITCH_HAT_LEFT:
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
case SWITCH_HAT_UPLEFT: case SWITCH_HAT_UPLEFT:
gamepad.buttons.up = true; gamepad->buttons.up = true;
gamepad.buttons.left = true; gamepad->buttons.left = true;
break; break;
} }
if (switch_report->b) gamepad.buttons.a = true; if (switch_report->b) gamepad->buttons.a = true;
if (switch_report->a) gamepad.buttons.b = true; if (switch_report->a) gamepad->buttons.b = true;
if (switch_report->y) gamepad.buttons.x = true; if (switch_report->y) gamepad->buttons.x = true;
if (switch_report->x) gamepad.buttons.y = true; if (switch_report->x) gamepad->buttons.y = true;
if (switch_report->minus) gamepad.buttons.back = true; if (switch_report->minus) gamepad->buttons.back = true;
if (switch_report->plus) gamepad.buttons.start = true; if (switch_report->plus) gamepad->buttons.start = true;
if (switch_report->l3) gamepad.buttons.l3 = true; if (switch_report->l3) gamepad->buttons.l3 = true;
if (switch_report->r3) gamepad.buttons.r3 = true; if (switch_report->r3) gamepad->buttons.r3 = true;
if(switch_report->home) gamepad.buttons.sys = true; if(switch_report->home) gamepad->buttons.sys = true;
if(switch_report->capture) gamepad.buttons.misc = true; if(switch_report->capture) gamepad->buttons.misc = true;
if(switch_report->l) gamepad.buttons.lb = true; if(switch_report->l) gamepad->buttons.lb = true;
if(switch_report->r) gamepad.buttons.rb = true; if(switch_report->r) gamepad->buttons.rb = true;
if(switch_report->lz) gamepad.triggers.l = 0xFF; if(switch_report->lz) gamepad->triggers.l = 0xFF;
if(switch_report->rz) gamepad.triggers.r = 0xFF; if(switch_report->rz) gamepad->triggers.r = 0xFF;
gamepad.joysticks.lx = scale_uint8_to_int16(switch_report->lx, false); gamepad->joysticks.lx = scale_uint8_to_int16(switch_report->lx, false);
gamepad.joysticks.ly = scale_uint8_to_int16(switch_report->ly, true); gamepad->joysticks.ly = scale_uint8_to_int16(switch_report->ly, true);
gamepad.joysticks.rx = scale_uint8_to_int16(switch_report->rx, false); gamepad->joysticks.rx = scale_uint8_to_int16(switch_report->rx, false);
gamepad.joysticks.ry = scale_uint8_to_int16(switch_report->ry, true); gamepad->joysticks.ry = scale_uint8_to_int16(switch_report->ry, true);
} }
void SwitchWired::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) {} void SwitchWired::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
void SwitchWired::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {}
bool SwitchWired::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{ {
(void)gamepad;
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
}
void SwitchWired::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool SwitchWired::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{
(void)gamepad;
(void)dev_addr;
(void)instance;
return true; // not aware of a wired switch gamepad with rumble return true; // not aware of a wired switch gamepad with rumble
} }

View File

@@ -1,5 +1,3 @@
#pragma once
#ifndef _SWITCHWIRED_H_ #ifndef _SWITCHWIRED_H_
#define _SWITCHWIRED_H_ #define _SWITCHWIRED_H_
@@ -10,6 +8,7 @@
const usb_vid_pid_t switch_wired_devices[] = const usb_vid_pid_t switch_wired_devices[] =
{ {
{0x20D6, 0xA719}, // PowerA wired {0x20D6, 0xA719}, // PowerA wired
{0x20D6, 0xA713}, // PowerA Enhanced wired
{0x0F0D, 0x0092} // Hori Pokken wired, I don't have this one so not 100% on if it'll work {0x0F0D, 0x0092} // Hori Pokken wired, I don't have this one so not 100% on if it'll work
}; };
@@ -53,14 +52,16 @@ struct SwitchWiredState
class SwitchWired : public GPHostDriver class SwitchWired : public GPHostDriver
{ {
public: public:
~SwitchWired() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
SwitchWiredState switch_wired; SwitchWiredState switch_wired;
void update_gamepad(Gamepad& gp, const SwitchWiredReport* switch_pro_data); void update_gamepad(Gamepad* gp, const SwitchWiredReport* switch_pro_data);
}; };
#endif // _SWITCHWIRED_H_ #endif // _SWITCHWIRED_H_

View File

@@ -7,13 +7,13 @@
#include "usbh/tusb_host.h" #include "usbh/tusb_host.h"
#include "usbh/tusb_host_manager.h" #include "usbh/tusb_host_manager.h"
#include "usbd/board_config.h" #include "ogxm_config.h"
#define PIO_USB_CONFIG { PIO_USB_DP_PIN, PIO_USB_TX_DEFAULT, PIO_SM_USB_TX_DEFAULT, PIO_USB_DMA_TX_DEFAULT, PIO_USB_RX_DEFAULT, PIO_SM_USB_RX_DEFAULT, PIO_SM_USB_EOP_DEFAULT, NULL, PIO_USB_DEBUG_PIN_NONE, PIO_USB_DEBUG_PIN_NONE, false, PIO_USB_PINOUT_DPDM } #define PIO_USB_CONFIG { PIO_USB_DP_PIN, PIO_USB_TX_DEFAULT, PIO_SM_USB_TX_DEFAULT, PIO_USB_DMA_TX_DEFAULT, PIO_USB_RX_DEFAULT, PIO_SM_USB_RX_DEFAULT, PIO_SM_USB_EOP_DEFAULT, NULL, PIO_USB_DEBUG_PIN_NONE, PIO_USB_DEBUG_PIN_NONE, false, PIO_USB_PINOUT_DPDM }
void board_setup() void board_setup()
{ {
#if USBD_BOARD == OGXM_ADA_FEATHER_USBH #if OGXM_BOARD == ADAFRUIT_FEATHER_USBH
gpio_init(VCC_EN_PIN); gpio_init(VCC_EN_PIN);
gpio_set_dir(VCC_EN_PIN, GPIO_OUT); gpio_set_dir(VCC_EN_PIN, GPIO_OUT);
gpio_put(VCC_EN_PIN, 1); gpio_put(VCC_EN_PIN, 1);

View File

@@ -2,6 +2,7 @@
#include "tusb.h" #include "tusb.h"
#include "host/usbh.h" #include "host/usbh.h"
#include "class/hid/hid_host.h" #include "class/hid/hid_host.h"
#include "tusb_gamepad.h"
#include "usbh/xinput/XInput.h" #include "usbh/xinput/XInput.h"
#include "usbh/n64usb/N64USB.h" #include "usbh/n64usb/N64USB.h"
@@ -16,20 +17,19 @@
#include "usbh/shared/hid_class_driver.h" #include "usbh/shared/hid_class_driver.h"
#include "usbh/tusb_host_manager.h" #include "usbh/tusb_host_manager.h"
#include "usbd/board_config.h" #include "ogxm_config.h"
#include "Gamepad.h"
struct HostedDevice struct HostManager
{ {
bool hid_class = {false}; bool hid = {false};
bool class_mounted = {false}; bool mounted = {false};
uint8_t class_address; uint8_t address;
uint8_t class_instance; uint8_t instance;
const usbh_class_driver_t* class_driver = {&usbh_xinput_driver}; const usbh_class_driver_t* class_driver = {&usbh_xinput_driver};
GPHostDriver* gamepad_driver = {nullptr}; GPHostDriver* gp_host_driver = {nullptr};
}; };
HostedDevice hosted_device[MAX_GAMEPADS] = {}; HostManager host_manager[MAX_GAMEPADS] = {};
typedef struct typedef struct
{ {
@@ -55,7 +55,7 @@ void led_mounted_indicator(bool mounted)
gpio_put(LED_INDICATOR_PIN, mounted ? 1 : 0); gpio_put(LED_INDICATOR_PIN, mounted ? 1 : 0);
} }
bool check_vid_pid(const usb_vid_pid_t* devices, size_t num_devices, HostMode check_mode, uint16_t vid, uint16_t pid) bool check_vid_pid(const usb_vid_pid_t* devices, size_t num_devices, uint16_t vid, uint16_t pid)
{ {
for (size_t i = 0; i < num_devices; i++) for (size_t i = 0; i < num_devices; i++)
{ {
@@ -68,42 +68,44 @@ bool check_vid_pid(const usb_vid_pid_t* devices, size_t num_devices, HostMode ch
return false; return false;
} }
void create_gamepad_driver(HostMode host_mode, int idx) void init_gp_host_driver(HostMode host_mode, int idx)
{ {
switch(host_mode) switch(host_mode)
{ {
case HOST_MODE_XINPUT: case HOST_MODE_XINPUT:
hosted_device[idx].gamepad_driver = new XInputHost(); host_manager[idx].gp_host_driver = new XInputHost();
break; break;
case HOST_MODE_HID_PSCLASSIC: case HOST_MODE_HID_PSCLASSIC:
hosted_device[idx].gamepad_driver = new PSClassic(); host_manager[idx].gp_host_driver = new PSClassic();
break; break;
case HOST_MODE_HID_DINPUT: case HOST_MODE_HID_DINPUT:
hosted_device[idx].gamepad_driver = new DInput(); host_manager[idx].gp_host_driver = new DInput();
break; break;
case HOST_MODE_HID_PS3: case HOST_MODE_HID_PS3:
hosted_device[idx].gamepad_driver = new Dualshock3(); host_manager[idx].gp_host_driver = new Dualshock3();
break; break;
case HOST_MODE_HID_PS4: case HOST_MODE_HID_PS4:
hosted_device[idx].gamepad_driver = new Dualshock4(); host_manager[idx].gp_host_driver = new Dualshock4();
break; break;
case HOST_MODE_HID_PS5: case HOST_MODE_HID_PS5:
hosted_device[idx].gamepad_driver = new Dualsense(); host_manager[idx].gp_host_driver = new Dualsense();
break; break;
case HOST_MODE_HID_SWITCH_PRO: case HOST_MODE_HID_SWITCH_PRO:
hosted_device[idx].gamepad_driver = new SwitchPro(); host_manager[idx].gp_host_driver = new SwitchPro();
break; break;
case HOST_MODE_HID_SWITCH_WIRED: case HOST_MODE_HID_SWITCH_WIRED:
hosted_device[idx].gamepad_driver = new SwitchWired(); host_manager[idx].gp_host_driver = new SwitchWired();
break; break;
case HOST_MODE_HID_N64USB: case HOST_MODE_HID_N64USB:
hosted_device[idx].gamepad_driver = new N64USB(); host_manager[idx].gp_host_driver = new N64USB();
break;
default:
break; break;
} }
if (hosted_device[idx].gamepad_driver) if (host_manager[idx].gp_host_driver)
{ {
hosted_device[idx].gamepad_driver->init((uint8_t)idx + 1, hosted_device[idx].class_address, hosted_device[idx].class_instance); host_manager[idx].gp_host_driver->init((uint8_t)idx + 1, host_manager[idx].address, host_manager[idx].instance);
} }
} }
@@ -111,9 +113,9 @@ int find_free_slot()
{ {
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (!hosted_device[i].class_mounted) if (!host_manager[i].mounted)
{ {
hosted_device[i].class_mounted = true; host_manager[i].mounted = true;
return i; return i;
} }
} }
@@ -125,30 +127,35 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
{ {
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (hosted_device[i].class_mounted && hosted_device[i].class_address == dev_addr && hosted_device[i].class_instance == instance) if (host_manager[i].mounted &&
host_manager[i].address == dev_addr &&
host_manager[i].instance == instance)
{ {
hosted_device[i].class_mounted = false; host_manager[i].mounted = false;
gamepad(i).reset_pad();
if (hosted_device[i].gamepad_driver) gamepad(i)->reset_pad(gamepad(i));
gamepad(i)->enable_analog_buttons = false;
if (host_manager[i].gp_host_driver)
{ {
delete hosted_device[i].gamepad_driver; delete host_manager[i].gp_host_driver;
hosted_device[i].gamepad_driver = nullptr; host_manager[i].gp_host_driver = nullptr;
} }
} }
} }
int free_slots = 0; bool all_free = true;
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (!hosted_device[i].gamepad_driver) if (host_manager[i].gp_host_driver != nullptr)
{ {
free_slots++; all_free = false;
break;
} }
} }
if (free_slots == MAX_GAMEPADS) if (all_free)
{ {
led_mounted_indicator(false); led_mounted_indicator(false);
} }
@@ -158,19 +165,21 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
void tuh_mount_cb(uint8_t daddr) void tuh_mount_cb(uint8_t daddr)
{ {
(void)daddr;
led_mounted_indicator(true); led_mounted_indicator(true);
} }
void tuh_umount_cb(uint8_t daddr) void tuh_umount_cb(uint8_t daddr)
{ {
(void)daddr;
} }
usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count)
{ {
*driver_count = 1; *driver_count = 1;
return hosted_device[0].class_driver; return host_manager[0].class_driver;
} }
/* ----------- HID ----------- */ /* ----------- HID ----------- */
@@ -182,12 +191,11 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
int slot = find_free_slot(); int slot = find_free_slot();
if (slot < 0) return; // no available slots if (slot < 0) return; // no available slots, shouldn't happen
hosted_device[slot].class_address = dev_addr; host_manager[slot].address = dev_addr;
hosted_device[slot].class_instance = instance; host_manager[slot].instance = instance;
HostMode host_mode;
uint16_t vid, pid; uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid); tuh_vid_pid_get(dev_addr, &vid, &pid);
@@ -196,11 +204,18 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
for (size_t i = 0; i < num_device_types; i++) for (size_t i = 0; i < num_device_types; i++)
{ {
if (check_vid_pid(device_types[i].devices, device_types[i].num_devices, device_types[i].check_mode, vid, pid)) if (check_vid_pid(device_types[i].devices, device_types[i].num_devices, vid, pid))
{ {
hosted_device[slot].hid_class = true; host_manager[slot].hid = true;
host_mode = device_types[i].check_mode;
create_gamepad_driver(host_mode, slot); init_gp_host_driver(device_types[i].check_mode, slot);
if (device_types[i].check_mode == HOST_MODE_HID_DINPUT ||
device_types[i].check_mode == HOST_MODE_HID_PS3)
{
gamepad(slot)->enable_analog_buttons = true;
}
break; break;
} }
} }
@@ -217,13 +232,13 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
{ {
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (hosted_device[i].class_mounted && if (host_manager[i].mounted &&
hosted_device[i].class_address == dev_addr && host_manager[i].address == dev_addr &&
hosted_device[i].class_instance == instance) host_manager[i].instance == instance)
{ {
if (hosted_device[i].gamepad_driver) if (host_manager[i].gp_host_driver)
{ {
hosted_device[i].gamepad_driver->process_hid_report(gamepad(i), dev_addr, instance, report, len); host_manager[i].gp_host_driver->process_hid_report(gamepad(i), dev_addr, instance, report, len);
} }
} }
} }
@@ -235,11 +250,11 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
// { // {
// for (int i = 0; i < MAX_GAMEPADS; i++) // for (int i = 0; i < MAX_GAMEPADS; i++)
// { // {
// if (hosted_device[i].class_mounted && // if (host_manager[i].mounted &&
// hosted_device[i].class_address == dev_addr && // host_manager[i].address == dev_addr &&
// hosted_device[i].class_instance == instance) // host_manager[i].instance == instance)
// { // {
// hosted_device[i].gamepad_driver->hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len); // host_manager[i].gp_host_driver->hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len);
// } // }
// } // }
// } // }
@@ -248,14 +263,21 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
void tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, const xinputh_interface_t *xinput_itf) void tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, const xinputh_interface_t *xinput_itf)
{ {
(void)xinput_itf;
int slot = find_free_slot(); int slot = find_free_slot();
if (slot < 0) return; // no available slots if (slot < 0) return; // no available slots
hosted_device[slot].class_address = dev_addr; host_manager[slot].address = dev_addr;
hosted_device[slot].class_instance = instance; host_manager[slot].instance = instance;
create_gamepad_driver(HOST_MODE_XINPUT, slot); init_gp_host_driver(HOST_MODE_XINPUT, slot);
if (xinput_itf->type == XBOXOG)
{
gamepad(slot)->enable_analog_buttons = true;
}
tuh_xinput_receive_report(dev_addr, instance); tuh_xinput_receive_report(dev_addr, instance);
} }
@@ -269,11 +291,11 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, xinputh_i
{ {
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (hosted_device[i].class_mounted && hosted_device[i].class_address == dev_addr && hosted_device[i].class_instance == instance) if (host_manager[i].mounted && host_manager[i].address == dev_addr && host_manager[i].instance == instance)
{ {
if (hosted_device[i].gamepad_driver) if (host_manager[i].gp_host_driver)
{ {
hosted_device[i].gamepad_driver->process_xinput_report(gamepad(i), dev_addr, instance, report, len); host_manager[i].gp_host_driver->process_xinput_report(gamepad(i), dev_addr, instance, report, len);
} }
} }
} }
@@ -283,6 +305,19 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, xinputh_i
/* ----------- SEND FEEDBACK ----------- */ /* ----------- SEND FEEDBACK ----------- */
void reset_hid_rumble(Gamepad* gp)
{
if (gp->rumble.l != UINT8_MAX)
{
gp->rumble.l = 0;
}
if (gp->rumble.r != UINT8_MAX)
{
gp->rumble.r = 0;
}
}
void send_fb_data_to_gamepad() void send_fb_data_to_gamepad()
{ {
static const uint8_t fb_interval_ms = 100; static const uint8_t fb_interval_ms = 100;
@@ -290,19 +325,19 @@ void send_fb_data_to_gamepad()
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (!hosted_device[i].class_mounted || !hosted_device[i].gamepad_driver) break; if (!host_manager[i].mounted || !host_manager[i].gp_host_driver) break;
unsigned long current_time = to_ms_since_boot(get_absolute_time()); unsigned long current_time = to_ms_since_boot(get_absolute_time());
if (current_time - fb_sent_time[i] >= fb_interval_ms) if (current_time - fb_sent_time[i] >= fb_interval_ms)
{ {
if (hosted_device[i].gamepad_driver->send_fb_data(gamepad(i), hosted_device[i].class_address, hosted_device[i].class_instance)) if (host_manager[i].gp_host_driver->send_fb_data(gamepad(i), host_manager[i].address, host_manager[i].instance))
{ {
fb_sent_time[i] = current_time; fb_sent_time[i] = current_time;
if (hosted_device[i].hid_class) if (host_manager[i].hid)
{ {
gamepad(i).reset_hid_rumble(); // reset rumble so it doesn't get stuck on reset_hid_rumble(gamepad(i));
} }
} }
} }

View File

@@ -15,53 +15,84 @@ void XInputHost::set_leds(uint8_t dev_addr, uint8_t instance)
xinput.leds_set = tuh_xinput_set_led(dev_addr, instance, xinput.player_id, true); xinput.leds_set = tuh_xinput_set_led(dev_addr, instance, xinput.player_id, true);
} }
void XInputHost::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) void XInputHost::process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len)
{ {
(void)len;
xinputh_interface_t *xid_itf = (xinputh_interface_t *)report; xinputh_interface_t *xid_itf = (xinputh_interface_t *)report;
xinput_gamepad_t *xinput_data = &xid_itf->pad; xinput_gamepad_t *xinput_data = &xid_itf->pad;
if (xid_itf->connected && xid_itf->new_pad_data) if (xid_itf->connected && xid_itf->new_pad_data)
{ {
gamepad.reset_pad(); gamepad->reset_pad(gamepad);
gamepad.buttons.up = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0; gamepad->buttons.up = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0;
gamepad.buttons.down = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0; gamepad->buttons.down = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0;
gamepad.buttons.left = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0; gamepad->buttons.left = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0;
gamepad.buttons.right = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0; gamepad->buttons.right = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0;
gamepad.buttons.a = (xinput_data->wButtons & XINPUT_GAMEPAD_A) != 0; gamepad->buttons.a = (xinput_data->wButtons & XINPUT_GAMEPAD_A) != 0;
gamepad.buttons.b = (xinput_data->wButtons & XINPUT_GAMEPAD_B) != 0; gamepad->buttons.b = (xinput_data->wButtons & XINPUT_GAMEPAD_B) != 0;
gamepad.buttons.x = (xinput_data->wButtons & XINPUT_GAMEPAD_X) != 0; gamepad->buttons.x = (xinput_data->wButtons & XINPUT_GAMEPAD_X) != 0;
gamepad.buttons.y = (xinput_data->wButtons & XINPUT_GAMEPAD_Y) != 0; gamepad->buttons.y = (xinput_data->wButtons & XINPUT_GAMEPAD_Y) != 0;
gamepad.buttons.l3 = (xinput_data->wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0; gamepad->buttons.l3 = (xinput_data->wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0;
gamepad.buttons.r3 = (xinput_data->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0; gamepad->buttons.r3 = (xinput_data->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0;
gamepad.buttons.back = (xinput_data->wButtons & XINPUT_GAMEPAD_BACK) != 0; gamepad->buttons.back = (xinput_data->wButtons & XINPUT_GAMEPAD_BACK) != 0;
gamepad.buttons.start = (xinput_data->wButtons & XINPUT_GAMEPAD_START) != 0; gamepad->buttons.start = (xinput_data->wButtons & XINPUT_GAMEPAD_START) != 0;
gamepad.buttons.rb = (xinput_data->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0; gamepad->buttons.rb = (xinput_data->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0;
gamepad.buttons.lb = (xinput_data->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0; gamepad->buttons.lb = (xinput_data->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0;
gamepad.buttons.sys = (xinput_data->wButtons & XINPUT_GAMEPAD_GUIDE) != 0; gamepad->buttons.sys = (xinput_data->wButtons & XINPUT_GAMEPAD_GUIDE) != 0;
gamepad.buttons.misc = (xinput_data->wButtons & XINPUT_GAMEPAD_SHARE) != 0; gamepad->buttons.misc = (xinput_data->wButtons & XINPUT_GAMEPAD_SHARE) != 0;
gamepad.triggers.l = xinput_data->bLeftTrigger; if (gamepad->enable_analog_buttons)
gamepad.triggers.r = xinput_data->bRightTrigger; {
gamepad->analog_buttons.up = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_UP) ? UINT8_MAX : 0;
gamepad->analog_buttons.down = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? UINT8_MAX : 0;
gamepad->analog_buttons.left = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? UINT8_MAX : 0;
gamepad->analog_buttons.right = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? UINT8_MAX : 0;
gamepad.joysticks.lx = xinput_data->sThumbLX; gamepad->analog_buttons.a = xinput_data->analogButtons.a;
gamepad.joysticks.ly = xinput_data->sThumbLY; gamepad->analog_buttons.b = xinput_data->analogButtons.b;
gamepad->analog_buttons.x = xinput_data->analogButtons.x;
gamepad->analog_buttons.y = xinput_data->analogButtons.y;
gamepad.joysticks.rx = xinput_data->sThumbRX; gamepad->analog_buttons.lb = xinput_data->analogButtons.white;
gamepad.joysticks.ry = xinput_data->sThumbRY; gamepad->analog_buttons.rb = xinput_data->analogButtons.black;
}
gamepad->triggers.l = xinput_data->bLeftTrigger;
gamepad->triggers.r = xinput_data->bRightTrigger;
gamepad->joysticks.lx = xinput_data->sThumbLX;
gamepad->joysticks.ly = xinput_data->sThumbLY;
gamepad->joysticks.rx = xinput_data->sThumbRX;
gamepad->joysticks.ry = xinput_data->sThumbRY;
} }
tuh_xinput_receive_report(dev_addr, instance); tuh_xinput_receive_report(dev_addr, instance);
} }
void XInputHost::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {} void XInputHost::process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report;
(void)len;
(void)gamepad;
}
void XInputHost::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) {} void XInputHost::hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
{
(void)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
}
bool XInputHost::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) bool XInputHost::send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance)
{ {
static int report_num = 0; static int report_num = 0;
@@ -79,5 +110,5 @@ bool XInputHost::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t
report_num = 0; report_num = 0;
} }
return tuh_xinput_set_rumble(dev_addr, instance, gamepad.rumble.l, gamepad.rumble.r, true); return tuh_xinput_set_rumble(dev_addr, instance, gamepad->rumble.l, gamepad->rumble.r, true);
} }

View File

@@ -17,11 +17,13 @@ struct XInputState
class XInputHost : public GPHostDriver class XInputHost : public GPHostDriver
{ {
public: public:
~XInputHost() override {}
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance); virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); virtual void process_hid_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len); virtual void process_xinput_report(Gamepad* gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance); virtual bool send_fb_data(const Gamepad* gamepad, uint8_t dev_addr, uint8_t instance);
private: private:
XInputState xinput; XInputState xinput;
void set_leds(uint8_t dev_addr, uint8_t instance); void set_leds(uint8_t dev_addr, uint8_t instance);

View File

@@ -1,28 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
char stored_string[100];
void clear_log()
{
memset(stored_string, 0, sizeof(stored_string));
}
void log(const char* format, ...)
{
va_list args;
va_start(args, format);
clear_log();
vsnprintf(stored_string, sizeof(stored_string), format, args);
strcat(stored_string, "\n");
va_end(args);
}
const char* get_log()
{
return stored_string;
}

View File

@@ -1,8 +0,0 @@
#ifndef _LOG_H_
#define _LOG_H_
void log(const char* format, ...);
void clear_log();
const char* get_log();
#endif // _LOG_H_