Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88a84fe6f2 | ||
|
|
91906866a8 | ||
|
|
22cabd06dc | ||
|
|
bf52296e60 | ||
|
|
9bdc0dbb33 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,5 +3,4 @@ build
|
|||||||
release
|
release
|
||||||
generated
|
generated
|
||||||
tools
|
tools
|
||||||
.ignore
|
.ignore
|
||||||
src/usbh/tusb_hid/experiment
|
|
||||||
@@ -40,6 +40,7 @@ file(GLOB_RECURSE SOURCES
|
|||||||
"src/usbd/shared/*"
|
"src/usbd/shared/*"
|
||||||
"src/usbd/switch/*"
|
"src/usbd/switch/*"
|
||||||
"src/usbd/xboxog/*"
|
"src/usbd/xboxog/*"
|
||||||
|
"src/usbd/dinput/*"
|
||||||
"src/usbd/xinput/*")
|
"src/usbd/xinput/*")
|
||||||
|
|
||||||
# Firmware
|
# Firmware
|
||||||
@@ -59,7 +60,8 @@ add_compile_definitions(FEATHER_RP2040)
|
|||||||
|
|
||||||
#------- USB host data +/- will be GPIO 0/1 ---------------------------------------#
|
#------- USB host data +/- will be GPIO 0/1 ---------------------------------------#
|
||||||
|
|
||||||
# add_compile_definitions(HOST_DEBUG) # CDC device, include utilities/log.h and use log() as you would printf()
|
#------- CDC MODE --------#
|
||||||
|
# add_compile_definitions(HOST_DEBUG) # makes RP2040 a CDC device, include "utilities/log.h" and use log() as you would printf()
|
||||||
|
|
||||||
|
|
||||||
target_link_libraries(${NAME}
|
target_link_libraries(${NAME}
|
||||||
@@ -79,6 +81,7 @@ target_link_libraries(${NAME}
|
|||||||
tinyusb_host
|
tinyusb_host
|
||||||
tinyusb_pico_pio_usb
|
tinyusb_pico_pio_usb
|
||||||
CRC32
|
CRC32
|
||||||
|
hid_parser
|
||||||
cmsis_core
|
cmsis_core
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Firmware for the RP2040, setup for the [Adafruit Feather USB Host board](https:/
|
|||||||
|
|
||||||
### Wireless adapters
|
### Wireless adapters
|
||||||
- Xbox 360 PC adapter (Microsoft or clones, syncs 1 controller)
|
- Xbox 360 PC adapter (Microsoft or clones, syncs 1 controller)
|
||||||
- 8Bitdo v1 and v2 Bluetooth adapters (set to XInput mode)
|
- 8Bitdo v1 and v2 Bluetooth adapters
|
||||||
- Most wireless adapters that present themselves as Switch/XInput/PlayStation controllers should work
|
- Most wireless adapters that present themselves as Switch/XInput/PlayStation controllers should work
|
||||||
|
|
||||||
Note: There are some third party controllers that can change their VID/PID, these might not work correctly.
|
Note: There are some third party controllers that can change their VID/PID, these might not work correctly.
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "usbh/tusb_hid/ps3.h"
|
// #include "usbh/tusb_hid/ps3.h"
|
||||||
#include "usbh/tusb_hid/ps4.h"
|
// #include "usbh/tusb_hid/ps4.h"
|
||||||
#include "usbh/tusb_hid/ps5.h"
|
// #include "usbh/tusb_hid/ps5.h"
|
||||||
#include "usbh/tusb_xinput/xinput_host.h"
|
#include "usbh/tusb_xinput/xinput_host.h"
|
||||||
|
|
||||||
struct GamepadState{
|
struct GamepadState{
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
#define HID_ENDPOINT_SIZE 64
|
#define HID_ENDPOINT_SIZE 64
|
||||||
|
|
||||||
|
// Mac OS-X and Linux automatically load the correct drivers. On
|
||||||
|
// Windows, even though the driver is supplied by Microsoft, an
|
||||||
|
// INF file is needed to load the driver. These numbers need to
|
||||||
|
// match the INF file.
|
||||||
|
// #define VENDOR_ID 0x10C4
|
||||||
|
// #define PRODUCT_ID 0x82C0
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
*
|
*
|
||||||
* Endpoint Buffer Configuration
|
* Endpoint Buffer Configuration
|
||||||
@@ -29,6 +36,21 @@
|
|||||||
#define DINPUT_HAT_UPLEFT 0x07
|
#define DINPUT_HAT_UPLEFT 0x07
|
||||||
#define DINPUT_HAT_NOTHING 0x08
|
#define DINPUT_HAT_NOTHING 0x08
|
||||||
|
|
||||||
|
#define DINPUT_MASK_SQUARE (1U << 0)
|
||||||
|
#define DINPUT_MASK_CROSS (1U << 1)
|
||||||
|
#define DINPUT_MASK_CIRCLE (1U << 2)
|
||||||
|
#define DINPUT_MASK_TRIANGLE (1U << 3)
|
||||||
|
#define DINPUT_MASK_L1 (1U << 4)
|
||||||
|
#define DINPUT_MASK_R1 (1U << 5)
|
||||||
|
#define DINPUT_MASK_L2 (1U << 6)
|
||||||
|
#define DINPUT_MASK_R2 (1U << 7)
|
||||||
|
#define DINPUT_MASK_SELECT (1U << 8)
|
||||||
|
#define DINPUT_MASK_START (1U << 9)
|
||||||
|
#define DINPUT_MASK_L3 (1U << 10)
|
||||||
|
#define DINPUT_MASK_R3 (1U << 11)
|
||||||
|
#define DINPUT_MASK_PS (1U << 12)
|
||||||
|
#define DINPUT_MASK_TP (1U << 13)
|
||||||
|
|
||||||
#define DINPUT_JOYSTICK_MIN 0x00
|
#define DINPUT_JOYSTICK_MIN 0x00
|
||||||
#define DINPUT_JOYSTICK_MID 0x80
|
#define DINPUT_JOYSTICK_MID 0x80
|
||||||
#define DINPUT_JOYSTICK_MAX 0xFF
|
#define DINPUT_JOYSTICK_MAX 0xFF
|
||||||
@@ -96,29 +118,29 @@ typedef struct __attribute((packed, aligned(1)))
|
|||||||
uint8_t r2_axis;
|
uint8_t r2_axis;
|
||||||
} DInputReport;
|
} DInputReport;
|
||||||
|
|
||||||
// struct DInputLed {
|
struct DInputLed {
|
||||||
// uint8_t time_enabled; /* the total time the led is active (0xff means forever) */
|
uint8_t time_enabled; /* the total time the led is active (0xff means forever) */
|
||||||
// uint8_t duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */
|
uint8_t duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */
|
||||||
// uint8_t enabled;
|
uint8_t enabled;
|
||||||
// uint8_t duty_off; /* % of duty_length the led is off (0xff means 100%) */
|
uint8_t duty_off; /* % of duty_length the led is off (0xff means 100%) */
|
||||||
// uint8_t duty_on; /* % of duty_length the led is on (0xff mean 100%) */
|
uint8_t duty_on; /* % of duty_length the led is on (0xff mean 100%) */
|
||||||
// } __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
// struct DInputRumble {
|
struct DInputRumble {
|
||||||
// uint8_t padding;
|
uint8_t padding;
|
||||||
// uint8_t right_duration; /* Right motor duration (0xff means forever) */
|
uint8_t right_duration; /* Right motor duration (0xff means forever) */
|
||||||
// uint8_t right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
|
uint8_t right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
|
||||||
// uint8_t left_duration; /* Left motor duration (0xff means forever) */
|
uint8_t left_duration; /* Left motor duration (0xff means forever) */
|
||||||
// uint8_t left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
|
uint8_t left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
|
||||||
// } __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
// struct DInputOutReport {
|
struct DInputOutReport {
|
||||||
// struct DInputRumble rumble;
|
struct DInputRumble rumble;
|
||||||
// uint8_t padding[4];
|
uint8_t padding[4];
|
||||||
// uint8_t leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
|
uint8_t leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
|
||||||
// struct DInputLed led[4]; /* LEDx at (4 - x) */
|
struct DInputLed led[4]; /* LEDx at (4 - x) */
|
||||||
// struct DInputLed _reserved; /* LED5, not actually soldered */
|
struct DInputLed _reserved; /* LED5, not actually soldered */
|
||||||
// } __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
static const uint8_t dinput_string_language[] = { 0x09, 0x04 };
|
static const uint8_t dinput_string_language[] = { 0x09, 0x04 };
|
||||||
static const uint8_t dinput_string_manufacturer[] = "SHANWAN";
|
static const uint8_t dinput_string_manufacturer[] = "SHANWAN";
|
||||||
|
|||||||
@@ -213,13 +213,13 @@ static const uint8_t hid_report_descriptor[] =
|
|||||||
|
|
||||||
static const uint8_t hid_hid_descriptor[] =
|
static const uint8_t hid_hid_descriptor[] =
|
||||||
{
|
{
|
||||||
0x09, // bLength
|
0x09, // bLength
|
||||||
0x21, // bDescriptorType (HID)
|
0x21, // bDescriptorType (HID)
|
||||||
0x11, 0x01, // bcdHID 1.11
|
0x11, 0x01, // bcdHID 1.11
|
||||||
0x00, // bCountryCode
|
0x00, // bCountryCode
|
||||||
0x01, // bNumDescriptors
|
0x01, // bNumDescriptors
|
||||||
0x22, // bDescriptorType[0] (HID)
|
0x22, // bDescriptorType[0] (HID)
|
||||||
sizeof(hid_report_descriptor), 0x00, // wDescriptorLength[0] 90
|
sizeof(hid_report_descriptor), 0x00, // wDescriptorLength[0] 90
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ typedef struct __attribute((packed, aligned(1)))
|
|||||||
int16_t acceler_z;
|
int16_t acceler_z;
|
||||||
|
|
||||||
int16_t velocity_z;
|
int16_t velocity_z;
|
||||||
} Dualshock3Report;
|
} DualShock3Report;
|
||||||
|
|
||||||
struct sixaxis_led {
|
struct sixaxis_led {
|
||||||
uint8_t time_enabled; /* the total time the led is active (0xff means forever) */
|
uint8_t time_enabled; /* the total time the led is active (0xff means forever) */
|
||||||
|
|||||||
@@ -5,12 +5,6 @@
|
|||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "bsp/board_api.h"
|
#include "bsp/board_api.h"
|
||||||
|
|
||||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
|
||||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
|
||||||
*
|
|
||||||
* Auto ProductID layout's Bitmap:
|
|
||||||
* [MSB] HID | MSC | CDC [LSB]
|
|
||||||
*/
|
|
||||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||||
@@ -24,8 +18,6 @@ tusb_desc_device_t const usbserial_device_descriptor =
|
|||||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||||
.bcdUSB = USB_BCD,
|
.bcdUSB = USB_BCD,
|
||||||
|
|
||||||
// Use Interface Association Descriptor (IAD) for CDC
|
|
||||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
|
||||||
.bDeviceClass = TUSB_CLASS_MISC,
|
.bDeviceClass = TUSB_CLASS_MISC,
|
||||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||||
@@ -72,7 +64,6 @@ enum {
|
|||||||
STRID_SERIAL,
|
STRID_SERIAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
// array of pointer to string descriptors
|
|
||||||
char const *string_desc_arr[] =
|
char const *string_desc_arr[] =
|
||||||
{
|
{
|
||||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||||
|
|||||||
@@ -1,60 +1,41 @@
|
|||||||
|
#include <pico/stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
|
||||||
#include "pico/multicore.h"
|
|
||||||
#include "hardware/flash.h"
|
#include "hardware/flash.h"
|
||||||
|
#include "hardware/sync.h"
|
||||||
#include "tusb.h"
|
|
||||||
|
|
||||||
#include "input_mode.h"
|
#include "input_mode.h"
|
||||||
|
|
||||||
#define AIRCR_REG (*((volatile uint32_t *)(0xE000ED0C))) // Address of the AIRCR register
|
#define AIRCR_Register (*((volatile uint32_t*)(PPB_BASE + 0x0ED0C)))
|
||||||
#define AIRCR_SYSRESETREQ (1 << 2) // Position of SYSRESETREQ bit in AIRCR
|
|
||||||
#define AIRCR_VECTKEY (0x5FA << 16) // VECTKEY value
|
|
||||||
|
|
||||||
#define FLASH_TARGET_OFFSET (256 * 1024)
|
#define EEPROM_SIZE 1
|
||||||
#define FLASH_SIZE_BYTES (2 * 1024 * 1024)
|
#define EEPROM_FLASH_TARGET_OFFSET (2 * 1024 * 1024 - EEPROM_SIZE)
|
||||||
|
|
||||||
void system_reset() {
|
void store_input_mode(enum InputMode mode)
|
||||||
AIRCR_REG = AIRCR_VECTKEY | AIRCR_SYSRESETREQ;
|
|
||||||
while(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool store_input_mode(enum InputMode new_mode)
|
|
||||||
{
|
{
|
||||||
int buf[FLASH_PAGE_SIZE/sizeof(int)];
|
uint8_t data = (uint8_t)mode;
|
||||||
memset(buf, 0xFF, FLASH_PAGE_SIZE);
|
|
||||||
int saved_mode = new_mode; // changed to uint8?
|
|
||||||
|
|
||||||
buf[0] = saved_mode;
|
uint32_t flash_offset = EEPROM_FLASH_TARGET_OFFSET % FLASH_SECTOR_SIZE;
|
||||||
|
uint32_t flash_sector_base = EEPROM_FLASH_TARGET_OFFSET - flash_offset;
|
||||||
|
|
||||||
uint32_t saved_interrupts = save_and_disable_interrupts();
|
uint8_t new_sector_content[FLASH_SECTOR_SIZE];
|
||||||
|
|
||||||
flash_range_erase((FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE), FLASH_SECTOR_SIZE);
|
memcpy(new_sector_content, (const void *)(XIP_BASE + flash_sector_base), FLASH_SECTOR_SIZE);
|
||||||
flash_range_program((FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE), (uint8_t *)buf, FLASH_PAGE_SIZE);
|
|
||||||
|
|
||||||
restore_interrupts(saved_interrupts);
|
new_sector_content[flash_offset] = data;
|
||||||
|
|
||||||
return true;
|
flash_range_erase(flash_sector_base, FLASH_SECTOR_SIZE);
|
||||||
|
flash_range_program(flash_sector_base, new_sector_content, FLASH_SECTOR_SIZE);
|
||||||
// const uint8_t *flash_target_contents = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
|
|
||||||
|
|
||||||
// if ((uint8_t)saved_mode != *flash_target_contents)
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool change_input_mode(Gamepad previous_gamepad)
|
void change_input_mode(Gamepad previous_gamepad)
|
||||||
{
|
{
|
||||||
if (!previous_gamepad.state.start)
|
if (!previous_gamepad.state.start)
|
||||||
{
|
{
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputMode new_mode;
|
InputMode new_mode;
|
||||||
|
|
||||||
if (previous_gamepad.state.up)
|
if (previous_gamepad.state.up)
|
||||||
@@ -77,26 +58,21 @@ bool change_input_mode(Gamepad previous_gamepad)
|
|||||||
{
|
{
|
||||||
new_mode = INPUT_MODE_PSCLASSIC;
|
new_mode = INPUT_MODE_PSCLASSIC;
|
||||||
}
|
}
|
||||||
|
// else if (previous_gamepad.state.b)
|
||||||
bool mode_stored = false;
|
// {
|
||||||
|
// new_mode = INPUT_MODE_USBSERIAL;
|
||||||
if (new_mode)
|
// }
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// tinyusb needs to be kaput in order to write to the flash
|
return;
|
||||||
// just hangs otherwise
|
|
||||||
|
|
||||||
tud_disconnect();
|
|
||||||
sleep_ms(300);
|
|
||||||
multicore_reset_core1(); // stop tusb host
|
|
||||||
|
|
||||||
if (store_input_mode(new_mode))
|
|
||||||
{
|
|
||||||
system_reset(); // reset rp2040
|
|
||||||
mode_stored = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mode_stored;
|
store_input_mode(new_mode);
|
||||||
|
sleep_ms(200);
|
||||||
|
|
||||||
|
// restart the rp2040
|
||||||
|
AIRCR_Register = 0x5FA0004;
|
||||||
|
sleep_ms(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InputMode get_input_mode()
|
enum InputMode get_input_mode()
|
||||||
@@ -105,11 +81,12 @@ enum InputMode get_input_mode()
|
|||||||
return INPUT_MODE_USBSERIAL;
|
return INPUT_MODE_USBSERIAL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint8_t *stored_value = (const uint8_t *)(XIP_BASE + FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
|
const uint8_t* flash_addr = (const uint8_t*)(XIP_BASE + EEPROM_FLASH_TARGET_OFFSET);
|
||||||
|
uint8_t stored_value = *flash_addr;
|
||||||
|
|
||||||
if (*stored_value >= INPUT_MODE_XINPUT && *stored_value <= INPUT_MODE_XBOXORIGINAL)
|
if (stored_value >= INPUT_MODE_XINPUT && stored_value <= INPUT_MODE_XBOXORIGINAL)
|
||||||
{
|
{
|
||||||
return(enum InputMode)*stored_value;
|
return(enum InputMode)stored_value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,17 +9,18 @@ extern "C" {
|
|||||||
|
|
||||||
enum InputMode
|
enum InputMode
|
||||||
{
|
{
|
||||||
INPUT_MODE_XINPUT = 0x01,
|
INPUT_MODE_XINPUT,
|
||||||
INPUT_MODE_SWITCH = 0x02,
|
INPUT_MODE_SWITCH,
|
||||||
INPUT_MODE_HID = 0x03,
|
INPUT_MODE_HID,
|
||||||
INPUT_MODE_PSCLASSIC = 0x04,
|
// INPUT_MODE_KEYBOARD,
|
||||||
INPUT_MODE_XBOXORIGINAL = 0x05,
|
INPUT_MODE_PSCLASSIC,
|
||||||
INPUT_MODE_USBSERIAL = 0x06,
|
INPUT_MODE_XBOXORIGINAL,
|
||||||
|
INPUT_MODE_USBSERIAL,
|
||||||
// INPUT_MODE_CONFIG,
|
// INPUT_MODE_CONFIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InputMode get_input_mode();
|
enum InputMode get_input_mode();
|
||||||
bool change_input_mode(Gamepad previous_gamepad_state);
|
void change_input_mode(Gamepad previous_gamepad_state);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "usbd/drivermanager.h"
|
#include "usbd/drivermanager.h"
|
||||||
#include "usbd/gpdriver.h"
|
#include "usbd/gpdriver.h"
|
||||||
|
|
||||||
#include "Gamepad.h"
|
|
||||||
#include "input_mode.h"
|
#include "input_mode.h"
|
||||||
|
|
||||||
Gamepad gamepad;
|
Gamepad gamepad;
|
||||||
@@ -44,7 +43,7 @@ int main(void)
|
|||||||
GPDriver* driver = driverManager.getDriver();
|
GPDriver* driver = driverManager.getDriver();
|
||||||
driver->process(&gamepad, outBuffer);
|
driver->process(&gamepad, outBuffer);
|
||||||
|
|
||||||
if (absolute_time_diff_us(last_time_gamepad_checked, get_absolute_time()) >= 500000)
|
if (absolute_time_diff_us(last_time_gamepad_checked, get_absolute_time()) >= 200000)
|
||||||
{
|
{
|
||||||
// check if digital buttons have changed (first 16 bytes of gamepad.state)
|
// check if digital buttons have changed (first 16 bytes of gamepad.state)
|
||||||
if (memcmp(&gamepad.state, &previous_gamepad.state, 16) != 0)
|
if (memcmp(&gamepad.state, &previous_gamepad.state, 16) != 0)
|
||||||
@@ -55,10 +54,8 @@ int main(void)
|
|||||||
// haven't changed for 3 seconds
|
// haven't changed for 3 seconds
|
||||||
else if (absolute_time_diff_us(last_time_gamepad_changed, get_absolute_time()) >= 3000000)
|
else if (absolute_time_diff_us(last_time_gamepad_changed, get_absolute_time()) >= 3000000)
|
||||||
{
|
{
|
||||||
if (!change_input_mode(previous_gamepad))
|
change_input_mode(previous_gamepad);
|
||||||
{
|
last_time_gamepad_changed = get_absolute_time();
|
||||||
last_time_gamepad_changed = get_absolute_time();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last_time_gamepad_checked = get_absolute_time();
|
last_time_gamepad_checked = get_absolute_time();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// #include "net/NetDriver.h"
|
// #include "net/NetDriver.h"
|
||||||
// #include "keyboard/KeyboardDriver.h"
|
// #include "keyboard/KeyboardDriver.h"
|
||||||
|
|
||||||
|
// #include "usbd/dinput/DInputDriver.h"
|
||||||
#include "usbd/hid/HIDDriver.h"
|
#include "usbd/hid/HIDDriver.h"
|
||||||
#include "usbd/psclassic/PSClassicDriver.h"
|
#include "usbd/psclassic/PSClassicDriver.h"
|
||||||
#include "usbd/switch/SwitchDriver.h"
|
#include "usbd/switch/SwitchDriver.h"
|
||||||
@@ -23,6 +24,9 @@ void DriverManager::setup(InputMode mode)
|
|||||||
case INPUT_MODE_HID:
|
case INPUT_MODE_HID:
|
||||||
driver = new HIDDriver();
|
driver = new HIDDriver();
|
||||||
break;
|
break;
|
||||||
|
// case INPUT_MODE_HID:
|
||||||
|
// driver = new DInputDriver();
|
||||||
|
// break;
|
||||||
case INPUT_MODE_PSCLASSIC:
|
case INPUT_MODE_PSCLASSIC:
|
||||||
driver = new PSClassicDriver();
|
driver = new PSClassicDriver();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "usbd/hid/HIDDriver.h"
|
#include "usbd/hid/HIDDriver.h"
|
||||||
#include "descriptors/HIDDescriptors.h"
|
#include "descriptors/HIDDescriptors.h"
|
||||||
|
#include "descriptors/PS3Descriptors.h"
|
||||||
#include "usbd/shared/driverhelper.h"
|
#include "usbd/shared/driverhelper.h"
|
||||||
|
|
||||||
// Magic byte sequence to enable PS button on PS3
|
// Magic byte sequence to enable PS button on PS3
|
||||||
@@ -127,11 +128,13 @@ void HIDDriver::process(Gamepad * gamepad, uint8_t * outBuffer)
|
|||||||
uint16_t HIDDriver::get_report(uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen)
|
uint16_t HIDDriver::get_report(uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen)
|
||||||
{
|
{
|
||||||
memcpy(buffer, &hidReport, sizeof(HIDReport));
|
memcpy(buffer, &hidReport, sizeof(HIDReport));
|
||||||
return sizeof(HIDReport);
|
return sizeof(HIDReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only PS4 does anything with set report
|
// Only PS4 does anything with set report
|
||||||
void HIDDriver::set_report(uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {}
|
void HIDDriver::set_report(uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Only XboxOG and Xbox One use vendor control xfer cb
|
// Only XboxOG and Xbox One use vendor control xfer cb
|
||||||
bool HIDDriver::vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
|
bool HIDDriver::vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
#include "usbh/tusb_host_manager.h" // global enum host_mode
|
#include "usbh/tusb_host_manager.h" // global enum host_mode
|
||||||
|
|
||||||
// TODO: make a host driver class for all this
|
// TODO: make a class for all this
|
||||||
|
|
||||||
|
Mouse* mouse = nullptr;
|
||||||
N64USB* n64usb = nullptr;
|
N64USB* n64usb = nullptr;
|
||||||
PSClassic* psclassic = nullptr;
|
PSClassic* psclassic = nullptr;
|
||||||
Dualshock3* dualshock3 = nullptr;
|
Dualshock3* dualshock3 = nullptr;
|
||||||
@@ -21,7 +22,7 @@ Dualsense* dualsense = nullptr;
|
|||||||
SwitchPro* switch_pro = nullptr;
|
SwitchPro* switch_pro = nullptr;
|
||||||
SwitchWired* switch_wired = nullptr;
|
SwitchWired* switch_wired = nullptr;
|
||||||
|
|
||||||
static bool gamepad_mounted;
|
static bool gamepad_mounted = false;
|
||||||
static uint8_t gamepad_dev_addr = 0;
|
static uint8_t gamepad_dev_addr = 0;
|
||||||
static uint8_t gamepad_instance = 0;
|
static uint8_t gamepad_instance = 0;
|
||||||
|
|
||||||
@@ -81,6 +82,11 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
|
|||||||
n64usb = new N64USB();
|
n64usb = new N64USB();
|
||||||
n64usb->init(dev_addr, instance);
|
n64usb->init(dev_addr, instance);
|
||||||
}
|
}
|
||||||
|
else if (host_mode == HOST_MODE_HID_MOUSE && !mouse)
|
||||||
|
{
|
||||||
|
mouse = new Mouse();
|
||||||
|
mouse->init(dev_addr, instance);
|
||||||
|
}
|
||||||
|
|
||||||
if (!tuh_hid_receive_report(dev_addr, instance))
|
if (!tuh_hid_receive_report(dev_addr, instance))
|
||||||
{
|
{
|
||||||
@@ -129,6 +135,11 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
|
|||||||
delete dualsense;
|
delete dualsense;
|
||||||
dualsense = nullptr;
|
dualsense = nullptr;
|
||||||
}
|
}
|
||||||
|
if (mouse)
|
||||||
|
{
|
||||||
|
delete mouse;
|
||||||
|
mouse = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,6 +169,9 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
|
|||||||
case HOST_MODE_HID_N64USB:
|
case HOST_MODE_HID_N64USB:
|
||||||
n64usb->process_report(report, len);
|
n64usb->process_report(report, len);
|
||||||
break;
|
break;
|
||||||
|
case HOST_MODE_HID_MOUSE:
|
||||||
|
mouse->process_report(report, len);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
||||||
@@ -166,6 +180,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send rumble data
|
||||||
bool send_fb_data_to_hid_gamepad()
|
bool send_fb_data_to_hid_gamepad()
|
||||||
{
|
{
|
||||||
if (!gamepad_mounted)
|
if (!gamepad_mounted)
|
||||||
@@ -200,6 +215,9 @@ bool send_fb_data_to_hid_gamepad()
|
|||||||
case HOST_MODE_HID_N64USB:
|
case HOST_MODE_HID_N64USB:
|
||||||
rumble_sent = n64usb->send_fb_data();
|
rumble_sent = n64usb->send_fb_data();
|
||||||
break;
|
break;
|
||||||
|
case HOST_MODE_HID_MOUSE:
|
||||||
|
rumble_sent = mouse->send_fb_data();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef _HID_HOST_APP_H_
|
#ifndef _HID_HOST_APP_H_
|
||||||
#define _HID_HOST_APP_H_
|
#define _HID_HOST_APP_H_
|
||||||
|
|
||||||
|
#include "usbh/tusb_hid/mouse.h"
|
||||||
#include "usbh/tusb_hid/n64usb.h"
|
#include "usbh/tusb_hid/n64usb.h"
|
||||||
#include "usbh/tusb_hid/psclassic.h"
|
#include "usbh/tusb_hid/psclassic.h"
|
||||||
#include "usbh/tusb_hid/ps3.h"
|
#include "usbh/tusb_hid/ps3.h"
|
||||||
|
|||||||
76
src/usbh/tusb_hid/mouse.cpp
Normal file
76
src/usbh/tusb_hid/mouse.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
|
||||||
|
#include "usbh/tusb_hid/mouse.h"
|
||||||
|
|
||||||
|
#include "utilities/scaling.h"
|
||||||
|
|
||||||
|
#include "Gamepad.h"
|
||||||
|
|
||||||
|
void Mouse::init(uint8_t dev_addr, uint8_t instance)
|
||||||
|
{
|
||||||
|
mouse.dev_addr = dev_addr;
|
||||||
|
mouse.instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t Mouse::scale_and_clamp_axes(int32_t value)
|
||||||
|
{
|
||||||
|
// minimum % of int16 +/- joystick value allowed
|
||||||
|
float minimum_percentage = 0.10; // 5%
|
||||||
|
int32_t scaled_value = 0;
|
||||||
|
|
||||||
|
if (value > 0)
|
||||||
|
{
|
||||||
|
scaled_value = (INT16_MAX * minimum_percentage) + ((1 - minimum_percentage) * value);
|
||||||
|
}
|
||||||
|
else if (value < 0)
|
||||||
|
{
|
||||||
|
scaled_value = (INT16_MIN * minimum_percentage) + ((1 - minimum_percentage) * value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaled_value >= INT16_MAX) return INT16_MAX;
|
||||||
|
else if (scaled_value <= INT16_MIN) return INT16_MIN;
|
||||||
|
|
||||||
|
return (int16_t)scaled_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse::update_gamepad(const hid_mouse_report_t* mouse_report)
|
||||||
|
{
|
||||||
|
// gamepad.reset_state();
|
||||||
|
|
||||||
|
gamepad.state.rt = (mouse_report->buttons & MOUSE_BUTTON_LEFT ) ? 0xFF : 0x00;
|
||||||
|
gamepad.state.lt = (mouse_report->buttons & MOUSE_BUTTON_RIGHT) ? 0xFF : 0x00;
|
||||||
|
|
||||||
|
// for testing
|
||||||
|
gamepad.state.x = (mouse_report->buttons & MOUSE_BUTTON_BACKWARD);
|
||||||
|
gamepad.state.a = (mouse_report->buttons & MOUSE_BUTTON_FORWARD );
|
||||||
|
|
||||||
|
gamepad.state.y = (mouse_report->wheel != 0);
|
||||||
|
|
||||||
|
int32_t scaled_y = scale_int8_to_int16(mouse_report->y, true) * 2; // * 2 to make more responsive
|
||||||
|
int32_t scaled_x = scale_int8_to_int16(mouse_report->x, false) * 2;
|
||||||
|
|
||||||
|
gamepad.state.ry = scale_and_clamp_axes(scaled_y);
|
||||||
|
gamepad.state.rx = scale_and_clamp_axes(scaled_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mouse::process_report(uint8_t const* report, uint16_t len)
|
||||||
|
{
|
||||||
|
static hid_mouse_report_t prev_report = { 0 };
|
||||||
|
|
||||||
|
hid_mouse_report_t mouse_report;
|
||||||
|
memcpy(&mouse_report, report, sizeof(mouse_report));
|
||||||
|
|
||||||
|
if (memcmp(&mouse_report, &prev_report, sizeof(mouse_report)) != 0)
|
||||||
|
update_gamepad(&mouse_report);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mouse::send_fb_data()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
31
src/usbh/tusb_hid/mouse.h
Normal file
31
src/usbh/tusb_hid/mouse.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef _MOUSE_H_
|
||||||
|
#define _MOUSE_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "class/hid/hid.h"
|
||||||
|
#include "usbh/tusb_hid/shared.h"
|
||||||
|
|
||||||
|
struct MouseState
|
||||||
|
{
|
||||||
|
uint8_t dev_addr = {0};
|
||||||
|
uint8_t instance = {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mouse
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void init(uint8_t dev_addr, uint8_t instance);
|
||||||
|
void process_report(uint8_t const* report, uint16_t len);
|
||||||
|
bool send_fb_data();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MouseState mouse;
|
||||||
|
|
||||||
|
int16_t scale_and_clamp_axes(int32_t value);
|
||||||
|
void update_gamepad(const hid_mouse_report_t* mouse_report);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _MOUSE_H_
|
||||||
@@ -6,15 +6,14 @@
|
|||||||
#include "class/hid/hid_host.h"
|
#include "class/hid/hid_host.h"
|
||||||
|
|
||||||
#include "utilities/scaling.h"
|
#include "utilities/scaling.h"
|
||||||
#include "Gamepad.h"
|
|
||||||
|
|
||||||
#include "usbh/tusb_hid/ps3.h"
|
#include "usbh/tusb_hid/ps3.h"
|
||||||
|
#include "Gamepad.h"
|
||||||
|
|
||||||
#include "utilities/log.h"
|
#include "utilities/log.h"
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* ---------------------------- */
|
||||||
/* this only works for DInput currently, no DS3 */
|
/* this does not work currently */
|
||||||
/* -------------------------------------------- */
|
/* ---------------------------- */
|
||||||
|
|
||||||
void Dualshock3::init(uint8_t dev_addr, uint8_t instance)
|
void Dualshock3::init(uint8_t dev_addr, uint8_t instance)
|
||||||
{
|
{
|
||||||
@@ -25,13 +24,15 @@ void Dualshock3::init(uint8_t dev_addr, uint8_t instance)
|
|||||||
tuh_vid_pid_get(dualshock3.dev_addr, &vid, &pid);
|
tuh_vid_pid_get(dualshock3.dev_addr, &vid, &pid);
|
||||||
if (vid == 0x054C && pid == 0x0268) dualshock3.sixaxis = true;
|
if (vid == 0x054C && pid == 0x0268) dualshock3.sixaxis = true;
|
||||||
|
|
||||||
|
// tuh_hid_set_protocol(dualshock3.dev_addr, dualshock3.instance, HID_PROTOCOL_REPORT);
|
||||||
|
// sleep_ms(200);
|
||||||
if (enable_reports())
|
if (enable_reports())
|
||||||
{
|
{
|
||||||
// log("reports enabled, addr: %02X inst: %02X", dev_addr, instance);
|
log("reports enabled, addr: %02X inst: %02X", dev_addr, instance);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// log("report enable failed");
|
log("reports enable failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +68,13 @@ bool Dualshock3::enable_reports()
|
|||||||
return dualshock3.report_enabled;
|
return dualshock3.report_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void Dualshock3::reset_state()
|
||||||
|
// {
|
||||||
|
// dualshock3.report_enabled = false;
|
||||||
|
// dualshock3.dev_addr = 0;
|
||||||
|
// dualshock3.instance = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
void Dualshock3::update_gamepad_dinput(const DInputReport* dinput_report)
|
void Dualshock3::update_gamepad_dinput(const DInputReport* dinput_report)
|
||||||
{
|
{
|
||||||
gamepad.reset_state();
|
gamepad.reset_state();
|
||||||
@@ -127,7 +135,7 @@ void Dualshock3::update_gamepad_dinput(const DInputReport* dinput_report)
|
|||||||
gamepad.state.ry = scale_uint8_to_int16(dinput_report->r_y_axis, true);
|
gamepad.state.ry = scale_uint8_to_int16(dinput_report->r_y_axis, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dualshock3::update_gamepad(const Dualshock3Report* ds3_data)
|
void Dualshock3::update_gamepad(const DualShock3Report* ds3_data)
|
||||||
{
|
{
|
||||||
gamepad.reset_state();
|
gamepad.reset_state();
|
||||||
|
|
||||||
@@ -165,12 +173,12 @@ void Dualshock3::process_report(uint8_t const* report, uint16_t len)
|
|||||||
// if (report[0] != 0x01) return;
|
// if (report[0] != 0x01) return;
|
||||||
|
|
||||||
// print hex values
|
// print hex values
|
||||||
// char hex_buffer[len * 3];
|
char hex_buffer[len * 3];
|
||||||
// for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
// {
|
{
|
||||||
// sprintf(hex_buffer + (i * 3), "%02X ", report[i]); // Convert byte to hexadecimal string
|
sprintf(hex_buffer + (i * 3), "%02X ", report[i]); // Convert byte to hexadecimal string
|
||||||
// }
|
}
|
||||||
// log(hex_buffer);
|
log(hex_buffer);
|
||||||
|
|
||||||
if (!dualshock3.sixaxis)
|
if (!dualshock3.sixaxis)
|
||||||
{
|
{
|
||||||
@@ -182,8 +190,8 @@ void Dualshock3::process_report(uint8_t const* report, uint16_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static Dualshock3Report prev_report = { 0 };
|
static DualShock3Report prev_report = { 0 };
|
||||||
Dualshock3Report ds3_report;
|
DualShock3Report ds3_report;
|
||||||
memcpy(&ds3_report, report, sizeof(ds3_report));
|
memcpy(&ds3_report, report, sizeof(ds3_report));
|
||||||
update_gamepad(&ds3_report);
|
update_gamepad(&ds3_report);
|
||||||
prev_report = ds3_report;
|
prev_report = ds3_report;
|
||||||
@@ -217,5 +225,8 @@ bool Dualshock3::send_fb_data()
|
|||||||
output_report.rumble.left_duration = UINT8_MAX / 2;
|
output_report.rumble.left_duration = UINT8_MAX / 2;
|
||||||
output_report.rumble.left_motor_force = gamepadOut.out_state.lrumble;
|
output_report.rumble.left_motor_force = gamepadOut.out_state.lrumble;
|
||||||
|
|
||||||
return tuh_hid_send_report(dualshock3.dev_addr, dualshock3.instance, 0x1, &output_report, sizeof(output_report));
|
bool rumble_sent = tuh_hid_send_report(dualshock3.dev_addr, dualshock3.instance, 1, &output_report, sizeof(output_report));
|
||||||
|
|
||||||
|
return rumble_sent;
|
||||||
|
// return true;
|
||||||
}
|
}
|
||||||
@@ -6,14 +6,15 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "usbh/tusb_hid/shared.h"
|
#include "usbh/tusb_hid/shared.h"
|
||||||
#include "descriptors/PS3Descriptors.h"
|
|
||||||
#include "descriptors/DInputDescriptors.h"
|
#include "descriptors/DInputDescriptors.h"
|
||||||
|
#include "descriptors/PS3Descriptors.h"
|
||||||
|
|
||||||
#define PS3_REPORT_BUFFER_SIZE 48
|
#define PS3_REPORT_BUFFER_SIZE 48
|
||||||
|
|
||||||
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)
|
||||||
|
{0x2563, 0x0575}, // Nuplay Armor 3
|
||||||
// {0x045E, 0x028E}, // Voyee generic "P3", won't work, IDs are for a 360 controller (dumb)
|
// {0x045E, 0x028E}, // Voyee generic "P3", won't work, IDs are for a 360 controller (dumb)
|
||||||
{0x044F, 0xB324}, // ThrustMaster Dual Trigger (PS3 mode)
|
{0x044F, 0xB324}, // ThrustMaster Dual Trigger (PS3 mode)
|
||||||
{0x0738, 0x8818}, // MadCatz Street Fighter IV Arcade FightStick
|
{0x0738, 0x8818}, // MadCatz Street Fighter IV Arcade FightStick
|
||||||
@@ -40,8 +41,8 @@ class Dualshock3
|
|||||||
Dualshock3State dualshock3;
|
Dualshock3State dualshock3;
|
||||||
|
|
||||||
bool enable_reports();
|
bool enable_reports();
|
||||||
void reset_state();
|
// void reset_state();
|
||||||
void update_gamepad(const Dualshock3Report* ds3_data);
|
void update_gamepad(const DualShock3Report* ds3_data);
|
||||||
void update_gamepad_dinput(const DInputReport* dinput_report);
|
void update_gamepad_dinput(const DInputReport* dinput_report);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
#include "tusb_host.h"
|
#include "tusb_host.h"
|
||||||
#include "tusb_host_manager.h"
|
#include "tusb_host_manager.h"
|
||||||
|
|
||||||
|
// TODO figure out something to do with the leds
|
||||||
|
// tuh_mounted is always true after unplugging a gamepad, idk what's up with that
|
||||||
|
|
||||||
#ifdef FEATHER_RP2040
|
#ifdef FEATHER_RP2040
|
||||||
#define PIO_USB_DP_PIN 16 // DM = 17
|
#define PIO_USB_DP_PIN 16 // DM = 17
|
||||||
#define PIN_5V_EN 18
|
#define PIN_5V_EN 18
|
||||||
@@ -59,10 +62,8 @@ void usbh_main()
|
|||||||
|
|
||||||
if (current_time - fb_sent_time >= fb_interval)
|
if (current_time - fb_sent_time >= fb_interval)
|
||||||
{
|
{
|
||||||
if (send_fb_data_to_gamepad())
|
send_fb_data_to_gamepad();
|
||||||
{
|
fb_sent_time = current_time;
|
||||||
fb_sent_time = current_time;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,8 +12,9 @@
|
|||||||
|
|
||||||
HostMode host_mode;
|
HostMode host_mode;
|
||||||
|
|
||||||
bool device_mounted;
|
bool device_mounted = false;
|
||||||
uint8_t device_daddr = 0;
|
uint8_t device_daddr = 0;
|
||||||
|
tusb_desc_interface_t config_descriptor;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -26,7 +27,7 @@ const DeviceTypeInfo 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 },
|
// { 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 },
|
||||||
@@ -46,16 +47,31 @@ bool check_vid_pid(const usb_vid_pid_t* devices, size_t num_devices, HostMode ch
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void config_descriptor_complete_cb(tuh_xfer_t* xfer)
|
||||||
|
{
|
||||||
|
if (xfer->result == XFER_RESULT_SUCCESS)
|
||||||
|
{
|
||||||
|
if ((config_descriptor.bInterfaceSubClass == 0x5D && config_descriptor.bInterfaceProtocol == 0x81) ||
|
||||||
|
(config_descriptor.bInterfaceSubClass == 0x5D && config_descriptor.bInterfaceProtocol == 0x01) ||
|
||||||
|
(config_descriptor.bInterfaceSubClass == 0x47 && config_descriptor.bInterfaceProtocol == 0xD0) ||
|
||||||
|
(config_descriptor.bInterfaceSubClass == 0x42 && config_descriptor.bInterfaceClass == 0x58))
|
||||||
|
{
|
||||||
|
host_mode = HOST_MODE_XINPUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tuh_mount_cb(uint8_t daddr)
|
void tuh_mount_cb(uint8_t daddr)
|
||||||
{
|
{
|
||||||
device_mounted = true;
|
if (!device_mounted)
|
||||||
device_daddr = daddr;
|
{
|
||||||
|
device_mounted = true;
|
||||||
|
device_daddr = daddr;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t vid, pid;
|
uint16_t vid, pid;
|
||||||
tuh_vid_pid_get(daddr, &vid, &pid);
|
tuh_vid_pid_get(daddr, &vid, &pid);
|
||||||
|
|
||||||
host_mode = HOST_MODE_XINPUT;
|
|
||||||
|
|
||||||
// set host mode depending on VID/PID match
|
// set host mode depending on VID/PID match
|
||||||
const size_t num_device_types = sizeof(device_types) / sizeof(DeviceTypeInfo);
|
const size_t num_device_types = sizeof(device_types) / sizeof(DeviceTypeInfo);
|
||||||
|
|
||||||
@@ -68,12 +84,15 @@ void tuh_mount_cb(uint8_t daddr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
// if (!tuh_descriptor_get_configuration(daddr, 0, &config_descriptor, sizeof(config_descriptor), config_descriptor_complete_cb, 0))
|
||||||
|
// {
|
||||||
|
host_mode = HOST_MODE_HID_MOUSE; // idk
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void tuh_umount_cb(uint8_t daddr)
|
void tuh_umount_cb(uint8_t daddr)
|
||||||
{
|
{
|
||||||
if (device_mounted)
|
if (device_mounted && device_daddr == daddr)
|
||||||
{
|
{
|
||||||
device_mounted = false;
|
device_mounted = false;
|
||||||
}
|
}
|
||||||
@@ -92,20 +111,18 @@ usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool send_fb_data_to_gamepad()
|
void send_fb_data_to_gamepad()
|
||||||
{
|
{
|
||||||
if (!device_mounted)
|
if (device_mounted)
|
||||||
return true;
|
|
||||||
|
|
||||||
if (host_mode == HOST_MODE_XINPUT)
|
|
||||||
{
|
{
|
||||||
return send_fb_data_to_xinput_gamepad();
|
if (host_mode == HOST_MODE_XINPUT)
|
||||||
|
{
|
||||||
|
send_fb_data_to_xinput_gamepad();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (send_fb_data_to_hid_gamepad())
|
||||||
|
gamepadOut.rumble_hid_reset(); // needed so rumble doesn't get stuck on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (send_fb_data_to_hid_gamepad())
|
|
||||||
{
|
|
||||||
gamepadOut.rumble_hid_reset();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
@@ -10,11 +10,12 @@ typedef enum
|
|||||||
HOST_MODE_HID_PS3,
|
HOST_MODE_HID_PS3,
|
||||||
HOST_MODE_HID_PS4,
|
HOST_MODE_HID_PS4,
|
||||||
HOST_MODE_HID_PS5,
|
HOST_MODE_HID_PS5,
|
||||||
HOST_MODE_HID_N64USB
|
HOST_MODE_HID_N64USB,
|
||||||
|
HOST_MODE_HID_MOUSE
|
||||||
} HostMode;
|
} HostMode;
|
||||||
|
|
||||||
extern HostMode host_mode;
|
extern HostMode host_mode;
|
||||||
|
|
||||||
bool send_fb_data_to_gamepad();
|
void send_fb_data_to_gamepad();
|
||||||
|
|
||||||
#endif // _TUSB_HOST_MANAGER_H_
|
#endif // _TUSB_HOST_MANAGER_H_
|
||||||
@@ -44,5 +44,28 @@ int16_t scale_uint8_to_int16(uint8_t value, bool invert)
|
|||||||
scaled_value = INT16_MAX;
|
scaled_value = INT16_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (int16_t)scaled_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t scale_int8_to_int16(int8_t value, bool invert)
|
||||||
|
{
|
||||||
|
const uint16_t multiplier = 257;
|
||||||
|
|
||||||
|
int32_t scaled_value = (int32_t)value * multiplier;
|
||||||
|
|
||||||
|
if (invert)
|
||||||
|
{
|
||||||
|
scaled_value = -scaled_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaled_value < INT16_MIN)
|
||||||
|
{
|
||||||
|
scaled_value = INT16_MIN;
|
||||||
|
}
|
||||||
|
else if (scaled_value > INT16_MAX)
|
||||||
|
{
|
||||||
|
scaled_value = INT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
return (int16_t)scaled_value;
|
return (int16_t)scaled_value;
|
||||||
}
|
}
|
||||||
@@ -7,5 +7,6 @@
|
|||||||
|
|
||||||
uint8_t scale_int16_to_uint8(int16_t value, bool invert);
|
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);
|
||||||
|
int16_t scale_int8_to_int16(int8_t value, bool invert);
|
||||||
|
|
||||||
#endif // _SCALING_H_
|
#endif // _SCALING_H_
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define FW_VERSION "0.3.0"
|
#define FW_VERSION "0.2.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user