new boards
This commit is contained in:
@@ -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"
|
||||
|
||||
33
README.md
33
README.md
@@ -1,7 +1,9 @@
|
||||
# OGX-Mini
|
||||

|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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:
|
||||

|
||||
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.
|
||||
6
hardware/BOM_OGX-Mini_RP2040-Zero_Interposer.csv
Normal file
6
hardware/BOM_OGX-Mini_RP2040-Zero_Interposer.csv
Normal 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,,,,,,,
|
||||
|
BIN
hardware/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip
Normal file
BIN
hardware/Gerber_OGX-Mini_RP2040-Zero_Interposer.zip
Normal file
Binary file not shown.
3
hardware/README.md
Normal file
3
hardware/README.md
Normal 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.
|
||||
1951
hardware/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf
Normal file
1951
hardware/Schematic_OGX-Mini_RP2040-Zero_Interposer.pdf
Normal file
File diff suppressed because it is too large
Load Diff
BIN
images/OGX-Mini-github.jpg
Normal file
BIN
images/OGX-Mini-github.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 507 KiB |
BIN
images/OGX-Mini-rpzero-int.jpg
Normal file
BIN
images/OGX-Mini-rpzero-int.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 594 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB |
@@ -1,5 +1,5 @@
|
||||
#include "Gamepad.h"
|
||||
#include "board_config.h"
|
||||
#include "usbd/board_config.h"
|
||||
|
||||
void Gamepad::reset_pad()
|
||||
{
|
||||
|
||||
@@ -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_
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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" {
|
||||
|
||||
2
src/usbd
2
src/usbd
Submodule src/usbd updated: 793d355a86...1c54b608ef
19
src/usbd_config.h
Normal file
19
src/usbd_config.h
Normal 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_
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
|
||||
@@ -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
113
src/usbh/ps3/DInput.cpp
Normal 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
36
src/usbh/ps3/DInput.h
Normal 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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
26
src/usbh/shared/scaling.cpp
Normal file
26
src/usbh/shared/scaling.cpp
Normal 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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user