new boards
This commit is contained in:
@@ -38,12 +38,12 @@ file(GLOB_RECURSE SOURCES
|
|||||||
"src/Gamepad.cpp"
|
"src/Gamepad.cpp"
|
||||||
|
|
||||||
"src/utilities/log.cpp"
|
"src/utilities/log.cpp"
|
||||||
"src/utilities/scaling.cpp"
|
|
||||||
|
|
||||||
"src/usbh/tusb_host_manager.cpp"
|
"src/usbh/tusb_host_manager.cpp"
|
||||||
"src/usbh/tusb_host.cpp"
|
"src/usbh/tusb_host.cpp"
|
||||||
"src/usbh/n64usb/N64USB.cpp"
|
"src/usbh/n64usb/N64USB.cpp"
|
||||||
"src/usbh/ps3/Dualshock3.cpp"
|
"src/usbh/ps3/Dualshock3.cpp"
|
||||||
|
"src/usbh/ps3/DInput.cpp"
|
||||||
"src/usbh/ps4/Dualshock4.cpp"
|
"src/usbh/ps4/Dualshock4.cpp"
|
||||||
"src/usbh/ps5/Dualsense.cpp"
|
"src/usbh/ps5/Dualsense.cpp"
|
||||||
"src/usbh/psclassic/PSClassic.cpp"
|
"src/usbh/psclassic/PSClassic.cpp"
|
||||||
@@ -51,6 +51,7 @@ file(GLOB_RECURSE SOURCES
|
|||||||
"src/usbh/switch/SwitchWired.cpp"
|
"src/usbh/switch/SwitchWired.cpp"
|
||||||
"src/usbh/xinput/XInput.cpp"
|
"src/usbh/xinput/XInput.cpp"
|
||||||
"src/usbh/shared/hid_class_driver.c"
|
"src/usbh/shared/hid_class_driver.c"
|
||||||
|
"src/usbh/shared/scaling.cpp"
|
||||||
|
|
||||||
"src/usbd/usbdriver.cpp"
|
"src/usbd/usbdriver.cpp"
|
||||||
"src/usbd/drivermanager.cpp"
|
"src/usbd/drivermanager.cpp"
|
||||||
|
|||||||
33
README.md
33
README.md
@@ -1,7 +1,9 @@
|
|||||||
# OGX-Mini
|
# 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
|
- Original Xbox
|
||||||
- Playstation 3
|
- Playstation 3
|
||||||
- Nintendo Switch (docked)
|
- Nintendo Switch (docked)
|
||||||
@@ -12,12 +14,14 @@ Firmware for the RP2040, setup for the [Adafruit Feather USB Host board](https:/
|
|||||||
### Wired controllers
|
### Wired controllers
|
||||||
- Original Xbox Duke and S
|
- Original Xbox Duke and S
|
||||||
- Xbox 360, One, Series, and Elite
|
- Xbox 360, One, Series, and Elite
|
||||||
|
- Dualshock 3 (PS3)
|
||||||
- Dualshock 4 (PS4)
|
- Dualshock 4 (PS4)
|
||||||
- Dualsense (PS5, Dualsense Edge should work but it's untested)
|
- Dualsense (PS5, Dualsense Edge should work but it's untested)
|
||||||
- Nintendo Switch Pro
|
- Nintendo Switch Pro
|
||||||
- Nintendo Switch wired (tested with PowerA brand)
|
- Nintendo Switch wired (tested with PowerA brand)
|
||||||
- Nintendo 64 USB (experimental, tested with RetroLink brand)
|
- Nintendo 64 USB (experimental, tested with RetroLink brand)
|
||||||
- Playstation Classic
|
- Playstation Classic
|
||||||
|
- Generic DInput
|
||||||
|
|
||||||
### Wireless adapters
|
### Wireless adapters
|
||||||
- Xbox 360 PC adapter (Microsoft or clones, syncs 1 controller)
|
- 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.
|
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
|
## 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.
|
If your third party controller isn't working, but the original version is listed above, send me the device's VID and PID and I'll add it so it's recognized properly.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
You can compile this for 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
|
## Special thanks
|
||||||
Thank you to Ryzee119 and the OpenStickCommunity, without their work this project would not exist.
|
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 "Gamepad.h"
|
||||||
#include "board_config.h"
|
#include "usbd/board_config.h"
|
||||||
|
|
||||||
void Gamepad::reset_pad()
|
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 "tusb.h"
|
||||||
|
|
||||||
#include "board_config.h"
|
#include "usbd/board_config.h"
|
||||||
#include "input_mode.h"
|
#include "input_mode.h"
|
||||||
|
|
||||||
#define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) // Address of the AIRCR register
|
#define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) // Address of the AIRCR register
|
||||||
@@ -103,8 +103,6 @@ enum InputMode get_input_mode()
|
|||||||
return INPUT_MODE_USBSERIAL;
|
return INPUT_MODE_USBSERIAL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// return INPUT_MODE_HID;
|
|
||||||
|
|
||||||
const uint8_t *stored_value = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
|
const uint8_t *stored_value = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
|
||||||
|
|
||||||
if (*stored_value >= INPUT_MODE_XINPUT && *stored_value <= INPUT_MODE_XBOXORIGINAL)
|
if (*stored_value >= INPUT_MODE_XINPUT && *stored_value <= INPUT_MODE_XBOXORIGINAL)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "usbd/drivers/gpdriver.h"
|
#include "usbd/drivers/gpdriver.h"
|
||||||
#include "Gamepad.h"
|
#include "Gamepad.h"
|
||||||
#include "input_mode.h"
|
#include "input_mode.h"
|
||||||
#include "board_config.h"
|
#include "usbd/board_config.h"
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#ifndef _TUSB_CONFIG_H_
|
#ifndef _TUSB_CONFIG_H_
|
||||||
#define _TUSB_CONFIG_H_
|
#define _TUSB_CONFIG_H_
|
||||||
|
|
||||||
#include "board_config.h"
|
#include "usbd/board_config.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
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_
|
#ifndef _GPHOSTDRIVER_H_
|
||||||
#define _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 init(uint8_t player_id, uint8_t dev_addr, uint8_t instance) = 0;
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) = 0;
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) = 0;
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) = 0;
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len) = 0;
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len) = 0;
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) = 0;
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // _GPHOSTDRIVER_H_
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
#include "utilities/scaling.h"
|
#include "usbh/shared/scaling.h"
|
||||||
#include "usbh/n64usb/N64USB.h"
|
#include "usbh/n64usb/N64USB.h"
|
||||||
|
|
||||||
void N64USB::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
|
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::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)
|
bool N64USB::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
return true;
|
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 init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
N64USBState n64usb;
|
N64USBState n64usb;
|
||||||
|
|||||||
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 "usbh/ps3/Dualshock3.h"
|
||||||
|
|
||||||
#include "utilities/scaling.h"
|
#include "usbh/shared/scaling.h"
|
||||||
#include "utilities/log.h"
|
|
||||||
|
|
||||||
#define PS3_REPORT_BUFFER_SIZE 48
|
|
||||||
|
|
||||||
void Dualshock3::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
|
void Dualshock3::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
dualshock3.player_id = player_id;
|
dualshock3.player_id = player_id;
|
||||||
|
dualshock3.response_count = 0;
|
||||||
uint16_t vid, pid;
|
dualshock3.reports_enabled = false;
|
||||||
tuh_vid_pid_get(dev_addr, &vid, &pid);
|
|
||||||
|
|
||||||
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_get_report(dev_addr, instance, 0xF2, HID_REPORT_TYPE_FEATURE, &dualshock3.en_buffer, 17);
|
||||||
tuh_hid_receive_report(dev_addr, instance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dualshock3::enable_reports(uint8_t dev_addr, uint8_t instance)
|
void Dualshock3::get_report_complete_cb(uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
uint8_t cmd_buf[4];
|
if (dualshock3.response_count == 0)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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] = {};
|
tuh_xfer_s transfer =
|
||||||
// buffer[0] = 0xF4;
|
{
|
||||||
// buffer[1] = 0x42;
|
.daddr = dev_addr,
|
||||||
// buffer[2] = 0x03;
|
.ep_addr = 0x00,
|
||||||
// buffer[3] = 0x00;
|
.setup = &setup_packet,
|
||||||
// buffer[4] = 0x00;
|
.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)
|
void Dualshock3::update_gamepad(Gamepad& gamepad, const Dualshock3Report* ds3_data)
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
gamepad.reset_pad();
|
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->l1) gamepad.buttons.lb = true;
|
||||||
if (ds3_data->r1) gamepad.buttons.rb = true;
|
if (ds3_data->r1) gamepad.buttons.rb = true;
|
||||||
|
|
||||||
if (ds3_data->l2) gamepad.triggers.l = 0xFF;
|
gamepad.triggers.l = ds3_data->l2_axis;
|
||||||
if (ds3_data->r2) gamepad.triggers.r = 0xFF;
|
gamepad.triggers.r = ds3_data->r2_axis;
|
||||||
|
|
||||||
gamepad.joysticks.lx = scale_uint8_to_int16(ds3_data->left_x, false);
|
gamepad.joysticks.lx = scale_uint8_to_int16(ds3_data->left_x, false);
|
||||||
gamepad.joysticks.ly = scale_uint8_to_int16(ds3_data->left_y, true);
|
gamepad.joysticks.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)
|
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)
|
static Dualshock3Report prev_report = { 0 };
|
||||||
{
|
Dualshock3Report ds3_report;
|
||||||
enable_reports(dev_addr, instance);
|
memcpy(&ds3_report, report, sizeof(ds3_report));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (!dualshock3.sixaxis)
|
if (memcmp(&ds3_report, &prev_report, sizeof(ds3_report)) != 0)
|
||||||
// {
|
{
|
||||||
// static DInputReport prev_report = {0};
|
update_gamepad(gamepad, &ds3_report);
|
||||||
// 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);
|
|
||||||
prev_report = ds3_report;
|
prev_report = ds3_report;
|
||||||
// }
|
}
|
||||||
|
|
||||||
tuh_hid_receive_report(dev_addr, instance);
|
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)
|
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;
|
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;
|
return false;
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
@@ -12,19 +12,15 @@
|
|||||||
const usb_vid_pid_t ps3_devices[] =
|
const usb_vid_pid_t ps3_devices[] =
|
||||||
{
|
{
|
||||||
{0x054C, 0x0268}, // Sony Batoh (Dualshock 3)
|
{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
|
struct Dualshock3State
|
||||||
{
|
{
|
||||||
uint8_t player_id = {0};
|
uint8_t player_id {0};
|
||||||
bool reports_enabled {false};
|
bool reports_enabled {false};
|
||||||
bool sixaxis {true};
|
uint8_t en_buffer[17];
|
||||||
|
Dualshock3OutReport out_report;
|
||||||
|
int response_count {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dualshock3 : public GPHostDriver
|
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 init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
Dualshock3State dualshock3;
|
Dualshock3State dualshock3;
|
||||||
void enable_reports(uint8_t dev_addr, uint8_t instance);
|
void update_gamepad(Gamepad& gp, const Dualshock3Report* ds3_data);
|
||||||
void update_gamepad_from_ds3(Gamepad& gp, const Dualshock3Report* ds3_data);
|
void get_report_complete_cb(uint8_t dev_addr, uint8_t instance);
|
||||||
void update_gamepad_from_dinput(Gamepad& gp, const DInputReport* dinput_report);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -4,9 +4,7 @@
|
|||||||
#include "CRC32.h"
|
#include "CRC32.h"
|
||||||
|
|
||||||
#include "usbh/ps4/Dualshock4.h"
|
#include "usbh/ps4/Dualshock4.h"
|
||||||
|
#include "usbh/shared/scaling.h"
|
||||||
#include "utilities/scaling.h"
|
|
||||||
#include "Gamepad.h"
|
|
||||||
|
|
||||||
#define REPORT_ID_GAMEPAD_STATE 0x11
|
#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::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)
|
bool Dualshock4::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
Dualshock4OutReport out_report = {0};
|
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 init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
Dualshock4State dualshock4;
|
Dualshock4State dualshock4;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "usbh/ps5/Dualsense.h"
|
#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)
|
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::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)
|
bool Dualsense::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
// need to figure out if the flags are necessary and how the LEDs work
|
// need to figure out if the flags are necessary and how the LEDs work
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ class Dualsense : public GPHostDriver
|
|||||||
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
DualsenseState dualsense;
|
DualsenseState dualsense;
|
||||||
|
|||||||
@@ -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::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)
|
bool PSClassic::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
return true;
|
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 init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
PSClassicState psclassic;
|
PSClassicState psclassic;
|
||||||
|
|||||||
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>
|
#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);
|
int16_t scale_uint8_to_int16(uint8_t value, bool invert);
|
||||||
|
|
||||||
#endif // _SCALING_H_
|
#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::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)
|
bool SwitchPro::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
if (!switch_pro.handshake_sent)
|
if (!switch_pro.handshake_sent)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class SwitchPro : public GPHostDriver
|
|||||||
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
SwitchProState switch_pro;
|
SwitchProState switch_pro;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "usbh/switch/SwitchWired.h"
|
#include "usbh/switch/SwitchWired.h"
|
||||||
|
|
||||||
#include "utilities/scaling.h"
|
#include "usbh/shared/scaling.h"
|
||||||
#include "usbd/descriptors/SwitchDescriptors.h"
|
#include "usbd/descriptors/SwitchDescriptors.h"
|
||||||
|
|
||||||
void SwitchWired::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
|
void SwitchWired::init(uint8_t player_id, uint8_t dev_addr, uint8_t instance)
|
||||||
@@ -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::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)
|
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
|
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 init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
SwitchWiredState switch_wired;
|
SwitchWiredState switch_wired;
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
#include "usbh/tusb_host.h"
|
#include "usbh/tusb_host.h"
|
||||||
#include "usbh/tusb_host_manager.h"
|
#include "usbh/tusb_host_manager.h"
|
||||||
#include "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 }
|
#define PIO_USB_CONFIG { PIO_USB_DP_PIN, PIO_USB_TX_DEFAULT, PIO_SM_USB_TX_DEFAULT, PIO_USB_DMA_TX_DEFAULT, PIO_USB_RX_DEFAULT, PIO_SM_USB_RX_DEFAULT, PIO_SM_USB_EOP_DEFAULT, NULL, PIO_USB_DEBUG_PIN_NONE, PIO_USB_DEBUG_PIN_NONE, false, PIO_USB_PINOUT_DPDM }
|
||||||
|
|
||||||
void board_setup()
|
void board_setup()
|
||||||
{
|
{
|
||||||
#ifdef VCC_EN_PIN
|
#if USBD_BOARD == OGXM_ADA_FEATHER_USBH
|
||||||
gpio_init(VCC_EN_PIN);
|
gpio_init(VCC_EN_PIN);
|
||||||
gpio_set_dir(VCC_EN_PIN, GPIO_OUT);
|
gpio_set_dir(VCC_EN_PIN, GPIO_OUT);
|
||||||
gpio_put(VCC_EN_PIN, 1);
|
gpio_put(VCC_EN_PIN, 1);
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#include "hardware/gpio.h"
|
#include "hardware/gpio.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "host/usbh.h"
|
#include "host/usbh.h"
|
||||||
|
#include "class/hid/hid_host.h"
|
||||||
|
|
||||||
#include "usbh/xinput/XInput.h"
|
#include "usbh/xinput/XInput.h"
|
||||||
#include "usbh/n64usb/N64USB.h"
|
#include "usbh/n64usb/N64USB.h"
|
||||||
#include "usbh/psclassic/PSClassic.h"
|
#include "usbh/psclassic/PSClassic.h"
|
||||||
|
#include "usbh/ps3/DInput.h"
|
||||||
#include "usbh/ps3/Dualshock3.h"
|
#include "usbh/ps3/Dualshock3.h"
|
||||||
#include "usbh/ps4/Dualshock4.h"
|
#include "usbh/ps4/Dualshock4.h"
|
||||||
#include "usbh/ps5/Dualsense.h"
|
#include "usbh/ps5/Dualsense.h"
|
||||||
@@ -14,7 +16,7 @@
|
|||||||
#include "usbh/shared/hid_class_driver.h"
|
#include "usbh/shared/hid_class_driver.h"
|
||||||
#include "usbh/tusb_host_manager.h"
|
#include "usbh/tusb_host_manager.h"
|
||||||
|
|
||||||
#include "board_config.h"
|
#include "usbd/board_config.h"
|
||||||
#include "Gamepad.h"
|
#include "Gamepad.h"
|
||||||
|
|
||||||
struct HostedDevice
|
struct HostedDevice
|
||||||
@@ -40,7 +42,8 @@ const DeviceType device_types[] =
|
|||||||
{
|
{
|
||||||
{ n64_devices, sizeof(n64_devices) / sizeof(usb_vid_pid_t), HOST_MODE_HID_N64USB },
|
{ 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 },
|
{ 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 },
|
{ 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 },
|
{ 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 },
|
{ 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:
|
case HOST_MODE_HID_PSCLASSIC:
|
||||||
hosted_device[idx].gamepad_driver = new PSClassic();
|
hosted_device[idx].gamepad_driver = new PSClassic();
|
||||||
break;
|
break;
|
||||||
|
case HOST_MODE_HID_DINPUT:
|
||||||
|
hosted_device[idx].gamepad_driver = new DInput();
|
||||||
|
break;
|
||||||
case HOST_MODE_HID_PS3:
|
case HOST_MODE_HID_PS3:
|
||||||
hosted_device[idx].gamepad_driver = new Dualshock3();
|
hosted_device[idx].gamepad_driver = new Dualshock3();
|
||||||
break;
|
break;
|
||||||
@@ -136,10 +142,16 @@ void unmount_gamepad(uint8_t dev_addr, uint8_t instance)
|
|||||||
|
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
if (!hosted_device[i].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 ----------- */
|
/* ----------- 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)
|
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++)
|
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)
|
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 ----------- */
|
/* ----------- XINPUT ----------- */
|
||||||
|
|
||||||
void tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, const xinputh_interface_t *xinput_itf)
|
void tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, const xinputh_interface_t *xinput_itf)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ typedef enum
|
|||||||
HOST_MODE_HID_SWITCH_PRO,
|
HOST_MODE_HID_SWITCH_PRO,
|
||||||
HOST_MODE_HID_SWITCH_WIRED,
|
HOST_MODE_HID_SWITCH_WIRED,
|
||||||
HOST_MODE_HID_PSCLASSIC,
|
HOST_MODE_HID_PSCLASSIC,
|
||||||
|
HOST_MODE_HID_DINPUT,
|
||||||
HOST_MODE_HID_PS3,
|
HOST_MODE_HID_PS3,
|
||||||
HOST_MODE_HID_PS4,
|
HOST_MODE_HID_PS4,
|
||||||
HOST_MODE_HID_PS5,
|
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::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)
|
bool XInputHost::send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
static int report_num = 0;
|
static int report_num = 0;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class XInputHost : public GPHostDriver
|
|||||||
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
virtual void init(uint8_t player_id, uint8_t dev_addr, uint8_t instance);
|
||||||
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
virtual void process_hid_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
virtual void process_xinput_report(Gamepad& gamepad, uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* report, uint16_t len);
|
||||||
|
virtual void hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len);
|
||||||
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
virtual bool send_fb_data(const Gamepad& gamepad, uint8_t dev_addr, uint8_t instance);
|
||||||
private:
|
private:
|
||||||
XInputState xinput;
|
XInputState xinput;
|
||||||
|
|||||||
@@ -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