new boards

This commit is contained in:
wiredopposite
2024-04-17 18:26:02 -06:00
parent 1f27c3d4b5
commit 2613221d44
41 changed files with 2496 additions and 351 deletions

View File

@@ -38,12 +38,12 @@ file(GLOB_RECURSE SOURCES
"src/Gamepad.cpp"
"src/utilities/log.cpp"
"src/utilities/scaling.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"
@@ -51,6 +51,7 @@ file(GLOB_RECURSE SOURCES
"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"

View File

@@ -1,7 +1,9 @@
# OGX-Mini
![Adafruit Feather RP2040 USB Host](images/ada_feather_rp2040_usb.jpg "Adafruit Feather RP2040 USB Host")
![OGX-Mini Boards](images/OGX-Mini-github.jpg "OGX-Mini Boards")
Firmware for the RP2040, setup for the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723) (can be used with the Pi Pico as well), capable of emulating gamepads for
Firmware for the RP2040, capable of emulating gamepads for several consoles. The firmware now comes in 3 flavors, for the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), the Pi Pico, and the Waveshare RP2040-Zero.
## Supported platforms
- Original Xbox
- Playstation 3
- Nintendo Switch (docked)
@@ -12,12 +14,14 @@ Firmware for the RP2040, setup for the [Adafruit Feather USB Host board](https:/
### Wired controllers
- Original Xbox Duke and S
- Xbox 360, One, Series, and Elite
- Dualshock 3 (PS3)
- Dualshock 4 (PS4)
- Dualsense (PS5, Dualsense Edge should work but it's untested)
- Nintendo Switch Pro
- Nintendo Switch wired (tested with PowerA brand)
- Nintendo 64 USB (experimental, tested with RetroLink brand)
- Playstation Classic
- Generic DInput
### Wireless adapters
- Xbox 360 PC adapter (Microsoft or clones, syncs 1 controller)
@@ -44,16 +48,33 @@ 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.
## 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.
![OGX-Mini Boards](images/OGX-Mini-rpzero-int.jpg "OGX-Mini Boards")
If you would like a prebuilt unit, you can purchase one, with cable and Xbox adapter included, from my website [wiredopposite.com](https://wiredopposite.com/product/ogx-mini-controller-adapter-for-original-xbox-playstation-3-and-switch-ogx360/) or my [Etsy store](https://www.etsy.com/listing/1426992904/ogx-mini-controller-adapter-for-original).
For the Pi Pico, this is a diagram of how you'd connect the extra USB port:
![Pi Pico Wiring Diagram](images/pi_pico_diagram.png "Pi Pico Wiring Diagram]")
For the [Adafruit Feather USB Host board](https://www.adafruit.com/product/5723), no extra work is needed.
## 2 & 4 Player support (in initial development)
With v0.4, 2 and 4 player variants of the firmware are included on the Releases page, this is only meant for PlayStation 3 and Nintendo Switch. You can use either a self-powered USB hub or an Xbox 360 wireless adapter to play with 4 controllers.
As it is right now, the Switch/PS3 will see 2 or 4 controllers no matter how many you're using, but I'm currently working on a way to connect controllers as they're plugged in or synced with a wireless adapter.
## Adding supported controllers
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
You can compile this for the Pi Pico by changing `BOARD_PI_PICO` to 1 (and the other boards to 0) in board_config.h
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.
That 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.
Here's a diagram of how you'd use the Pico:
![Pi Pico Wiring Diagram](images/pi_pico_diagram.png "Pi Pico Wiring Diagram]")
You can also choose OGXM_RPZERO_INTERPOSER for the RP2040-Zero and that will set D+ and D- to GPIO 10 and 11, so connecting a USB port is easier. You can still use the Pi Pico firmware on the RP2040-Zero (the other way around has not been tested though).
## Special thanks
Thank you to Ryzee119 and the OpenStickCommunity, without their work this project would not exist.

View File

@@ -0,0 +1,6 @@
References,Qty,Description,Manufacturer,MPN,Digikey,Mouser,RS,Newark,Farnell,LCSC,JLC Assembly
USB1,1,USB TYPE-A SINGLE PORT RIGHT ANG,,CU01SAH0S00,2987-CU01SAH0S00-ND,,,,,,
"R1,R2",2,RES 27 OHM 5% 1/8W 0805,,RC0805JR-0727RL,311-27ARCT-ND,,,,,,
R3,1,RES 470 OHM 1% 1/8W 0805 (Optional),,RC0805FR-07470RL,311-470CRCT-ND,,,,,,
LED1,1,LED GREEN CLEAR 0805 SMD (Optional),,150080GS75000,732-4983-1-ND,,,,,,
U1,1,Waveshare RP2040-Zero,,Waveshare RP2040-Zero,,,,,,,
1 References Qty Description Manufacturer MPN Digikey Mouser RS Newark Farnell LCSC JLC Assembly
2 USB1 1 USB TYPE-A SINGLE PORT RIGHT ANG CU01SAH0S00 2987-CU01SAH0S00-ND
3 R1,R2 2 RES 27 OHM 5% 1/8W 0805 RC0805JR-0727RL 311-27ARCT-ND
4 R3 1 RES 470 OHM 1% 1/8W 0805 (Optional) RC0805FR-07470RL 311-470CRCT-ND
5 LED1 1 LED GREEN CLEAR 0805 SMD (Optional) 150080GS75000 732-4983-1-ND
6 U1 1 Waveshare RP2040-Zero Waveshare RP2040-Zero

Binary file not shown.

3
hardware/README.md Normal file
View File

@@ -0,0 +1,3 @@
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.

File diff suppressed because it is too large Load Diff

BIN
images/OGX-Mini-github.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

View File

@@ -1,5 +1,5 @@
#include "Gamepad.h"
#include "board_config.h"
#include "usbd/board_config.h"
void Gamepad::reset_pad()
{

View File

@@ -1,110 +0,0 @@
#ifndef BOARD_CONFIG_H_
#define BOARD_CONFIG_H_
// Boards // Wired
#define OGXM_PI_PICO 1
#define OGXM_ADA_FEATHER_USBH 2
#define OGXM_RPZERO_INTERPOSER 3
// Boards // Wireless
#define OGXW_RETAIL_1CH 11
#define OGXW_RPZERO_1CH 12
#define OGXW_RPZERO_2CH 13
#define OGXW_LITE 16
// ----- Options ---- //
#define OGX_BOARD OGXM_ADA_FEATHER_USBH
#define OGX_MAX_GAMEPADS 1
#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()
// ------------------ //
// Don't edit below this unless you're changing pinouts for new hardware
// Type
#define WIRED 1
#define WIRELESS 2
// MCU
#define MCU_RP2040 1
#define MCU_ESP32S3 2
#if OGX_BOARD != OGXW_LITE
#define OGX_MCU MCU_RP2040
#else
#define OGX_MCU MCU_ESP32S3
#endif
#if (OGX_BOARD == OGXM_ADA_FEATHER_USBH) || (OGX_BOARD == OGXM_PI_PICO) || (OGX_BOARD == OGXM_RPZERO_INTERPOSER)
#define OGX_TYPE WIRED
#else
#define OGX_TYPE WIRELESS
#endif
#if OGX_TYPE == WIRED
#define MAX_GAMEPADS OGX_MAX_GAMEPADS
#if OGX_BOARD == OGXM_ADA_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 OGX_BOARD == OGXM_PI_PICO
#define PIO_USB_DP_PIN 0 // DM = 1
#define LED_INDICATOR_PIN 25
#elif OGX_BOARD == OGXM_RPZERO_INTERPOSER
#define PIO_USB_DP_PIN 10 // DM = 11
#define LED_INDICATOR_PIN 13
#endif
#elif OGX_TYPE == WIRELESS
#ifdef CONFIG_BLUEPAD32_MAX_DEVICES
#define MAX_GAMEPADS CONFIG_BLUEPAD32_MAX_DEVICES
#else
#define MAX_GAMEPADS OGX_MAX_GAMEPADS
#endif
#define PLAYER_ID1_PIN 2
#define PLAYER_ID2_PIN 3
#if (OGX_BOARD == OGXW_RETAIL_1CH)
#define I2C1_SLAVE_SDA_PIN 18
#define I2C1_SLAVE_SCL_PIN 19
#define MODE_SEL_PIN 21
#define ESP_PROG_PIN 20 // ESP32 IO0
#define ESP_RST_PIN 8 // ESP32 EN
#define UART0_TX_PIN 16
#define UART0_RX_PIN 17
#elif (OGX_BOARD == OGXW_RPZERO_1CH)
#define I2C1_SLAVE_SDA_PIN 10
#define I2C1_SLAVE_SCL_PIN 11
#define MODE_SEL_PIN 9
#define ESP_PROG_PIN 15 // ESP32 IO0
#define ESP_RST_PIN 14 // ESP32 EN
#define UART0_TX_PIN 12
#define UART0_RX_PIN 13
#elif (OGX_BOARD == OGXW_RPZERO_2CH)
#define I2C1_SLAVE_SDA_PIN 10
#define I2C1_SLAVE_SCL_PIN 11
#define MODE_SEL_PIN 8
#define ESP_PROG_PIN 9 // ESP32 IO0
#define ESP_RST_PIN 7 // ESP32 EN
#define UART0_TX_PIN 12
#define UART0_RX_PIN 13
#endif
#endif
#endif // BOARD_CONFIG_H_

View File

@@ -6,7 +6,7 @@
#include "tusb.h"
#include "board_config.h"
#include "usbd/board_config.h"
#include "input_mode.h"
#define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) // Address of the AIRCR register
@@ -103,8 +103,6 @@ enum InputMode get_input_mode()
return INPUT_MODE_USBSERIAL;
#endif
// return INPUT_MODE_HID;
const uint8_t *stored_value = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
if (*stored_value >= INPUT_MODE_XINPUT && *stored_value <= INPUT_MODE_XBOXORIGINAL)

View File

@@ -12,7 +12,7 @@
#include "usbd/drivers/gpdriver.h"
#include "Gamepad.h"
#include "input_mode.h"
#include "board_config.h"
#include "usbd/board_config.h"
int main(void)
{

View File

@@ -26,7 +26,7 @@
#ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_
#include "board_config.h"
#include "usbd/board_config.h"
#ifdef __cplusplus
extern "C" {

19
src/usbd_config.h Normal file
View File

@@ -0,0 +1,19 @@
#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_ADA_FEATHER_USBH
#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

@@ -1,5 +1,3 @@
#pragma once
#ifndef _GPHOSTDRIVER_H_
#define _GPHOSTDRIVER_H_
@@ -16,7 +14,8 @@ class GPHostDriver
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 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;
};
#endif
#endif // _GPHOSTDRIVER_H_

View File

@@ -2,7 +2,7 @@
#include "pico/stdlib.h"
#include "tusb.h"
#include "utilities/scaling.h"
#include "usbh/shared/scaling.h"
#include "usbh/n64usb/N64USB.h"
void N64USB::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
@@ -85,6 +85,8 @@ void N64USB::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t inst
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)
{
return true;

View File

@@ -57,6 +57,7 @@ class N64USB: public GPHostDriver
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 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);
private:
N64USBState n64usb;

113
src/usbh/ps3/DInput.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include <stdint.h>
#include "pico/stdlib.h"
#include "tusb.h"
#include "class/hid/hid_host.h"
#include "usbh/ps3/DInput.h"
#include "usbh/shared/scaling.h"
void DInput::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
{
dinput.player_id = player_id;
tuh_hid_receive_report(dev_addr, instance);
}
void DInput::update_gamepad(Gamepad& gamepad, const DInputReport* dinput_report)
{
gamepad.reset_pad();
switch (dinput_report->direction)
{
case DINPUT_HAT_UP:
gamepad.buttons.up = true;
break;
case DINPUT_HAT_UPRIGHT:
gamepad.buttons.up = true;
gamepad.buttons.right = true;
break;
case DINPUT_HAT_RIGHT:
gamepad.buttons.right = true;
break;
case DINPUT_HAT_DOWNRIGHT:
gamepad.buttons.right = true;
gamepad.buttons.down = true;
break;
case DINPUT_HAT_DOWN:
gamepad.buttons.down = true;
break;
case DINPUT_HAT_DOWNLEFT:
gamepad.buttons.down = true;
gamepad.buttons.left = true;
break;
case DINPUT_HAT_LEFT:
gamepad.buttons.left = true;
break;
case DINPUT_HAT_UPLEFT:
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->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->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;
}
else if (dinput_report->l2_btn)
{
gamepad.triggers.l = 0xFF;
}
if (dinput_report->r2_axis > 0)
{
gamepad.triggers.r = dinput_report->r2_axis;
}
else if (dinput_report->r2_btn)
{
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);
}
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};
DInputReport dinput_report;
memcpy(&dinput_report, report, sizeof(dinput_report));
if (memcmp(&dinput_report, &prev_report, sizeof(dinput_report)) != 0)
{
update_gamepad(gamepad, &dinput_report);
prev_report = dinput_report;
}
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)
{
return true;
}

36
src/usbh/ps3/DInput.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef _DINPUT_H_
#define _DINPUT_H_
#include <stdint.h>
#include "usbh/GPHostDriver.h"
#include "usbd/descriptors/DInputDescriptors.h"
const usb_vid_pid_t dinput_devices[] =
{
{0x044F, 0xB324}, // ThrustMaster Dual Trigger (PS3 mode)
{0x0738, 0x8818}, // MadCatz Street Fighter IV Arcade FightStick
{0x0810, 0x0003}, // Personal Communication Systems, Inc. Generic
{0x146B, 0x0902}, // BigBen Interactive Wired Mini PS3 Game Controller
{0x2563, 0x0575} // SHANWAN 2In1 USB Joystick
};
struct DInputState
{
uint8_t player_id = {0};
};
class DInput : 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 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);
private:
DInputState dinput;
void update_gamepad(Gamepad& gp, const DInputReport* dinput_report);
};
#endif // _DINPUT_H_

View File

@@ -5,119 +5,211 @@
#include "usbh/ps3/Dualshock3.h"
#include "utilities/scaling.h"
#include "utilities/log.h"
#define PS3_REPORT_BUFFER_SIZE 48
#include "usbh/shared/scaling.h"
void Dualshock3::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
{
dualshock3.player_id = player_id;
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
dualshock3.response_count = 0;
dualshock3.reports_enabled = false;
if (vid == 0x054C && pid == 0x0268)
// tuh_hid_get_report not working correctly?
tusb_control_request_t setup_packet =
{
dualshock3.sixaxis = true;
.bmRequestType = 0xA1,
.bRequest = 0x01, // GET_REPORT
.wValue = (HID_REPORT_TYPE_FEATURE << 8) | 0xF2,
.wIndex = 0x0000,
.wLength = 17
};
tuh_xfer_s transfer =
{
.daddr = dev_addr,
.ep_addr = 0x00,
.setup = &setup_packet,
.buffer = (uint8_t*)&dualshock3.en_buffer,
.complete_cb = NULL,
.user_data = 0
};
if (tuh_control_xfer(&transfer))
{
get_report_complete_cb(dev_addr, instance);
}
enable_reports(dev_addr, instance);
tuh_hid_receive_report(dev_addr, instance);
// tuh_hid_get_report(dev_addr, instance, 0xF2, HID_REPORT_TYPE_FEATURE, &dualshock3.en_buffer, 17);
}
void Dualshock3::enable_reports(uint8_t dev_addr, uint8_t instance)
{
uint8_t cmd_buf[4];
cmd_buf[0] = 0x42;
// cmd_buf[1] = 0x0c;
cmd_buf[1] = 0x03;
cmd_buf[2] = 0x00;
cmd_buf[3] = 0x00;
if (tuh_hid_send_ready)
void Dualshock3::get_report_complete_cb(uint8_t dev_addr, uint8_t instance)
{
if (dualshock3.response_count == 0)
{
dualshock3.reports_enabled = tuh_hid_set_report(dev_addr, instance, 0xF4, HID_REPORT_TYPE_FEATURE, &cmd_buf, sizeof(cmd_buf));
tusb_control_request_t setup_packet =
{
.bmRequestType = 0xA1,
.bRequest = 0x01, // GET_REPORT
.wValue = (HID_REPORT_TYPE_FEATURE << 8) | 0xF2,
.wIndex = 0x0000,
.wLength = 17
};
tuh_xfer_s transfer =
{
.daddr = dev_addr,
.ep_addr = 0x00,
.setup = &setup_packet,
.buffer = (uint8_t*)&dualshock3.en_buffer,
.complete_cb = NULL,
.user_data = 0
};
if (tuh_control_xfer(&transfer))
{
dualshock3.response_count++;
get_report_complete_cb(dev_addr, instance);
return;
}
}
else if (dualshock3.response_count == 1)
{
tusb_control_request_t setup_packet =
{
.bmRequestType = 0xA1,
.bRequest = 0x01, // GET_REPORT
.wValue = (HID_REPORT_TYPE_FEATURE << 8) | 0xF2,
.wIndex = 0x0000,
.wLength = 8
};
// static uint8_t buffer[5] = {};
// buffer[0] = 0xF4;
// buffer[1] = 0x42;
// buffer[2] = 0x03;
// buffer[3] = 0x00;
// buffer[4] = 0x00;
tuh_xfer_s transfer =
{
.daddr = dev_addr,
.ep_addr = 0x00,
.setup = &setup_packet,
.buffer = (uint8_t*)&dualshock3.en_buffer,
.complete_cb = NULL,
.user_data = 0
};
// dualshock3.reports_enabled = tuh_hid_set_report(dev_addr, instance, 0, HID_REPORT_TYPE_FEATURE, buffer, sizeof(buffer));
if (tuh_control_xfer(&transfer))
{
dualshock3.response_count++;
get_report_complete_cb(dev_addr, instance);
return;
}
}
else if (dualshock3.response_count == 2)
{
dualshock3.response_count++;
// dualshock3.reports_enabled = tuh_hid_send_report(dev_addr, instance, 0, cmd_buf, sizeof(cmd_buf));
uint8_t default_report[] =
{
0x01, 0xff, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00
};
// if (dualshock3.reports_enabled)
memcpy(&dualshock3.out_report, &default_report, sizeof(Dualshock3OutReport));
dualshock3.out_report.leds_bitmap = 0x1 << (instance + 1);
dualshock3.out_report.led[instance].time_enabled = UINT8_MAX;
tusb_control_request_t setup_packet =
{
.bmRequestType = 0x21,
.bRequest = 0x09, // SET_REPORT
.wValue = 0x0201,
.wIndex = 0x0000,
.wLength = sizeof(Dualshock3OutReport)
};
tuh_xfer_s transfer =
{
.daddr = dev_addr,
.ep_addr = 0x00,
.setup = &setup_packet,
.buffer = (uint8_t*)&dualshock3.out_report,
.complete_cb = NULL,
.user_data = 0
};
if (tuh_control_xfer(&transfer))
{
dualshock3.reports_enabled = true;
tuh_hid_receive_report(dev_addr, 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)
{
// if (dualshock3.response_count == 0)
// {
// tuh_hid_receive_report(dev_addr, instance);
// if (tuh_hid_get_report(dev_addr, instance, 0xF2, HID_REPORT_TYPE_FEATURE, &dualshock3.en_buffer, 17))
// {
// dualshock3.response_count++;
// }
// }
// else if (dualshock3.response_count == 1)
// {
// if (tuh_hid_get_report(dev_addr, instance, 0xF5, HID_REPORT_TYPE_FEATURE, &dualshock3.en_buffer, 8))
// {
// dualshock3.response_count++;
// }
// }
// else if (dualshock3.response_count == 2)
// {
// dualshock3.response_count++;
// uint8_t default_report[] =
// {
// 0x01, 0xff, 0x00, 0xff, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0x00, 0x00, 0x00, 0x00, 0x00
// };
// memcpy(&dualshock3.out_report, &default_report, sizeof(Dualshock3OutReport));
// dualshock3.out_report.leds_bitmap = 0x1 << (instance + 1);
// dualshock3.out_report.led[instance].time_enabled = UINT8_MAX;
// tusb_control_request_t setup_packet =
// {
// .bmRequestType = 0x21,
// .bRequest = 0x09, // SET_REPORT
// .wValue = 0x0201,
// .wIndex = 0x0000,
// .wLength = sizeof(Dualshock3OutReport)
// };
// tuh_xfer_s transfer =
// {
// .daddr = dev_addr,
// .ep_addr = 0x00,
// .setup = &setup_packet,
// .buffer = (uint8_t*)&dualshock3.out_report,
// .complete_cb = NULL,
// .user_data = 0
// };
// if (tuh_control_xfer(&transfer))
// {
// dualshock3.reports_enabled = true;
// tuh_hid_receive_report(dev_addr, instance);
// }
// }
}
void Dualshock3::update_gamepad_from_dinput(Gamepad& gamepad, const DInputReport* dinput_report)
{
// gamepad.reset_pad();
// switch (dinput_report->direction)
// {
// case DINPUT_HAT_UP:
// gamepad.buttons.up = true;
// break;
// case DINPUT_HAT_UPRIGHT:
// gamepad.buttons.up = true;
// gamepad.buttons.right = true;
// break;
// case DINPUT_HAT_RIGHT:
// gamepad.buttons.right = true;
// break;
// case DINPUT_HAT_DOWNRIGHT:
// gamepad.buttons.right = true;
// gamepad.buttons.down = true;
// break;
// case DINPUT_HAT_DOWN:
// gamepad.buttons.down = true;
// break;
// case DINPUT_HAT_DOWNLEFT:
// gamepad.buttons.down = true;
// gamepad.buttons.left = true;
// break;
// case DINPUT_HAT_LEFT:
// gamepad.buttons.left = true;
// break;
// case DINPUT_HAT_UPLEFT:
// gamepad.buttons.up = true;
// gamepad.buttons.left = true;
// break;
// }
// if (dinput_report->square) gamepad.buttons.x = true;
// if (dinput_report->triangle) gamepad.buttons.y = true;
// if (dinput_report->cross) gamepad.buttons.a = true;
// if (dinput_report->circle) gamepad.buttons.b = true;
// if (dinput_report->select) gamepad.buttons.back = true;
// if (dinput_report->start) gamepad.buttons.start = true;
// if (dinput_report->ps) gamepad.buttons.sys = true;
// if (dinput_report->l3) gamepad.buttons.l3 = true;
// if (dinput_report->r3) gamepad.buttons.r3 = true;
// if (dinput_report->l1) gamepad.buttons.lb = true;
// if (dinput_report->r1) gamepad.buttons.rb = true;
// if (dinput_report->l2) gamepad.triggers.l = 0xFF;
// if (dinput_report->r2) gamepad.triggers.r = 0xFF;
// gamepad.joysticks.lx = scale_uint8_to_int16(dinput_report->lx_axis, false);
// gamepad.joysticks.ly = scale_uint8_to_int16(dinput_report->ly_axis, true);
// gamepad.joysticks.rx = scale_uint8_to_int16(dinput_report->rx_axis, false);
// gamepad.joysticks.ry = scale_uint8_to_int16(dinput_report->ry_axis, true);
}
void Dualshock3::update_gamepad_from_ds3(Gamepad& gamepad, const Dualshock3Report* ds3_data)
void Dualshock3::update_gamepad(Gamepad& gamepad, const Dualshock3Report* ds3_data)
{
gamepad.reset_pad();
@@ -141,8 +233,8 @@ void Dualshock3::update_gamepad_from_ds3(Gamepad& gamepad, const Dualshock3Repor
if (ds3_data->l1) gamepad.buttons.lb = true;
if (ds3_data->r1) gamepad.buttons.rb = true;
if (ds3_data->l2) gamepad.triggers.l = 0xFF;
if (ds3_data->r2) gamepad.triggers.r = 0xFF;
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);
@@ -152,28 +244,15 @@ void Dualshock3::update_gamepad_from_ds3(Gamepad& gamepad, const Dualshock3Repor
void Dualshock3::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{
if (dualshock3.sixaxis && !dualshock3.reports_enabled)
{
enable_reports(dev_addr, instance);
return;
}
static Dualshock3Report prev_report = { 0 };
Dualshock3Report ds3_report;
memcpy(&ds3_report, report, sizeof(ds3_report));
// if (!dualshock3.sixaxis)
// {
// static DInputReport prev_report = {0};
// DInputReport dinput_report;
// memcpy(&dinput_report, report, sizeof(dinput_report));
// update_gamepad_from_dinput(gp, &dinput_report);
// prev_report = dinput_report;
// }
// else
// {
static Dualshock3Report prev_report = { 0 };
Dualshock3Report ds3_report;
memcpy(&ds3_report, report, sizeof(ds3_report));
update_gamepad_from_ds3(gamepad, &ds3_report);
if (memcmp(&ds3_report, &prev_report, sizeof(ds3_report)) != 0)
{
update_gamepad(gamepad, &ds3_report);
prev_report = ds3_report;
// }
}
tuh_hid_receive_report(dev_addr, instance);
}
@@ -182,43 +261,52 @@ void Dualshock3::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8
bool Dualshock3::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{
if (dualshock3.sixaxis && !dualshock3.reports_enabled)
static absolute_time_t next_allowed_time = {0};
absolute_time_t current_time = get_absolute_time();
if (!dualshock3.reports_enabled)
{
enable_reports(dev_addr, instance);
return false;
}
else if (!dualshock3.sixaxis)
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;
if (gamepad.rumble.l > 0 || gamepad.rumble.r > 0 ||
absolute_time_diff_us(current_time, next_allowed_time) < 0)
{
return true;
tusb_control_request_t setup_packet =
{
.bmRequestType = 0x21,
.bRequest = 0x09,
.wValue = 0x0201,
.wIndex = 0x0000,
.wLength = sizeof(Dualshock3OutReport)
};
tuh_xfer_s transfer =
{
.daddr = dev_addr,
.ep_addr = 0x00,
.setup = &setup_packet,
.buffer = (uint8_t*)&dualshock3.out_report,
.complete_cb = NULL,
.user_data = 0
};
if (tuh_control_xfer(&transfer))
{
if (gamepad.rumble.l == 0 && gamepad.rumble.r == 0)
{
next_allowed_time = delayed_by_us(get_absolute_time(), 500000);
}
return true;
}
}
return true;
// uint8_t default_report[] =
// {
// 0x01, 0xff, 0x00, 0xff, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0xff, 0x27, 0x10, 0x00, 0x32,
// 0x00, 0x00, 0x00, 0x00, 0x00
// };
// Dualshock3OutReport out_report = {};
// // memcpy(&out_report, default_report, sizeof(out_report));
// // out_report.leds_bitmap |= 0x1 << (instance+1);
// // out_report.leds_bitmap = 0x02;
// // out_report.led->time_enabled = 0xFF;
// // out_report.led->duty_on = 0xFF;
// // out_report.rumble.right_duration = UINT8_MAX / 2;
// // if (gamepad.rumble.r > 0) out_report.rumble.right_motor_on = 1;
// // out_report.rumble.left_duration = UINT8_MAX / 2;
// // out_report.rumble.left_motor_force = gamepad.rumble.l;
// return tuh_hid_send_report(dev_addr, instance, 0x1, &out_report, sizeof(Dualshock3OutReport));
return false;
}

View File

@@ -12,19 +12,15 @@
const usb_vid_pid_t ps3_devices[] =
{
{0x054C, 0x0268}, // Sony Batoh (Dualshock 3)
// {0x045E, 0x028E}, // Voyee generic "P3", won't work, IDs are for a 360 controller (dumb)
{0x044F, 0xB324}, // ThrustMaster Dual Trigger (PS3 mode)
{0x0738, 0x8818}, // MadCatz Street Fighter IV Arcade FightStick
{0x0810, 0x0003}, // Personal Communication Systems, Inc. Generic
{0x146B, 0x0902}, // BigBen Interactive Wired Mini PS3 Game Controller
{0x2563, 0x0575} // SHANWAN 2In1 USB Joystick
};
struct Dualshock3State
{
uint8_t player_id = {0};
uint8_t player_id {0};
bool reports_enabled {false};
bool sixaxis {true};
uint8_t en_buffer[17];
Dualshock3OutReport out_report;
int response_count {0};
};
class Dualshock3 : public GPHostDriver
@@ -33,12 +29,12 @@ class Dualshock3 : public GPHostDriver
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 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);
private:
Dualshock3State dualshock3;
void enable_reports(uint8_t dev_addr, uint8_t instance);
void update_gamepad_from_ds3(Gamepad& gp, const Dualshock3Report* ds3_data);
void update_gamepad_from_dinput(Gamepad& gp, const DInputReport* dinput_report);
void update_gamepad(Gamepad& gp, const Dualshock3Report* ds3_data);
void get_report_complete_cb(uint8_t dev_addr, uint8_t instance);
};
#endif

View File

@@ -4,9 +4,7 @@
#include "CRC32.h"
#include "usbh/ps4/Dualshock4.h"
#include "utilities/scaling.h"
#include "Gamepad.h"
#include "usbh/shared/scaling.h"
#define REPORT_ID_GAMEPAD_STATE 0x11
@@ -125,6 +123,8 @@ void Dualshock4::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t
void Dualshock4::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, 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) {}
bool Dualshock4::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{
Dualshock4OutReport out_report = {0};

View File

@@ -128,6 +128,7 @@ class Dualshock4 : public GPHostDriver
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 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);
private:
Dualshock4State dualshock4;

View File

@@ -4,7 +4,7 @@
#include "usbh/ps5/Dualsense.h"
#include "utilities/scaling.h"
#include "usbh/shared/scaling.h"
void Dualsense::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
{
@@ -84,6 +84,8 @@ void Dualsense::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t i
void Dualsense::process_xinput_report(Gamepad& gp, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, 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) {}
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

View File

@@ -140,6 +140,7 @@ class Dualsense : public GPHostDriver
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 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);
private:
DualsenseState dualsense;

View File

@@ -79,6 +79,8 @@ void PSClassic::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t i
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)
{
return true;

View File

@@ -24,6 +24,7 @@ class PSClassic : public GPHostDriver
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 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);
private:
PSClassicState psclassic;

View File

@@ -0,0 +1,26 @@
#include "usbh/shared/scaling.h"
int16_t scale_uint8_to_int16(uint8_t value, bool invert)
{
const uint32_t scaling_factor = UINT16_MAX;
const int32_t bias = INT16_MIN;
int32_t scaled_value = ((uint32_t)value * scaling_factor) >> 8;
scaled_value += bias;
if (invert)
{
scaled_value = -scaled_value - 1;
}
if (scaled_value < INT16_MIN)
{
scaled_value = INT16_MIN;
}
else if (scaled_value > INT16_MAX)
{
scaled_value = INT16_MAX;
}
return (int16_t)scaled_value;
}

View File

@@ -3,7 +3,6 @@
#include <stdint.h>
// uint8_t scale_int16_to_uint8(int16_t value, bool invert);
int16_t scale_uint8_to_int16(uint8_t value, bool invert);
#endif // _SCALING_H_

View File

@@ -122,6 +122,8 @@ void SwitchPro::update_gamepad(Gamepad& gamepad, const SwitchProReport* switch_r
void SwitchPro::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, 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) {}
bool SwitchPro::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{
if (!switch_pro.handshake_sent)

View File

@@ -32,6 +32,7 @@ class SwitchPro : public GPHostDriver
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 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);
private:
SwitchProState switch_pro;

View File

@@ -5,7 +5,7 @@
#include "usbh/switch/SwitchWired.h"
#include "utilities/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)
@@ -94,6 +94,8 @@ void SwitchWired::update_gamepad(Gamepad& gamepad, const SwitchWiredReport* swit
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)
{
return true; // not aware of a wired switch gamepad with rumble

View File

@@ -56,6 +56,7 @@ class SwitchWired : public GPHostDriver
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 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);
private:
SwitchWiredState switch_wired;

View File

@@ -7,13 +7,13 @@
#include "usbh/tusb_host.h"
#include "usbh/tusb_host_manager.h"
#include "board_config.h"
#include "usbd/board_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()
{
#ifdef VCC_EN_PIN
#if USBD_BOARD == OGXM_ADA_FEATHER_USBH
gpio_init(VCC_EN_PIN);
gpio_set_dir(VCC_EN_PIN, GPIO_OUT);
gpio_put(VCC_EN_PIN, 1);

View File

@@ -1,10 +1,12 @@
#include "hardware/gpio.h"
#include "tusb.h"
#include "host/usbh.h"
#include "class/hid/hid_host.h"
#include "usbh/xinput/XInput.h"
#include "usbh/n64usb/N64USB.h"
#include "usbh/psclassic/PSClassic.h"
#include "usbh/ps3/DInput.h"
#include "usbh/ps3/Dualshock3.h"
#include "usbh/ps4/Dualshock4.h"
#include "usbh/ps5/Dualsense.h"
@@ -14,7 +16,7 @@
#include "usbh/shared/hid_class_driver.h"
#include "usbh/tusb_host_manager.h"
#include "board_config.h"
#include "usbd/board_config.h"
#include "Gamepad.h"
struct HostedDevice
@@ -40,7 +42,8 @@ const DeviceType device_types[] =
{
{ n64_devices, sizeof(n64_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_N64USB },
{ psc_devices, sizeof(psc_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_PSCLASSIC },
// { ps3_devices, sizeof(ps3_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_PS3 },
{ dinput_devices, sizeof(dinput_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_DINPUT},
{ ps3_devices, sizeof(ps3_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_PS3 },
{ ps4_devices, sizeof(ps4_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_PS4 },
{ ps5_devices, sizeof(ps5_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_PS5 },
{ switch_wired_devices, sizeof(switch_wired_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_SWITCH_WIRED },
@@ -75,6 +78,9 @@ void create_gamepad_driver(HostMode host_mode, int idx)
case HOST_MODE_HID_PSCLASSIC:
hosted_device[idx].gamepad_driver = new PSClassic();
break;
case HOST_MODE_HID_DINPUT:
hosted_device[idx].gamepad_driver = new DInput();
break;
case HOST_MODE_HID_PS3:
hosted_device[idx].gamepad_driver = new Dualshock3();
break;
@@ -136,10 +142,16 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (!hosted_device[i].gamepad_driver) free_slots++;
if (!hosted_device[i].gamepad_driver)
{
free_slots++;
}
}
if (free_slots == MAX_GAMEPADS) led_mounted_indicator(false);
if (free_slots == MAX_GAMEPADS)
{
led_mounted_indicator(false);
}
}
/* ----------- TUSB ----------- */
@@ -193,7 +205,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
}
}
tuh_hid_receive_report(dev_addr, instance);
// tuh_hid_receive_report(dev_addr, instance);
}
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
@@ -205,7 +217,9 @@ 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 (hosted_device[i].class_mounted &&
hosted_device[i].class_address == dev_addr &&
hosted_device[i].class_instance == instance)
{
if (hosted_device[i].gamepad_driver)
{
@@ -213,10 +227,23 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
}
}
}
tuh_hid_receive_report(dev_addr, instance);
}
// Current version of TinyUSB may be bugged so omitting this for now
// void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len)
// {
// 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)
// {
// hosted_device[i].gamepad_driver->hid_get_report_complete_cb(dev_addr, instance, report_id, report_type, len);
// }
// }
// }
/* ----------- XINPUT ----------- */
void tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, const xinputh_interface_t *xinput_itf)

View File

@@ -8,6 +8,7 @@ typedef enum
HOST_MODE_HID_SWITCH_PRO,
HOST_MODE_HID_SWITCH_WIRED,
HOST_MODE_HID_PSCLASSIC,
HOST_MODE_HID_DINPUT,
HOST_MODE_HID_PS3,
HOST_MODE_HID_PS4,
HOST_MODE_HID_PS5,

View File

@@ -59,6 +59,8 @@ void XInputHost::process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8
void XInputHost::process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, 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) {}
bool XInputHost::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
{
static int report_num = 0;

View File

@@ -20,6 +20,7 @@ class XInputHost : public GPHostDriver
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 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);
private:
XInputState xinput;

View File

@@ -1,48 +0,0 @@
#include "utilities/scaling.h"
// uint8_t scale_int16_to_uint8(int16_t value, bool invert)
// {
// if (value == INT16_MIN && invert)
// {
// return UINT8_MAX;
// }
//
// if (invert)
// {
// value = -value;
// }
//
// uint32_t scaled_value = static_cast<uint32_t>(value - INT16_MIN) * UINT8_MAX / (INT16_MAX - INT16_MIN);
//
// if (scaled_value > UINT8_MAX)
// {
// scaled_value = UINT8_MAX;
// }
//
// return static_cast<uint8_t>(scaled_value);
// }
int16_t scale_uint8_to_int16(uint8_t value, bool invert)
{
const uint32_t scaling_factor = UINT16_MAX;
const int32_t bias = INT16_MIN;
int32_t scaled_value = ((uint32_t)value * scaling_factor) >> 8;
scaled_value += bias;
if (invert)
{
scaled_value = -scaled_value - 1;
}
if (scaled_value < INT16_MIN)
{
scaled_value = INT16_MIN;
}
else if (scaled_value > INT16_MAX)
{
scaled_value = INT16_MAX;
}
return (int16_t)scaled_value;
}