3 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
38 changed files with 789 additions and 786 deletions

8
.gitmodules vendored
View File

@@ -4,9 +4,9 @@
[submodule "lib/tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git
[submodule "src/usbd"]
path = src/usbd
url = https://github.com/wiredopposite/usbd.git
[submodule "lib/tusb_gamepad"]
path = lib/tusb_gamepad
url = https://github.com/wiredopposite/tusb_gamepad.git
[submodule "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)
set(CMAKE_BUILD_TYPE Release)
message("Build type: \"${CMAKE_BUILD_TYPE}\"")
# Project name
set(NAME OGX-Mini)
# Board type
set(PICO_BOARD none)
# 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)
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}")
endif()
set(PICO_PIO_USB_PATH "${CMAKE_CURRENT_LIST_DIR}/lib/Pico-PIO-USB")
set(PICO_TINYUSB_PATH "${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb")
set(TUSB_XINPUT_PATH "${CMAKE_CURRENT_LIST_DIR}/lib/tusb_xinput")
add_subdirectory(${TUSB_XINPUT_PATH} xinput_host)
set(ROOT ${CMAKE_CURRENT_LIST_DIR})
set(PICO_PIO_USB_PATH ${ROOT}/lib/Pico-PIO-USB)
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()
add_subdirectory(lib/Pico-PIO-USB)
add_subdirectory(lib)
# add_subdirectory(${ROOT}/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
"src/main.cpp"
"src/input_mode.cpp"
"src/Gamepad.cpp"
${SRC_DIR}/main.cpp
${SRC_DIR}/input_mode.cpp
"src/utilities/log.cpp"
"src/usbh/tusb_host_manager.cpp"
"src/usbh/tusb_host.cpp"
"src/usbh/n64usb/N64USB.cpp"
"src/usbh/ps3/Dualshock3.cpp"
"src/usbh/ps3/DInput.cpp"
"src/usbh/ps4/Dualshock4.cpp"
"src/usbh/ps5/Dualsense.cpp"
"src/usbh/psclassic/PSClassic.cpp"
"src/usbh/switch/SwitchPro.cpp"
"src/usbh/switch/SwitchWired.cpp"
"src/usbh/xinput/XInput.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"
${SRC_DIR}/usbh/tusb_host_manager.cpp
${SRC_DIR}/usbh/tusb_host.cpp
${SRC_DIR}/usbh/n64usb/N64USB.cpp
${SRC_DIR}/usbh/ps3/Dualshock3.cpp
${SRC_DIR}/usbh/ps3/DInput.cpp
${SRC_DIR}/usbh/ps4/Dualshock4.cpp
${SRC_DIR}/usbh/ps5/Dualsense.cpp
${SRC_DIR}/usbh/psclassic/PSClassic.cpp
${SRC_DIR}/usbh/switch/SwitchPro.cpp
${SRC_DIR}/usbh/switch/SwitchWired.cpp
${SRC_DIR}/usbh/xinput/XInput.cpp
${SRC_DIR}/usbh/shared/hid_class_driver.c
${SRC_DIR}/usbh/shared/scaling.cpp
)
# Firmware
add_executable(${NAME}
${SOURCES}
)
add_executable(${NAME} ${SOURCES})
target_include_directories(${NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/lib)
include_directories(
lib/)
${ROOT}/src
${ROOT}/lib)
target_link_libraries(${NAME}
pico_stdlib
@@ -102,6 +85,7 @@ target_link_libraries(${NAME}
CRC32
cmsis_core
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

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

View File

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

View File

@@ -6,13 +6,12 @@
#include "tusb.h"
#include "bsp/board_api.h"
#include "tusb_gamepad.h"
#include "drivermanager.h"
#include "drivers/gpdriver.h"
#include "usbh/tusb_host.h"
#include "usbd/drivermanager.h"
#include "usbd/drivers/gpdriver.h"
#include "Gamepad.h"
#include "input_mode.h"
#include "usbd/board_config.h"
int main(void)
{
@@ -29,7 +28,7 @@ int main(void)
multicore_reset_core1();
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_checked = get_absolute_time();
@@ -39,16 +38,16 @@ int main(void)
{
uint8_t outBuffer[64];
GPDriver* driver = driverManager.getDriver();
driver->process(i, &gamepad(i), outBuffer);
driver->update_rumble(i, &gamepad(i));
driver->process(i, gamepad(i), outBuffer);
driver->update_rumble(i, gamepad(i));
}
if (absolute_time_diff_us(last_time_gamepad_checked, get_absolute_time()) >= 500000)
{
// 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();
}
// 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_
#define _TUSB_CONFIG_H_
#include "usbd/board_config.h"
#include "board_config.h"
#define MAX_GAMEPADS 1
#ifdef __cplusplus
extern "C" {
@@ -89,7 +91,7 @@
#define CFG_TUD_ENABLED 1
// 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.
* Tinyusb use follows macros to declare transferring memory so that they can be put
@@ -128,7 +130,7 @@
//--------------------------------------------------------------------
#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif
#define CFG_TUD_CDC_RX_BUFSIZE 256

Submodule src/usbd deleted from f7bdb97a37

View File

@@ -1,15 +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
#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 "host/usbh.h" // needed so xinput_host will build
#include "xinput_host.h"
#include "tusb_gamepad.h"
#include "usbh/shared/shared.h"
#include "xinput_host.h"
#include "Gamepad.h"
class GPHostDriver
{
public:
virtual ~GPHostDriver() = default;
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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_

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);
}
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;
switch(n64_dpad)
{
case N64_DPAD_MASK_UP:
gamepad.buttons.up = true;
gamepad->buttons.up = true;
break;
case N64_DPAD_MASK_UP_RIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
gamepad->buttons.up = true;
gamepad->buttons.right = true;
break;
case N64_DPAD_MASK_RIGHT:
gamepad.buttons.right = true;
gamepad->buttons.right = true;
break;
case N64_DPAD_MASK_RIGHT_DOWN:
gamepad.buttons.right = true;
gamepad.buttons.down = true;
gamepad->buttons.right = true;
gamepad->buttons.down = true;
break;
case N64_DPAD_MASK_DOWN:
gamepad.buttons.down = true;
gamepad->buttons.down = true;
break;
case N64_DPAD_MASK_DOWN_LEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
gamepad->buttons.down = true;
gamepad->buttons.left = true;
break;
case N64_DPAD_MASK_LEFT:
gamepad.buttons.left = true;
gamepad->buttons.left = true;
break;
case N64_DPAD_MASK_LEFT_UP:
gamepad.buttons.left = true;
gamepad.buttons.up = true;
gamepad->buttons.left = true;
gamepad->buttons.up = true;
break;
}
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_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_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_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_A_MASK) gamepad.buttons.a = 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_L_MASK) gamepad.buttons.lb = true;
if (n64_data->buttons & N64_R_MASK) gamepad.buttons.rb = 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_START_MASK) gamepad->buttons.start = 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_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.lx = scale_uint8_to_int16(n64_data->x, false);
gamepad->joysticks.ly = scale_uint8_to_int16(n64_data->y, true);
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;
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);
}
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 N64USB::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 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;
}

View File

@@ -1,5 +1,3 @@
#pragma once
#ifndef _N64USB_H_
#define _N64USB_H_
@@ -54,14 +52,16 @@ struct N64USBState
class N64USB: public GPHostDriver
{
public:
~N64USB() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
N64USBState n64usb;
void update_gamepad(Gamepad& gp, const N64USBReport* n64_data);
void update_gamepad(Gamepad* gp, const N64USBReport* n64_data);
};
#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);
}
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)
{
case DINPUT_HAT_UP:
gamepad.buttons.up = true;
gamepad->buttons.up = true;
break;
case DINPUT_HAT_UPRIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
gamepad->buttons.up = true;
gamepad->buttons.right = true;
break;
case DINPUT_HAT_RIGHT:
gamepad.buttons.right = true;
gamepad->buttons.right = true;
break;
case DINPUT_HAT_DOWNRIGHT:
gamepad.buttons.right = true;
gamepad.buttons.down = true;
gamepad->buttons.right = true;
gamepad->buttons.down = true;
break;
case DINPUT_HAT_DOWN:
gamepad.buttons.down = true;
gamepad->buttons.down = true;
break;
case DINPUT_HAT_DOWNLEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
gamepad->buttons.down = true;
gamepad->buttons.left = true;
break;
case DINPUT_HAT_LEFT:
gamepad.buttons.left = true;
gamepad->buttons.left = true;
break;
case DINPUT_HAT_UPLEFT:
gamepad.buttons.up = true;
gamepad.buttons.left = true;
gamepad->buttons.up = true;
gamepad->buttons.left = true;
break;
}
if (dinput_report->square_btn) gamepad.buttons.x = true;
if (dinput_report->triangle_btn) gamepad.buttons.y = true;
if (dinput_report->cross_btn) gamepad.buttons.a = true;
if (dinput_report->circle_btn) gamepad.buttons.b = true;
if (dinput_report->square_btn) gamepad->buttons.x = true;
if (dinput_report->triangle_btn) gamepad->buttons.y = true;
if (dinput_report->cross_btn) gamepad->buttons.a = true;
if (dinput_report->circle_btn) gamepad->buttons.b = true;
if (dinput_report->select_btn) gamepad.buttons.back = true;
if (dinput_report->start_btn) gamepad.buttons.start = true;
if (dinput_report->ps_btn) gamepad.buttons.sys = true;
if (dinput_report->select_btn) gamepad->buttons.back = true;
if (dinput_report->start_btn) gamepad->buttons.start = true;
if (dinput_report->ps_btn) gamepad->buttons.sys = true;
if (dinput_report->l3_btn) gamepad.buttons.l3 = true;
if (dinput_report->r3_btn) gamepad.buttons.r3 = true;
if (dinput_report->l3_btn) gamepad->buttons.l3 = true;
if (dinput_report->r3_btn) gamepad->buttons.r3 = true;
if (dinput_report->l1_btn) gamepad.buttons.lb = true;
if (dinput_report->r1_btn) gamepad.buttons.rb = true;
if (dinput_report->l1_btn) gamepad->buttons.lb = true;
if (dinput_report->r1_btn) gamepad->buttons.rb = true;
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)
{
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)
{
gamepad.triggers.r = 0xFF;
gamepad->triggers.r = 0xFF;
}
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);
gamepad->analog_buttons.up = dinput_report->up_axis;
gamepad->analog_buttons.down = dinput_report->down_axis;
gamepad->analog_buttons.left = dinput_report->left_axis;
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;
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);
}
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 DInput::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 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;
}

View File

@@ -2,9 +2,9 @@
#define _DINPUT_H_
#include <stdint.h>
#include "descriptors/DInputDescriptors.h"
#include "usbh/GPHostDriver.h"
#include "usbd/descriptors/DInputDescriptors.h"
const usb_vid_pid_t dinput_devices[] =
{
@@ -23,14 +23,16 @@ struct DInputState
class DInput : public GPHostDriver
{
public:
~DInput() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
DInputState dinput;
void update_gamepad(Gamepad& gp, const DInputReport* dinput_report);
void update_gamepad(Gamepad* gp, const DInputReport* dinput_report);
};
#endif // _DINPUT_H_

View File

@@ -4,7 +4,6 @@
#include "class/hid/hid_host.h"
#include "usbh/ps3/Dualshock3.h"
#include "usbh/shared/scaling.h"
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)dev_addr;
(void)instance;
(void)report_id;
(void)report_type;
(void)len;
// if (dualshock3.response_count == 0)
// {
// 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->down) gamepad.buttons.down =true;
if (ds3_data->left) gamepad.buttons.left =true;
if (ds3_data->right) gamepad.buttons.right =true;
if (ds3_data->up) gamepad->buttons.up =true;
if (ds3_data->down) gamepad->buttons.down =true;
if (ds3_data->left) gamepad->buttons.left =true;
if (ds3_data->right) gamepad->buttons.right =true;
if (ds3_data->square) gamepad.buttons.x = true;
if (ds3_data->triangle) gamepad.buttons.y = true;
if (ds3_data->cross) gamepad.buttons.a = true;
if (ds3_data->circle) gamepad.buttons.b = true;
if (ds3_data->square) gamepad->buttons.x = true;
if (ds3_data->triangle) gamepad->buttons.y = true;
if (ds3_data->cross) gamepad->buttons.a = true;
if (ds3_data->circle) gamepad->buttons.b = true;
if (ds3_data->select) gamepad.buttons.back = true;
if (ds3_data->start) gamepad.buttons.start = true;
if (ds3_data->ps) gamepad.buttons.sys = true;
if (ds3_data->select) gamepad->buttons.back = true;
if (ds3_data->start) gamepad->buttons.start = true;
if (ds3_data->ps) gamepad->buttons.sys = true;
if (ds3_data->l3) gamepad.buttons.l3 = true;
if (ds3_data->r3) gamepad.buttons.r3 = true;
if (ds3_data->l3) gamepad->buttons.l3 = true;
if (ds3_data->r3) gamepad->buttons.r3 = true;
if (ds3_data->l1) gamepad.buttons.lb = true;
if (ds3_data->r1) gamepad.buttons.rb = true;
if (ds3_data->l1) gamepad->buttons.lb = true;
if (ds3_data->r1) gamepad->buttons.rb = true;
gamepad.triggers.l = ds3_data->l2_axis;
gamepad.triggers.r = ds3_data->r2_axis;
gamepad->analog_buttons.up = ds3_data->up_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.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);
gamepad->analog_buttons.x = ds3_data->square_axis;
gamepad->analog_buttons.y = ds3_data->triangle_axis;
gamepad->analog_buttons.a = ds3_data->cross_axis;
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;
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);
}
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 Dualshock3::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;
}
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};
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;
}
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_duration = (gamepad->rumble.r > 0) ? 20: 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_motor_force = gamepad.rumble.l;
dualshock3.out_report.rumble.left_duration = (gamepad->rumble.l > 0) ? 20 : 0;
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)
{
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 (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);
}

View File

@@ -1,13 +1,10 @@
#pragma once
#ifndef _DUALSHOCK3_H_
#define _DUALSHOCK3_H_
#include <stdint.h>
#include "descriptors/PS3Descriptors.h"
#include "usbh/GPHostDriver.h"
#include "usbd/descriptors/PS3Descriptors.h"
#include "usbd/descriptors/DInputDescriptors.h"
const usb_vid_pid_t ps3_devices[] =
{
@@ -26,14 +23,16 @@ struct Dualshock3State
class Dualshock3 : public GPHostDriver
{
public:
~Dualshock3() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
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);
};

View File

@@ -44,70 +44,72 @@ bool Dualshock4::set_leds(uint8_t dev_addr, uint8_t instance)
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)
{
case PS4_DPAD_MASK_UP:
gamepad.buttons.up = true;
gamepad->buttons.up = true;
break;
case PS4_DPAD_MASK_UP_RIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
gamepad->buttons.up = true;
gamepad->buttons.right = true;
break;
case PS4_DPAD_MASK_RIGHT:
gamepad.buttons.right = true;
gamepad->buttons.right = true;
break;
case PS4_DPAD_MASK_RIGHT_DOWN:
gamepad.buttons.right = true;
gamepad.buttons.down = true;
gamepad->buttons.right = true;
gamepad->buttons.down = true;
break;
case PS4_DPAD_MASK_DOWN:
gamepad.buttons.down = true;
gamepad->buttons.down = true;
break;
case PS4_DPAD_MASK_DOWN_LEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
gamepad->buttons.down = true;
gamepad->buttons.left = true;
break;
case PS4_DPAD_MASK_LEFT:
gamepad.buttons.left = true;
gamepad->buttons.left = true;
break;
case PS4_DPAD_MASK_LEFT_UP:
gamepad.buttons.left = true;
gamepad.buttons.up = true;
gamepad->buttons.left = true;
gamepad->buttons.up = true;
break;
}
if (ds4_data->square) gamepad.buttons.x = true;
if (ds4_data->cross) gamepad.buttons.a = true;
if (ds4_data->circle) gamepad.buttons.b = true;
if (ds4_data->triangle) gamepad.buttons.y = true;
if (ds4_data->square) gamepad->buttons.x = true;
if (ds4_data->cross) gamepad->buttons.a = true;
if (ds4_data->circle) gamepad->buttons.b = true;
if (ds4_data->triangle) gamepad->buttons.y = true;
if (ds4_data->share) gamepad.buttons.back = true;
if (ds4_data->option) gamepad.buttons.start = true;
if (ds4_data->ps) gamepad.buttons.sys = true;
if (ds4_data->tpad) gamepad.buttons.misc = true;
if (ds4_data->share) gamepad->buttons.back = true;
if (ds4_data->option) gamepad->buttons.start = true;
if (ds4_data->ps) gamepad->buttons.sys = true;
if (ds4_data->tpad) gamepad->buttons.misc = true;
if (ds4_data->l1) gamepad.buttons.lb = true;
if (ds4_data->r1) gamepad.buttons.rb = true;
if (ds4_data->l1) gamepad->buttons.lb = true;
if (ds4_data->r1) gamepad->buttons.rb = true;
if (ds4_data->l3) gamepad.buttons.l3 = true;
if (ds4_data->r3) gamepad.buttons.r3 = true;
if (ds4_data->l3) gamepad->buttons.l3 = true;
if (ds4_data->r3) gamepad->buttons.r3 = true;
gamepad.triggers.l = ds4_data->l2_trigger;
gamepad.triggers.r = ds4_data->r2_trigger;
gamepad->triggers.l = ds4_data->l2_trigger;
gamepad->triggers.r = ds4_data->r2_trigger;
gamepad.joysticks.lx = scale_uint8_to_int16(ds4_data->lx, false);
gamepad.joysticks.ly = scale_uint8_to_int16(ds4_data->ly, true);
gamepad.joysticks.rx = scale_uint8_to_int16(ds4_data->rx, false);
gamepad.joysticks.ry = scale_uint8_to_int16(ds4_data->ry, true);
gamepad->joysticks.lx = scale_uint8_to_int16(ds4_data->lx, false);
gamepad->joysticks.ly = scale_uint8_to_int16(ds4_data->ly, true);
gamepad->joysticks.rx = scale_uint8_to_int16(ds4_data->rx, false);
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;
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);
}
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};
out_report.set_rumble = 1;
out_report.motor_left = gamepad.rumble.l;
out_report.motor_right = gamepad.rumble.r;
out_report.motor_left = gamepad->rumble.l;
out_report.motor_right = gamepad->rumble.r;
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_
#define _DUALSHOCK4_H_
@@ -125,14 +123,16 @@ struct Dualshock4State
class Dualshock4 : public GPHostDriver
{
public:
~Dualshock4() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
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);
};

View File

@@ -3,7 +3,6 @@
#include "tusb.h"
#include "usbh/ps5/Dualsense.h"
#include "usbh/shared/scaling.h"
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);
}
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)
{
case PS5_MASK_DPAD_UP:
gamepad.buttons.up = true;
gamepad->buttons.up = true;
break;
case PS5_MASK_DPAD_UP_RIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
gamepad->buttons.up = true;
gamepad->buttons.right = true;
break;
case PS5_MASK_DPAD_RIGHT:
gamepad.buttons.right = true;
gamepad->buttons.right = true;
break;
case PS5_MASK_DPAD_RIGHT_DOWN:
gamepad.buttons.right = true;
gamepad.buttons.down = true;
gamepad->buttons.right = true;
gamepad->buttons.down = true;
break;
case PS5_MASK_DPAD_DOWN:
gamepad.buttons.down = true;
gamepad->buttons.down = true;
break;
case PS5_MASK_DPAD_DOWN_LEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
gamepad->buttons.down = true;
gamepad->buttons.left = true;
break;
case PS5_MASK_DPAD_LEFT:
gamepad.buttons.left = true;
gamepad->buttons.left = true;
break;
case PS5_MASK_DPAD_LEFT_UP:
gamepad.buttons.left = true;
gamepad.buttons.up = true;
gamepad->buttons.left = true;
gamepad->buttons.up = true;
break;
}
if (ds_report->square) gamepad.buttons.x = true;
if (ds_report->cross) gamepad.buttons.a = true;
if (ds_report->circle) gamepad.buttons.b = true;
if (ds_report->triangle) gamepad.buttons.y = true;
if (ds_report->square) gamepad->buttons.x = true;
if (ds_report->cross) gamepad->buttons.a = true;
if (ds_report->circle) gamepad->buttons.b = 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_R1) gamepad.buttons.rb = 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_SHARE) gamepad.buttons.back = true;
if (ds_report->buttons[0] & PS5_MASK_OPTIONS) gamepad.buttons.start = 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_L3) gamepad.buttons.l3 = true;
if (ds_report->buttons[0] & PS5_MASK_R3) gamepad.buttons.r3 = 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[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_PS) gamepad->buttons.sys = true;
if (ds_report->buttons[1] & PS5_MASK_MIC) gamepad->buttons.misc = true;
gamepad.triggers.l = ds_report->lt;
gamepad.triggers.r = ds_report->rt;
gamepad->triggers.l = ds_report->lt;
gamepad->triggers.r = ds_report->rt;
gamepad.joysticks.lx = scale_uint8_to_int16(ds_report->lx, false);
gamepad.joysticks.ly = scale_uint8_to_int16(ds_report->ly, true);
gamepad.joysticks.rx = scale_uint8_to_int16(ds_report->rx, false);
gamepad.joysticks.ry = scale_uint8_to_int16(ds_report->ry, true);
gamepad->joysticks.lx = scale_uint8_to_int16(ds_report->lx, false);
gamepad->joysticks.ly = scale_uint8_to_int16(ds_report->ly, true);
gamepad->joysticks.rx = scale_uint8_to_int16(ds_report->rx, false);
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;
memcpy(&ds_report, report, sizeof(ds_report));
update_gamepad(gamepad, &ds_report);
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
DualsenseOutReport out_report = {0};
out_report.valid_flag0 = 0x02; // idk what this means
out_report.valid_flag1 = 0x02; // this one either
out_report.valid_flag2 = 0x04; // uhhhhh
out_report.motor_left = gamepad.rumble.l;
out_report.motor_right = gamepad.rumble.r;
out_report.motor_left = gamepad->rumble.l;
out_report.motor_right = gamepad->rumble.r;
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:
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
DualsenseState dualsense;
void update_gamepad(Gamepad& gp, const DualsenseReport* ds_report);
void update_gamepad(Gamepad* gp, const DualsenseReport* ds_report);
};
#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);
}
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) {
case PSCLASSIC_MASK_UP_LEFT:
gamepad.buttons.up = true;
gamepad.buttons.left = true;
gamepad->buttons.up = true;
gamepad->buttons.left = true;
break;
case PSCLASSIC_MASK_UP:
gamepad.buttons.up = true;
gamepad->buttons.up = true;
break;
case PSCLASSIC_MASK_UP_RIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
gamepad->buttons.up = true;
gamepad->buttons.right = true;
break;
case PSCLASSIC_MASK_LEFT:
gamepad.buttons.left = true;
gamepad->buttons.left = true;
break;
case PSCLASSIC_MASK_RIGHT:
gamepad.buttons.right = true;
gamepad->buttons.right = true;
break;
case PSCLASSIC_MASK_DOWN_LEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
gamepad->buttons.down = true;
gamepad->buttons.left = true;
break;
case PSCLASSIC_MASK_DOWN:
gamepad.buttons.down = true;
gamepad->buttons.down = true;
break;
case PSCLASSIC_MASK_DOWN_RIGHT:
gamepad.buttons.down = true;
gamepad.buttons.right = true;
gamepad->buttons.down = true;
gamepad->buttons.right = true;
break;
}
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_CROSS) gamepad.buttons.a = true;
if (psc_data->buttons & PSCLASSIC_MASK_SQUARE) gamepad.buttons.x = 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_CROSS) gamepad->buttons.a = 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_R2) gamepad.triggers.r = 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_L1) gamepad.buttons.lb = true;
if (psc_data->buttons & PSCLASSIC_MASK_R1) gamepad.buttons.rb = 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_SELECT) gamepad.buttons.back = true;
if (psc_data->buttons & PSCLASSIC_MASK_START) gamepad.buttons.start = true;
if (psc_data->buttons & PSCLASSIC_MASK_SELECT) gamepad->buttons.back = 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;
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);
}
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 PSClassic::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 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;
}

View File

@@ -1,12 +1,10 @@
#pragma once
#ifndef _PSCLASSIC_H_
#define _PSCLASSIC_H_
#include <stdint.h>
#include "descriptors/PSClassicDescriptors.h"
#include "usbh/GPHostDriver.h"
#include "usbd/descriptors/PSClassicDescriptors.h"
const usb_vid_pid_t psc_devices[] =
{
@@ -21,14 +19,16 @@ struct PSClassicState
class PSClassic : public GPHostDriver
{
public:
~PSClassic() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
PSClassicState psclassic;
void update_gamepad(Gamepad& gp, const PSClassicReport* psc_data);
void update_gamepad(Gamepad* gp, const PSClassicReport* psc_data);
};
#endif // _PSCLASSIC_H_

View File

@@ -7,12 +7,15 @@
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;
}
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};
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)
{
if (tuh_hid_send_ready)
if (tuh_hid_send_ready(dev_addr, instance))
{
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));
}
}
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)
{
return;
@@ -51,7 +56,7 @@ void SwitchPro::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t i
return;
}
static SwitchProReport prev_report = {0};
static SwitchProReport prev_report = {};
SwitchProReport 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;
}
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->down) gamepad.buttons.down =true;
if (switch_report->left) gamepad.buttons.left =true;
if (switch_report->right) gamepad.buttons.right =true;
if (switch_report->up) gamepad->buttons.up =true;
if (switch_report->down) gamepad->buttons.down =true;
if (switch_report->left) gamepad->buttons.left =true;
if (switch_report->right) gamepad->buttons.right =true;
if (switch_report->y) gamepad.buttons.x = true;
if (switch_report->x) gamepad.buttons.y = true;
if (switch_report->b) gamepad.buttons.a = true;
if (switch_report->a) gamepad.buttons.b = true;
if (switch_report->y) gamepad->buttons.x = true;
if (switch_report->x) gamepad->buttons.y = true;
if (switch_report->b) gamepad->buttons.a = true;
if (switch_report->a) gamepad->buttons.b = true;
if (switch_report->minus) gamepad.buttons.back = true;
if (switch_report->plus) gamepad.buttons.start = true;
if (switch_report->home) gamepad.buttons.sys = true;
if (switch_report->capture) gamepad.buttons.misc = true;
if (switch_report->minus) gamepad->buttons.back = true;
if (switch_report->plus) gamepad->buttons.start = true;
if (switch_report->home) gamepad->buttons.sys = true;
if (switch_report->capture) gamepad->buttons.misc = true;
if (switch_report->stickL) gamepad.buttons.l3 = true;
if (switch_report->stickR) gamepad.buttons.r3 = true;
if (switch_report->stickL) gamepad->buttons.l3 = true;
if (switch_report->stickR) gamepad->buttons.r3 = true;
if (switch_report->l) gamepad.buttons.lb = true;
if (switch_report->r) gamepad.buttons.rb = true;
if (switch_report->l) gamepad->buttons.lb = true;
if (switch_report->r) gamepad->buttons.rb = true;
if (switch_report->zl) gamepad.triggers.l = 0xFF;
if (switch_report->zr) gamepad.triggers.r = 0xFF;
if (switch_report->zl) gamepad->triggers.l = 0xFF;
if (switch_report->zr) gamepad->triggers.r = 0xFF;
gamepad.joysticks.lx = normalize_axes(switch_report->leftX );
gamepad.joysticks.ly = normalize_axes(switch_report->leftY );
gamepad.joysticks.rx = normalize_axes(switch_report->rightX);
gamepad.joysticks.ry = normalize_axes(switch_report->rightY);
gamepad->joysticks.lx = normalize_axes(switch_report->leftX );
gamepad->joysticks.ly = normalize_axes(switch_report->leftY );
gamepad->joysticks.rx = normalize_axes(switch_report->rightX);
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)
{
@@ -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.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[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;
}
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[1] = 0x88;

View File

@@ -1,11 +1,9 @@
#pragma once
#ifndef _SWITCHPRO_H_
#define _SWITCHPRO_H_
#include <stdint.h>
#include "descriptors/SwitchProDescriptors.h"
#include "usbd/descriptors/SwitchProDescriptors.h"
#include "usbh/GPHostDriver.h"
const usb_vid_pid_t switch_pro_devices[] =
@@ -29,18 +27,20 @@ struct SwitchProState
class SwitchPro : public GPHostDriver
{
public:
~SwitchPro() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
SwitchProState switch_pro;
void send_handshake(uint8_t dev_addr, uint8_t instance);
void disable_timeout(uint8_t dev_addr, uint8_t instance);
uint8_t get_output_sequence_counter();
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_

View File

@@ -2,11 +2,10 @@
#include "pico/stdlib.h"
#include "pico/time.h"
#include "tusb.h"
#include "descriptors/SwitchDescriptors.h"
#include "usbh/switch/SwitchWired.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)
{
@@ -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);
}
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;
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);
}
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)
{
case SWITCH_HAT_UP:
gamepad.buttons.up = true;
gamepad->buttons.up = true;
break;
case SWITCH_HAT_UPRIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
gamepad->buttons.up = true;
gamepad->buttons.right = true;
break;
case SWITCH_HAT_RIGHT:
gamepad.buttons.right = true;
gamepad->buttons.right = true;
break;
case SWITCH_HAT_DOWNRIGHT:
gamepad.buttons.right = true;
gamepad.buttons.down = true;
gamepad->buttons.right = true;
gamepad->buttons.down = true;
break;
case SWITCH_HAT_DOWN:
gamepad.buttons.down = true;
gamepad->buttons.down = true;
break;
case SWITCH_HAT_DOWNLEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
gamepad->buttons.down = true;
gamepad->buttons.left = true;
break;
case SWITCH_HAT_LEFT:
gamepad.buttons.left = true;
gamepad->buttons.left = true;
break;
case SWITCH_HAT_UPLEFT:
gamepad.buttons.up = true;
gamepad.buttons.left = true;
gamepad->buttons.up = true;
gamepad->buttons.left = true;
break;
}
if (switch_report->b) gamepad.buttons.a = true;
if (switch_report->a) gamepad.buttons.b = true;
if (switch_report->y) gamepad.buttons.x = true;
if (switch_report->x) gamepad.buttons.y = true;
if (switch_report->b) gamepad->buttons.a = true;
if (switch_report->a) gamepad->buttons.b = true;
if (switch_report->y) gamepad->buttons.x = true;
if (switch_report->x) gamepad->buttons.y = true;
if (switch_report->minus) gamepad.buttons.back = true;
if (switch_report->plus) gamepad.buttons.start = true;
if (switch_report->l3) gamepad.buttons.l3 = true;
if (switch_report->r3) gamepad.buttons.r3 = true;
if (switch_report->minus) gamepad->buttons.back = true;
if (switch_report->plus) gamepad->buttons.start = true;
if (switch_report->l3) gamepad->buttons.l3 = true;
if (switch_report->r3) gamepad->buttons.r3 = true;
if(switch_report->home) gamepad.buttons.sys = true;
if(switch_report->capture) gamepad.buttons.misc = true;
if(switch_report->home) gamepad->buttons.sys = true;
if(switch_report->capture) gamepad->buttons.misc = true;
if(switch_report->l) gamepad.buttons.lb = true;
if(switch_report->r) gamepad.buttons.rb = true;
if(switch_report->l) gamepad->buttons.lb = true;
if(switch_report->r) gamepad->buttons.rb = true;
if(switch_report->lz) gamepad.triggers.l = 0xFF;
if(switch_report->rz) gamepad.triggers.r = 0xFF;
if(switch_report->lz) gamepad->triggers.l = 0xFF;
if(switch_report->rz) gamepad->triggers.r = 0xFF;
gamepad.joysticks.lx = scale_uint8_to_int16(switch_report->lx, false);
gamepad.joysticks.ly = scale_uint8_to_int16(switch_report->ly, true);
gamepad.joysticks.rx = scale_uint8_to_int16(switch_report->rx, false);
gamepad.joysticks.ry = scale_uint8_to_int16(switch_report->ry, true);
gamepad->joysticks.lx = scale_uint8_to_int16(switch_report->lx, false);
gamepad->joysticks.ly = scale_uint8_to_int16(switch_report->ly, true);
gamepad->joysticks.rx = scale_uint8_to_int16(switch_report->rx, false);
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::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 SwitchWired::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 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
}

View File

@@ -1,5 +1,3 @@
#pragma once
#ifndef _SWITCHWIRED_H_
#define _SWITCHWIRED_H_
@@ -54,14 +52,16 @@ struct SwitchWiredState
class SwitchWired : public GPHostDriver
{
public:
~SwitchWired() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
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_

View File

@@ -7,13 +7,13 @@
#include "usbh/tusb_host.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 }
void board_setup()
{
#if USBD_BOARD == OGXM_ADA_FEATHER_USBH
#if OGXM_BOARD == ADAFRUIT_FEATHER_USBH
gpio_init(VCC_EN_PIN);
gpio_set_dir(VCC_EN_PIN, GPIO_OUT);
gpio_put(VCC_EN_PIN, 1);

View File

@@ -2,6 +2,7 @@
#include "tusb.h"
#include "host/usbh.h"
#include "class/hid/hid_host.h"
#include "tusb_gamepad.h"
#include "usbh/xinput/XInput.h"
#include "usbh/n64usb/N64USB.h"
@@ -16,20 +17,19 @@
#include "usbh/shared/hid_class_driver.h"
#include "usbh/tusb_host_manager.h"
#include "usbd/board_config.h"
#include "Gamepad.h"
#include "ogxm_config.h"
struct HostedDevice
struct HostManager
{
bool hid_class = {false};
bool class_mounted = {false};
uint8_t class_address;
uint8_t class_instance;
bool hid = {false};
bool mounted = {false};
uint8_t address;
uint8_t instance;
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
{
@@ -55,7 +55,7 @@ void led_mounted_indicator(bool mounted)
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++)
{
@@ -68,42 +68,44 @@ bool check_vid_pid(const usb_vid_pid_t* devices, size_t num_devices, HostMode ch
return false;
}
void create_gamepad_driver(HostMode host_mode, int idx)
void init_gp_host_driver(HostMode host_mode, int idx)
{
switch(host_mode)
{
case HOST_MODE_XINPUT:
hosted_device[idx].gamepad_driver = new XInputHost();
host_manager[idx].gp_host_driver = new XInputHost();
break;
case HOST_MODE_HID_PSCLASSIC:
hosted_device[idx].gamepad_driver = new PSClassic();
host_manager[idx].gp_host_driver = new PSClassic();
break;
case HOST_MODE_HID_DINPUT:
hosted_device[idx].gamepad_driver = new DInput();
host_manager[idx].gp_host_driver = new DInput();
break;
case HOST_MODE_HID_PS3:
hosted_device[idx].gamepad_driver = new Dualshock3();
host_manager[idx].gp_host_driver = new Dualshock3();
break;
case HOST_MODE_HID_PS4:
hosted_device[idx].gamepad_driver = new Dualshock4();
host_manager[idx].gp_host_driver = new Dualshock4();
break;
case HOST_MODE_HID_PS5:
hosted_device[idx].gamepad_driver = new Dualsense();
host_manager[idx].gp_host_driver = new Dualsense();
break;
case HOST_MODE_HID_SWITCH_PRO:
hosted_device[idx].gamepad_driver = new SwitchPro();
host_manager[idx].gp_host_driver = new SwitchPro();
break;
case HOST_MODE_HID_SWITCH_WIRED:
hosted_device[idx].gamepad_driver = new SwitchWired();
host_manager[idx].gp_host_driver = new SwitchWired();
break;
case HOST_MODE_HID_N64USB:
hosted_device[idx].gamepad_driver = new N64USB();
host_manager[idx].gp_host_driver = new N64USB();
break;
default:
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++)
{
if (!hosted_device[i].class_mounted)
if (!host_manager[i].mounted)
{
hosted_device[i].class_mounted = true;
host_manager[i].mounted = true;
return i;
}
}
@@ -125,15 +127,19 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
{
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;
gamepad(i).reset_pad();
host_manager[i].mounted = false;
gamepad(i)->reset_pad(gamepad(i));
gamepad(i)->enable_analog_buttons = false;
if (hosted_device[i].gamepad_driver)
if (host_manager[i].gp_host_driver)
{
delete hosted_device[i].gamepad_driver;
hosted_device[i].gamepad_driver = nullptr;
delete host_manager[i].gp_host_driver;
host_manager[i].gp_host_driver = nullptr;
}
}
}
@@ -142,7 +148,7 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (hosted_device[i].gamepad_driver != nullptr)
if (host_manager[i].gp_host_driver != nullptr)
{
all_free = false;
break;
@@ -159,19 +165,21 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
void tuh_mount_cb(uint8_t daddr)
{
(void)daddr;
led_mounted_indicator(true);
}
void tuh_umount_cb(uint8_t daddr)
{
(void)daddr;
}
usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count)
{
*driver_count = 1;
return hosted_device[0].class_driver;
return host_manager[0].class_driver;
}
/* ----------- HID ----------- */
@@ -183,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();
if (slot < 0) return; // no available slots
if (slot < 0) return; // no available slots, shouldn't happen
hosted_device[slot].class_address = dev_addr;
hosted_device[slot].class_instance = instance;
host_manager[slot].address = dev_addr;
host_manager[slot].instance = instance;
HostMode host_mode;
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
@@ -197,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++)
{
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_mode = device_types[i].check_mode;
create_gamepad_driver(host_mode, slot);
host_manager[slot].hid = true;
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;
}
}
@@ -218,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++)
{
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_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);
}
}
}
@@ -236,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++)
// {
// 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].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);
// }
// }
// }
@@ -249,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)xinput_itf;
int slot = find_free_slot();
if (slot < 0) return; // no available slots
hosted_device[slot].class_address = dev_addr;
hosted_device[slot].class_instance = instance;
host_manager[slot].address = dev_addr;
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);
}
@@ -270,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++)
{
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);
}
}
}
@@ -284,6 +305,19 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, xinputh_i
/* ----------- 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()
{
static const uint8_t fb_interval_ms = 100;
@@ -291,19 +325,19 @@ void send_fb_data_to_gamepad()
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());
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;
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);
}
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;
xinput_gamepad_t *xinput_data = &xid_itf->pad;
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.down = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 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.up = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_UP) != 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.right = (xinput_data->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0;
gamepad.buttons.a = (xinput_data->wButtons & XINPUT_GAMEPAD_A) != 0;
gamepad.buttons.b = (xinput_data->wButtons & XINPUT_GAMEPAD_B) != 0;
gamepad.buttons.x = (xinput_data->wButtons & XINPUT_GAMEPAD_X) != 0;
gamepad.buttons.y = (xinput_data->wButtons & XINPUT_GAMEPAD_Y) != 0;
gamepad->buttons.a = (xinput_data->wButtons & XINPUT_GAMEPAD_A) != 0;
gamepad->buttons.b = (xinput_data->wButtons & XINPUT_GAMEPAD_B) != 0;
gamepad->buttons.x = (xinput_data->wButtons & XINPUT_GAMEPAD_X) != 0;
gamepad->buttons.y = (xinput_data->wButtons & XINPUT_GAMEPAD_Y) != 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.back = (xinput_data->wButtons & XINPUT_GAMEPAD_BACK) != 0;
gamepad.buttons.start = (xinput_data->wButtons & XINPUT_GAMEPAD_START) != 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.back = (xinput_data->wButtons & XINPUT_GAMEPAD_BACK) != 0;
gamepad->buttons.start = (xinput_data->wButtons & XINPUT_GAMEPAD_START) != 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.sys = (xinput_data->wButtons & XINPUT_GAMEPAD_GUIDE) != 0;
gamepad.buttons.misc = (xinput_data->wButtons & XINPUT_GAMEPAD_SHARE) != 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.sys = (xinput_data->wButtons & XINPUT_GAMEPAD_GUIDE) != 0;
gamepad->buttons.misc = (xinput_data->wButtons & XINPUT_GAMEPAD_SHARE) != 0;
gamepad.triggers.l = xinput_data->bLeftTrigger;
gamepad.triggers.r = xinput_data->bRightTrigger;
if (gamepad->enable_analog_buttons)
{
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.joysticks.ly = xinput_data->sThumbLY;
gamepad->analog_buttons.a = xinput_data->analogButtons.a;
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.joysticks.ry = xinput_data->sThumbRY;
gamepad->analog_buttons.lb = xinput_data->analogButtons.white;
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);
}
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;
@@ -79,5 +110,5 @@ bool XInputHost::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t
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
{
public:
~XInputHost() override {}
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_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_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 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:
XInputState xinput;
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_