mirror of
https://github.com/ravinrabbid/DonCon2040.git
synced 2025-02-12 00:43:07 +01:00
Port over the remaining USB modes from DivaCon
This commit is contained in:
parent
e86d869c46
commit
ee3eaac3d6
@ -47,7 +47,7 @@ extern "C" {
|
||||
#define CFG_TUD_CDC (1)
|
||||
#define CFG_TUD_MSC (0)
|
||||
#define CFG_TUD_MIDI (0)
|
||||
#define CFG_TUD_HID (0)
|
||||
#define CFG_TUD_HID (1)
|
||||
#define CFG_TUD_VENDOR (0)
|
||||
|
||||
// Device class buffer sizes
|
||||
|
21
include/usb/hid_driver.h
Normal file
21
include/usb/hid_driver.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _USB_HID_DRIVER_H_
|
||||
#define _USB_HID_DRIVER_H_
|
||||
|
||||
#include "usb/hid_ps3_driver.h"
|
||||
#include "usb/hid_ps4_driver.h"
|
||||
#include "usb/hid_switch_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const usbd_class_driver_t hid_app_driver;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _USB_HID_DRIVER_H_
|
57
include/usb/hid_ps3_driver.h
Normal file
57
include/usb/hid_ps3_driver.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef _USB_HID_PS3_DRIVER_H_
|
||||
#define _USB_HID_PS3_DRIVER_H_
|
||||
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USBD_PS3_NAME "Dualshock3 Emulation"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct __attribute((packed, aligned(1))) {
|
||||
uint8_t report_id;
|
||||
uint8_t padding;
|
||||
uint8_t buttons1;
|
||||
uint8_t buttons2;
|
||||
uint8_t buttons3;
|
||||
uint8_t padding1;
|
||||
uint8_t lx;
|
||||
uint8_t ly;
|
||||
uint8_t rx;
|
||||
uint8_t ry;
|
||||
uint8_t padding2[8];
|
||||
uint8_t lt;
|
||||
uint8_t rt;
|
||||
uint8_t padding3[9];
|
||||
uint8_t unknown_0x02_1;
|
||||
uint8_t battery;
|
||||
uint8_t unknown_0x12;
|
||||
uint8_t padding4[4];
|
||||
uint8_t unknown[5];
|
||||
uint16_t acc_x;
|
||||
uint16_t acc_z;
|
||||
uint16_t acc_y;
|
||||
uint8_t padding5;
|
||||
uint8_t unknown_0x02_2;
|
||||
} hid_ps3_report_t;
|
||||
|
||||
extern const tusb_desc_device_t ds3_desc_device;
|
||||
extern const uint8_t ps3_desc_cfg[];
|
||||
extern const uint8_t ps3_desc_hid_report[];
|
||||
|
||||
bool send_hid_ps3_report(usb_report_t report);
|
||||
uint16_t hid_ps3_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen);
|
||||
void hid_ps3_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _USB_HID_PS3_DRIVER_H_
|
63
include/usb/hid_ps4_driver.h
Normal file
63
include/usb/hid_ps4_driver.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef _USB_HID_PS4_DRIVER_H_
|
||||
#define _USB_HID_PS4_DRIVER_H_
|
||||
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USBD_PS4_NAME "Dualshock4 Emulation"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// https://www.psdevwiki.com/ps4/DS4-USB
|
||||
typedef struct __attribute((packed, aligned(1))) {
|
||||
uint8_t report_id;
|
||||
uint8_t lx;
|
||||
uint8_t ly;
|
||||
uint8_t rx;
|
||||
uint8_t ry;
|
||||
uint8_t buttons1;
|
||||
uint8_t buttons2;
|
||||
uint8_t buttons3;
|
||||
uint8_t lt;
|
||||
uint8_t rt;
|
||||
uint16_t timestamp;
|
||||
uint8_t battery;
|
||||
uint16_t gyrox;
|
||||
uint16_t gyroy;
|
||||
uint16_t gyroz;
|
||||
int16_t accelx;
|
||||
int16_t accely;
|
||||
int16_t accelz;
|
||||
uint8_t unknown1[5];
|
||||
uint8_t extension;
|
||||
uint8_t unknown2[2];
|
||||
uint8_t touchpad_event_active;
|
||||
uint8_t touchpad_counter;
|
||||
uint8_t touchpad1_touches;
|
||||
uint8_t touchpad1_position[3];
|
||||
uint8_t touchpad2_touches;
|
||||
uint8_t touchpad2_position[3];
|
||||
uint8_t unknown3[21];
|
||||
} hid_ps4_report_t;
|
||||
|
||||
extern const tusb_desc_device_t ps4_tatacon_desc_device;
|
||||
extern const tusb_desc_device_t ds4_desc_device;
|
||||
extern const uint8_t ps4_desc_cfg[];
|
||||
extern const uint8_t ps4_desc_hid_report[];
|
||||
|
||||
bool send_hid_ps4_report(usb_report_t report);
|
||||
uint16_t hid_ps4_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen);
|
||||
void hid_ps4_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _USB_HID_PS4_DRIVER_H_
|
41
include/usb/hid_switch_driver.h
Normal file
41
include/usb/hid_switch_driver.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _USB_HID_SWITCH_DRIVER_H_
|
||||
#define _USB_HID_SWITCH_DRIVER_H_
|
||||
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USBD_SWITCH_NAME "Switch Horipad Emulation"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct __attribute((packed, aligned(1))) {
|
||||
uint16_t buttons;
|
||||
uint8_t hat;
|
||||
uint8_t lx;
|
||||
uint8_t ly;
|
||||
uint8_t rx;
|
||||
uint8_t ry;
|
||||
uint8_t vendor;
|
||||
} hid_switch_report_t;
|
||||
|
||||
extern const tusb_desc_device_t switch_tatacon_desc_device;
|
||||
extern const tusb_desc_device_t switch_horipad_desc_device;
|
||||
extern const uint8_t switch_desc_cfg[];
|
||||
extern const uint8_t switch_desc_hid_report[];
|
||||
|
||||
bool send_hid_switch_report(usb_report_t report);
|
||||
uint16_t hid_switch_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen);
|
||||
void hid_switch_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _USB_HID_SWITCH_DRIVER_H_
|
@ -15,10 +15,11 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
// USB_MODE_SWITCH_TATACON,
|
||||
// USB_MODE_SWITCH_HORIPAD,
|
||||
// USB_MODE_DUALSHOCK3,
|
||||
// USB_MODE_DUALSHOCK4,
|
||||
USB_MODE_SWITCH_TATACON,
|
||||
USB_MODE_SWITCH_HORIPAD,
|
||||
USB_MODE_DUALSHOCK3,
|
||||
USB_MODE_PS4_TATACON,
|
||||
USB_MODE_DUALSHOCK4,
|
||||
USB_MODE_XBOX360,
|
||||
USB_MODE_DEBUG,
|
||||
} usb_mode_t;
|
||||
@ -41,8 +42,27 @@ typedef struct {
|
||||
uint16_t size;
|
||||
} usb_report_t;
|
||||
|
||||
typedef enum {
|
||||
USB_PLAYER_LED_ID,
|
||||
USB_PLAYER_LED_COLOR,
|
||||
} usb_player_led_type_t;
|
||||
|
||||
typedef struct {
|
||||
usb_player_led_type_t type;
|
||||
union {
|
||||
uint8_t id;
|
||||
struct {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
};
|
||||
};
|
||||
} usb_player_led_t;
|
||||
|
||||
extern char *const usbd_desc_str[];
|
||||
|
||||
typedef void (*usbd_player_led_cb_t)(usb_player_led_t);
|
||||
|
||||
void usb_driver_init(usb_mode_t mode);
|
||||
void usb_driver_task();
|
||||
|
||||
@ -50,6 +70,9 @@ usb_mode_t usb_driver_get_mode();
|
||||
|
||||
void usb_driver_send_and_receive_report(usb_report_t report);
|
||||
|
||||
void usb_driver_set_player_led_cb(usbd_player_led_cb_t cb);
|
||||
usbd_player_led_cb_t usb_driver_get_player_led_cb();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef _UTILS_INPUTSTATE_H_
|
||||
#define _UTILS_INPUTSTATE_H_
|
||||
|
||||
#include "usb/hid_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
#include "usb/xinput_driver.h"
|
||||
|
||||
@ -40,9 +41,15 @@ struct InputState {
|
||||
Controller controller;
|
||||
|
||||
private:
|
||||
hid_switch_report_t m_switch_report;
|
||||
hid_ps3_report_t m_ps3_report;
|
||||
hid_ps4_report_t m_ps4_report;
|
||||
xinput_report_t m_xinput_report;
|
||||
std::string m_debug_report;
|
||||
|
||||
usb_report_t getSwitchReport();
|
||||
usb_report_t getPS3InputReport();
|
||||
usb_report_t getPS4InputReport();
|
||||
usb_report_t getXinputReport();
|
||||
usb_report_t getDebugReport();
|
||||
|
||||
|
@ -176,6 +176,16 @@ void Display::showMenu() { m_state = State::Menu; }
|
||||
|
||||
static std::string modeToString(usb_mode_t mode) {
|
||||
switch (mode) {
|
||||
case USB_MODE_SWITCH_TATACON:
|
||||
return "Switch Tatacon";
|
||||
case USB_MODE_SWITCH_HORIPAD:
|
||||
return "Switch Horipad";
|
||||
case USB_MODE_DUALSHOCK3:
|
||||
return "Dualshock 3";
|
||||
case USB_MODE_PS4_TATACON:
|
||||
return "PS4 Tatacon";
|
||||
case USB_MODE_DUALSHOCK4:
|
||||
return "Dualshock 4";
|
||||
case USB_MODE_XBOX360:
|
||||
return "Xbox 360";
|
||||
case USB_MODE_DEBUG:
|
||||
|
64
src/usb/hid_driver.c
Normal file
64
src/usb/hid_driver.c
Normal file
@ -0,0 +1,64 @@
|
||||
#include "usb/hid_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "class/hid/hid_device.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen) {
|
||||
switch (usb_driver_get_mode()) {
|
||||
case USB_MODE_SWITCH_TATACON:
|
||||
case USB_MODE_SWITCH_HORIPAD:
|
||||
return hid_switch_get_report_cb(itf, report_id, report_type, buffer, reqlen);
|
||||
case USB_MODE_DUALSHOCK3:
|
||||
return hid_ps3_get_report_cb(itf, report_id, report_type, buffer, reqlen);
|
||||
// case USB_MODE_PS4_TATACON:
|
||||
case USB_MODE_DUALSHOCK4:
|
||||
return hid_ps4_get_report_cb(itf, report_id, report_type, buffer, reqlen);
|
||||
default:
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize) {
|
||||
switch (usb_driver_get_mode()) {
|
||||
case USB_MODE_SWITCH_TATACON:
|
||||
case USB_MODE_SWITCH_HORIPAD:
|
||||
hid_switch_set_report_cb(itf, report_id, report_type, buffer, bufsize);
|
||||
break;
|
||||
case USB_MODE_DUALSHOCK3:
|
||||
hid_ps3_set_report_cb(itf, report_id, report_type, buffer, bufsize);
|
||||
break;
|
||||
// case USB_MODE_PS4_TATACON:
|
||||
case USB_MODE_DUALSHOCK4:
|
||||
hid_ps4_set_report_cb(itf, report_id, report_type, buffer, bufsize);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
bool hid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) {
|
||||
// Magic byte sequence to enable PS button on PS3
|
||||
static const uint8_t magic_init_bytes[8] = {0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
if (stage == CONTROL_STAGE_SETUP && request->bmRequestType == 0xA1 &&
|
||||
request->bRequest == HID_REQ_CONTROL_GET_REPORT && request->wValue == 0x0300) {
|
||||
return tud_hid_report(0, magic_init_bytes, sizeof(magic_init_bytes));
|
||||
} else {
|
||||
return hidd_control_xfer_cb(rhport, stage, request);
|
||||
}
|
||||
}
|
||||
|
||||
const usbd_class_driver_t hid_app_driver = {
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
.name = "HID",
|
||||
#endif
|
||||
.init = hidd_init,
|
||||
.reset = hidd_reset,
|
||||
.open = hidd_open,
|
||||
.control_xfer_cb = hid_control_xfer_cb,
|
||||
.xfer_cb = hidd_xfer_cb,
|
||||
.sof = NULL};
|
207
src/usb/hid_ps3_driver.c
Normal file
207
src/usb/hid_ps3_driver.c
Normal file
@ -0,0 +1,207 @@
|
||||
#include "usb/hid_ps3_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "class/hid/hid_device.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
const tusb_desc_device_t ds3_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_UNSPECIFIED,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = 0x054C, // Sny
|
||||
.idProduct = 0x0268, // Dualshock3
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUFACTURER,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
USBD_ITF_HID,
|
||||
USBD_ITF_MAX,
|
||||
};
|
||||
|
||||
#define USBD_PS3_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
|
||||
const uint8_t ps3_desc_cfg[] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_LANGUAGE, USBD_PS3_DESC_LEN, 0, USBD_MAX_POWER_MAX),
|
||||
TUD_HID_INOUT_DESCRIPTOR(USBD_ITF_HID, USBD_STR_PS3, 0, 148, 0x02, 0x81, CFG_TUD_HID_EP_BUFSIZE, 1),
|
||||
};
|
||||
|
||||
const uint8_t ps3_desc_hid_report[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x04, // Usage (Joystick)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0xA1, 0x02, // Collection (Logical)
|
||||
0x85, 0x01, // Report ID (1)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x13, // Report Count (19)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x45, 0x01, // Physical Maximum (1)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x13, // Usage Maximum (0x13)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x0D, // Report Count (13)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xA1, 0x00, // Collection (Physical)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, // End Collection
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x27, // Report Count (39)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x30, // Report Count (48)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x30, // Report Count (48)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
0xA1, 0x02, // Collection (Logical)
|
||||
0x85, 0x02, // Report ID (2)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x30, // Report Count (48)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
0xA1, 0x02, // Collection (Logical)
|
||||
0x85, 0xEE, // Report ID (-18)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x30, // Report Count (48)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
0xA1, 0x02, // Collection (Logical)
|
||||
0x85, 0xEF, // Report ID (-17)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x30, // Report Count (48)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
static hid_ps3_report_t last_report = {};
|
||||
|
||||
bool send_hid_ps3_report(usb_report_t report) {
|
||||
bool result = false;
|
||||
if (tud_hid_ready()) {
|
||||
result = tud_hid_report(0, report.data, report.size);
|
||||
}
|
||||
|
||||
memcpy(&last_report, report.data, tu_min16(report.size, sizeof(hid_ps3_report_t)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t ps3_report_0xf2[] = {
|
||||
0xff, 0xff, 0x00, // Unknown
|
||||
0x00, 0x07, 0x04, // MAC address OUI (ALPS Co.)
|
||||
0x39, 0x39, 0x39, // MAC manufacturer specific
|
||||
0x00, 0x03, 0x50, 0x81, 0xd8, 0x01, 0x8a // Unknown
|
||||
};
|
||||
static const uint8_t ps3_report_0xf5[] = {0x00, 0xf0, 0xf0, 0x02, 0x5e, 0x16, 0x26}; // Unknown
|
||||
|
||||
uint16_t hid_ps3_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen) {
|
||||
(void)itf;
|
||||
(void)reqlen;
|
||||
|
||||
static bool do_init_mac = true;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_INPUT) {
|
||||
memcpy(buffer, &last_report, sizeof(hid_ps3_report_t));
|
||||
return sizeof(hid_ps3_report_t);
|
||||
} else if (report_type == HID_REPORT_TYPE_FEATURE) {
|
||||
switch (report_id) {
|
||||
case 0xf2:
|
||||
if (do_init_mac) {
|
||||
pico_unique_board_id_t uid;
|
||||
pico_get_unique_board_id(&uid);
|
||||
|
||||
// Genrate manufacturer specific using pico board id
|
||||
for (uint8_t i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; ++i) {
|
||||
ps3_report_0xf2[6 + (i % 3)] ^= uid.id[i];
|
||||
}
|
||||
|
||||
do_init_mac = false;
|
||||
}
|
||||
|
||||
memcpy(buffer, ps3_report_0xf2, sizeof(ps3_report_0xf2));
|
||||
return sizeof(ps3_report_0xf2);
|
||||
case 0xf5:
|
||||
memcpy(buffer, ps3_report_0xf5, sizeof(ps3_report_0xf5));
|
||||
return sizeof(ps3_report_0xf5);
|
||||
default:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct __attribute((packed, aligned(1))) {
|
||||
uint8_t rumble[4];
|
||||
uint8_t padding[4];
|
||||
uint8_t leds_bitmap;
|
||||
uint8_t leds[5][5];
|
||||
} hid_ps3_ouput_report_t;
|
||||
|
||||
void hid_ps3_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize) {
|
||||
(void)itf;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_INVALID) {
|
||||
if (bufsize > 0) {
|
||||
report_id = buffer[0];
|
||||
buffer = &buffer[1];
|
||||
bufsize--;
|
||||
}
|
||||
}
|
||||
|
||||
switch (report_id) {
|
||||
case 0x01:
|
||||
if (bufsize == sizeof(hid_ps3_ouput_report_t)) {
|
||||
hid_ps3_ouput_report_t *report = (hid_ps3_ouput_report_t *)buffer;
|
||||
|
||||
usb_player_led_t player_led = {.type = USB_PLAYER_LED_ID, .id = 0};
|
||||
player_led.id = 0 | ((report->leds_bitmap & 0x02) ? (1 << 0) : 0) //
|
||||
| ((report->leds_bitmap & 0x04) ? (1 << 1) : 0) //
|
||||
| ((report->leds_bitmap & 0x08) ? (1 << 2) : 0) //
|
||||
| ((report->leds_bitmap & 0x10) ? (1 << 3) : 0);
|
||||
|
||||
usb_driver_get_player_led_cb()(player_led);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
414
src/usb/hid_ps4_driver.c
Normal file
414
src/usb/hid_ps4_driver.c
Normal file
@ -0,0 +1,414 @@
|
||||
#include "usb/hid_ps4_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "class/hid/hid_device.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
const tusb_desc_device_t ps4_tatacon_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_UNSPECIFIED,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = 0x0F0D, // HORI
|
||||
.idProduct = 0x00C9, // PS4-095 aka Taiko Drum
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUFACTURER,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
const tusb_desc_device_t ds4_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_UNSPECIFIED,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = 0x054C, // Sny
|
||||
.idProduct = 0x05C4, // Dualshock 4
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUFACTURER,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
USBD_ITF_HID,
|
||||
USBD_ITF_MAX,
|
||||
};
|
||||
|
||||
#define USBD_PS4_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
|
||||
const uint8_t ps4_desc_cfg[] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_LANGUAGE, USBD_PS4_DESC_LEN, 0, USBD_MAX_POWER_MAX),
|
||||
TUD_HID_INOUT_DESCRIPTOR(USBD_ITF_HID, USBD_STR_PS4, 0, 507, 0x03, 0x84, CFG_TUD_HID_EP_BUFSIZE, 1),
|
||||
};
|
||||
|
||||
const uint8_t ps4_desc_hid_report[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, // Usage (Game Pad)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x85, 0x01, // Report ID (1)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x07, // Logical Maximum (7)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
||||
0x65, 0x00, // Unit (None)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x0E, // Usage Maximum (0x0E)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x0E, // Report Count (14)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x75, 0x06, // Report Size (6)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x7F, // Logical Maximum (127)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x33, // Usage (Rx)
|
||||
0x09, 0x34, // Usage (Ry)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x95, 0x36, // Report Count (54)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x85, 0x05, // Report ID (5)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x95, 0x1F, // Report Count (31)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x04, // Report ID (4)
|
||||
0x09, 0x23, // Usage (0x23)
|
||||
0x95, 0x24, // Report Count (36)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x02, // Report ID (2)
|
||||
0x09, 0x24, // Usage (0x24)
|
||||
0x95, 0x24, // Report Count (36)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x08, // Report ID (8)
|
||||
0x09, 0x25, // Usage (0x25)
|
||||
0x95, 0x03, // Report Count (3)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x10, // Report ID (16)
|
||||
0x09, 0x26, // Usage (0x26)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x11, // Report ID (17)
|
||||
0x09, 0x27, // Usage (0x27)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x12, // Report ID (18)
|
||||
0x06, 0x02, 0xFF, // Usage Page (Vendor Defined 0xFF02)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x95, 0x0F, // Report Count (15)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x13, // Report ID (19)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x95, 0x16, // Report Count (22)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x14, // Report ID (20)
|
||||
0x06, 0x05, 0xFF, // Usage Page (Vendor Defined 0xFF05)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x95, 0x10, // Report Count (16)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x15, // Report ID (21)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x95, 0x2C, // Report Count (44)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x06, 0x80, 0xFF, // Usage Page (Vendor Defined 0xFF80)
|
||||
0x85, 0x80, // Report ID (-128)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x81, // Report ID (-127)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x82, // Report ID (-126)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x95, 0x05, // Report Count (5)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x83, // Report ID (-125)
|
||||
0x09, 0x23, // Usage (0x23)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x84, // Report ID (-124)
|
||||
0x09, 0x24, // Usage (0x24)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x85, // Report ID (-123)
|
||||
0x09, 0x25, // Usage (0x25)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x86, // Report ID (-122)
|
||||
0x09, 0x26, // Usage (0x26)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x87, // Report ID (-121)
|
||||
0x09, 0x27, // Usage (0x27)
|
||||
0x95, 0x23, // Report Count (35)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x88, // Report ID (-120)
|
||||
0x09, 0x28, // Usage (0x28)
|
||||
0x95, 0x22, // Report Count (34)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x89, // Report ID (-119)
|
||||
0x09, 0x29, // Usage (0x29)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x90, // Report ID (-112)
|
||||
0x09, 0x30, // Usage (0x30)
|
||||
0x95, 0x05, // Report Count (5)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x91, // Report ID (-111)
|
||||
0x09, 0x31, // Usage (0x31)
|
||||
0x95, 0x03, // Report Count (3)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x92, // Report ID (-110)
|
||||
0x09, 0x32, // Usage (0x32)
|
||||
0x95, 0x03, // Report Count (3)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0x93, // Report ID (-109)
|
||||
0x09, 0x33, // Usage (0x33)
|
||||
0x95, 0x0C, // Report Count (12)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA0, // Report ID (-96)
|
||||
0x09, 0x40, // Usage (0x40)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA1, // Report ID (-95)
|
||||
0x09, 0x41, // Usage (0x41)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA2, // Report ID (-94)
|
||||
0x09, 0x42, // Usage (0x42)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA3, // Report ID (-93)
|
||||
0x09, 0x43, // Usage (0x43)
|
||||
0x95, 0x30, // Report Count (48)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA4, // Report ID (-92)
|
||||
0x09, 0x44, // Usage (0x44)
|
||||
0x95, 0x0D, // Report Count (13)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA5, // Report ID (-91)
|
||||
0x09, 0x45, // Usage (0x45)
|
||||
0x95, 0x15, // Report Count (21)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA6, // Report ID (-90)
|
||||
0x09, 0x46, // Usage (0x46)
|
||||
0x95, 0x15, // Report Count (21)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF0, // Report ID (-16)
|
||||
0x09, 0x47, // Usage (0x47)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF1, // Report ID (-15)
|
||||
0x09, 0x48, // Usage (0x48)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xF2, // Report ID (-14)
|
||||
0x09, 0x49, // Usage (0x49)
|
||||
0x95, 0x0F, // Report Count (15)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA7, // Report ID (-89)
|
||||
0x09, 0x4A, // Usage (0x4A)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA8, // Report ID (-88)
|
||||
0x09, 0x4B, // Usage (0x4B)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xA9, // Report ID (-87)
|
||||
0x09, 0x4C, // Usage (0x4C)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xAA, // Report ID (-86)
|
||||
0x09, 0x4E, // Usage (0x4E)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xAB, // Report ID (-85)
|
||||
0x09, 0x4F, // Usage (0x4F)
|
||||
0x95, 0x39, // Report Count (57)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xAC, // Report ID (-84)
|
||||
0x09, 0x50, // Usage (0x50)
|
||||
0x95, 0x39, // Report Count (57)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xAD, // Report ID (-83)
|
||||
0x09, 0x51, // Usage (0x51)
|
||||
0x95, 0x0B, // Report Count (11)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xAE, // Report ID (-82)
|
||||
0x09, 0x52, // Usage (0x52)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xAF, // Report ID (-81)
|
||||
0x09, 0x53, // Usage (0x53)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xB0, // Report ID (-80)
|
||||
0x09, 0x54, // Usage (0x54)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xB1, // Report ID (-79)
|
||||
0x09, 0x55, // Usage (0x55)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xB2, // Report ID (-78)
|
||||
0x09, 0x56, // Usage (0x56)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xE0, // Report ID (-32)
|
||||
0x09, 0x57, // Usage (0x57)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xB3, // Report ID (-77)
|
||||
0x09, 0x55, // Usage (0x55)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x85, 0xB4, // Report ID (-76)
|
||||
0x09, 0x55, // Usage (0x55)
|
||||
0x95, 0x3F, // Report Count (63)
|
||||
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
// MAC Address
|
||||
static uint8_t ps4_0x81_report[] = {0x39, 0x39, 0x39, 0x68, 0x22, 0x00};
|
||||
|
||||
// Version Info
|
||||
static const uint8_t ps4_0xa3_report[] = {0x4a, 0x75, 0x6c, 0x20, 0x31, 0x31, 0x20, 0x32, 0x30, 0x31, 0x36, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x3a, 0x33, 0x33, 0x3a, 0x33, 0x38,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x64,
|
||||
0x01, 0x00, 0x00, 0x00, 0x09, 0x70, 0x00, 0x02, 0x00, 0x80, 0x03, 0x00};
|
||||
|
||||
// Calibration Data
|
||||
static const uint8_t ps4_0x02_report[] = {0x04, 0x00, 0xf9, 0xff, 0x06, 0x00, 0x1d, 0x22, 0xec, 0xdd, 0x68, 0x22,
|
||||
0x88, 0xdd, 0xa9, 0x23, 0x62, 0xdc, 0x1c, 0x02, 0x1c, 0x02, 0x05, 0x20,
|
||||
0xfb, 0xdf, 0x49, 0x20, 0xb7, 0xdf, 0x0d, 0x20, 0xf4, 0xdf, 0x01, 0x00};
|
||||
|
||||
static hid_ps4_report_t last_report = {};
|
||||
|
||||
bool send_hid_ps4_report(usb_report_t report) {
|
||||
bool result = false;
|
||||
if (tud_hid_ready()) {
|
||||
result = tud_hid_report(0, report.data, report.size);
|
||||
}
|
||||
|
||||
memcpy(&last_report, report.data, tu_min16(report.size, sizeof(hid_ps4_report_t)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t hid_ps4_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen) {
|
||||
(void)itf;
|
||||
(void)reqlen;
|
||||
|
||||
static bool do_init_mac = true;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_INPUT) {
|
||||
memcpy(&buffer, &last_report, sizeof(hid_ps4_report_t));
|
||||
return sizeof(hid_ps4_report_t);
|
||||
} else if (report_type == HID_REPORT_TYPE_FEATURE) {
|
||||
switch (report_id) {
|
||||
case 0x81:
|
||||
if (do_init_mac) {
|
||||
pico_unique_board_id_t uid;
|
||||
pico_get_unique_board_id(&uid);
|
||||
|
||||
// Genrate manufacturer specific using pico board id
|
||||
for (uint8_t i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; ++i) {
|
||||
ps4_0x81_report[(i % 3)] ^= uid.id[i];
|
||||
}
|
||||
|
||||
do_init_mac = false;
|
||||
}
|
||||
|
||||
memcpy(buffer, ps4_0x81_report, sizeof(ps4_0x81_report));
|
||||
return sizeof(ps4_0x81_report);
|
||||
case 0xa3:
|
||||
memcpy(buffer, ps4_0xa3_report, sizeof(ps4_0xa3_report));
|
||||
return sizeof(ps4_0xa3_report);
|
||||
case 0x02:
|
||||
memcpy(buffer, ps4_0x02_report, sizeof(ps4_0x02_report));
|
||||
return sizeof(ps4_0x02_report);
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct __attribute((packed, aligned(1))) {
|
||||
uint8_t content_flags; // 0x01: Rumble, 0x02: Color, 0x04: Flash
|
||||
uint8_t unknown1[2];
|
||||
uint8_t rumble_weak;
|
||||
uint8_t rumble_strong;
|
||||
uint8_t led_red;
|
||||
uint8_t led_green;
|
||||
uint8_t led_blue;
|
||||
uint8_t flash_bright_time;
|
||||
uint8_t flash_dark_time;
|
||||
uint8_t unknown2[21];
|
||||
} hid_ps4_ouput_report_t;
|
||||
|
||||
void hid_ps4_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize) {
|
||||
(void)itf;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_INVALID) {
|
||||
if (bufsize > 0) {
|
||||
report_id = buffer[0];
|
||||
buffer = &buffer[1];
|
||||
bufsize--;
|
||||
}
|
||||
}
|
||||
|
||||
switch (report_id) {
|
||||
case 0x05:
|
||||
if (bufsize == sizeof(hid_ps4_ouput_report_t)) {
|
||||
hid_ps4_ouput_report_t *report = (hid_ps4_ouput_report_t *)buffer;
|
||||
if (report->content_flags & 0x02) {
|
||||
usb_player_led_t player_led = {.type = USB_PLAYER_LED_COLOR,
|
||||
.red = report->led_red,
|
||||
.green = report->led_green,
|
||||
.blue = report->led_blue};
|
||||
usb_driver_get_player_led_cb()(player_led);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
130
src/usb/hid_switch_driver.c
Normal file
130
src/usb/hid_switch_driver.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include "usb/hid_switch_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "class/hid/hid_device.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
const tusb_desc_device_t switch_tatacon_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_UNSPECIFIED,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = 0x0F0D, // HORI
|
||||
.idProduct = 0x00F0, // NSW-079 aka Taiko Drum
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUFACTURER,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
const tusb_desc_device_t switch_horipad_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_UNSPECIFIED,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = 0x0F0D, // HORI
|
||||
.idProduct = 0x00C1, // HORIPAD
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUFACTURER,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
USBD_ITF_HID,
|
||||
USBD_ITF_MAX,
|
||||
};
|
||||
|
||||
#define USBD_SWITCH_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
|
||||
const uint8_t switch_desc_cfg[] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_LANGUAGE, USBD_SWITCH_DESC_LEN, 0, USBD_MAX_POWER_MAX),
|
||||
TUD_HID_INOUT_DESCRIPTOR(USBD_ITF_HID, USBD_STR_SWITCH, 0, 86, 0x02, 0x81, CFG_TUD_HID_EP_BUFSIZE, 1),
|
||||
};
|
||||
|
||||
const uint8_t switch_desc_hid_report[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, // Usage (Game Pad)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x45, 0x01, // Physical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x10, // Report Count (16)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x10, // Usage Maximum (0x10)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x25, 0x07, // Logical Maximum (7)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
||||
0x65, 0x00, // Unit (None)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x0A, 0x21, 0x26, // Usage (0x2621)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
static hid_switch_report_t last_report = {};
|
||||
|
||||
bool send_hid_switch_report(usb_report_t report) {
|
||||
bool result = false;
|
||||
if (tud_hid_ready()) {
|
||||
result = tud_hid_report(0, report.data, report.size);
|
||||
}
|
||||
|
||||
memcpy(&last_report, report.data, tu_min16(report.size, sizeof(hid_switch_report_t)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t hid_switch_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer,
|
||||
uint16_t reqlen) {
|
||||
(void)itf;
|
||||
(void)report_id;
|
||||
(void)reqlen;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_INPUT) {
|
||||
memcpy(buffer, &last_report, sizeof(hid_switch_report_t));
|
||||
return sizeof(hid_switch_report_t);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hid_switch_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer,
|
||||
uint16_t bufsize) {
|
||||
(void)itf;
|
||||
(void)report_id;
|
||||
(void)report_type;
|
||||
(void)bufsize;
|
||||
(void)buffer;
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
#include "usb/usb_driver.h"
|
||||
#include "usb/debug_driver.h"
|
||||
// #include "usb/hid_driver.h"
|
||||
#include "usb/hid_driver.h"
|
||||
#include "usb/xinput_driver.h"
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
static usb_mode_t usbd_mode = USB_MODE_DEBUG;
|
||||
static usbd_player_led_cb_t usbd_player_led_cb = NULL;
|
||||
static const tusb_desc_device_t *usbd_desc_device = NULL;
|
||||
static const uint8_t *usbd_desc_cfg = NULL;
|
||||
static const uint8_t *usbd_desc_hid_report = NULL;
|
||||
@ -18,12 +19,12 @@ static bool (*usbd_receive_report)() = NULL;
|
||||
static char usbd_serial_str[USBD_SERIAL_STR_SIZE] = {};
|
||||
|
||||
char *const usbd_desc_str[] = {
|
||||
[USBD_STR_MANUFACTURER] = USBD_MANUFACTURER, //
|
||||
[USBD_STR_PRODUCT] = USBD_PRODUCT, //
|
||||
[USBD_STR_SERIAL] = usbd_serial_str, //
|
||||
// [USBD_STR_SWITCH] = USBD_SWITCH_NAME, //
|
||||
// [USBD_STR_PS3] = USBD_PS3_NAME, //
|
||||
// [USBD_STR_PS4] = USBD_PS4_NAME, //
|
||||
[USBD_STR_MANUFACTURER] = USBD_MANUFACTURER, //
|
||||
[USBD_STR_PRODUCT] = USBD_PRODUCT, //
|
||||
[USBD_STR_SERIAL] = usbd_serial_str, //
|
||||
[USBD_STR_SWITCH] = USBD_SWITCH_NAME, //
|
||||
[USBD_STR_PS3] = USBD_PS3_NAME, //
|
||||
[USBD_STR_PS4] = USBD_PS4_NAME, //
|
||||
[USBD_STR_XINPUT] = USBD_XINPUT_NAME, //
|
||||
[USBD_STR_CDC] = USBD_DEBUG_CDC_NAME, //
|
||||
[USBD_STR_RPI_RESET] = USBD_DEBUG_RESET_NAME, //
|
||||
@ -33,38 +34,46 @@ void usb_driver_init(usb_mode_t mode) {
|
||||
usbd_mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
// case USB_MODE_SWITCH_TATACON:
|
||||
// usbd_desc_device = &switch_tatacon_desc_device;
|
||||
// usbd_desc_cfg = switch_desc_cfg;
|
||||
// usbd_desc_hid_report = switch_desc_hid_report;
|
||||
// usbd_app_driver = &hid_app_driver;
|
||||
// usbd_send_report = send_hid_switch_report;
|
||||
// usbd_receive_report = NULL;
|
||||
// break;
|
||||
// case USB_MODE_SWITCH_HORIPAD:
|
||||
// usbd_desc_device = &switch_horipad_desc_device;
|
||||
// usbd_desc_cfg = switch_desc_cfg;
|
||||
// usbd_desc_hid_report = switch_desc_hid_report;
|
||||
// usbd_app_driver = &hid_app_driver;
|
||||
// usbd_send_report = send_hid_switch_report;
|
||||
// usbd_receive_report = NULL;
|
||||
// break;
|
||||
// case USB_MODE_DUALSHOCK3:
|
||||
// usbd_desc_device = &ds3_desc_device;
|
||||
// usbd_desc_cfg = ps3_desc_cfg;
|
||||
// usbd_desc_hid_report = ps3_desc_hid_report;
|
||||
// usbd_app_driver = &hid_app_driver;
|
||||
// usbd_send_report = send_hid_ps3_report;
|
||||
// usbd_receive_report = NULL;
|
||||
// break;
|
||||
// case USB_MODE_DUALSHOCK4:
|
||||
// usbd_desc_device = &ds4_desc_device;
|
||||
// usbd_desc_cfg = ps4_desc_cfg;
|
||||
// usbd_desc_hid_report = ps4_desc_hid_report;
|
||||
// usbd_app_driver = &hid_app_driver;
|
||||
// usbd_send_report = send_hid_ps4_report;
|
||||
// usbd_receive_report = NULL;
|
||||
// break;
|
||||
case USB_MODE_SWITCH_TATACON:
|
||||
usbd_desc_device = &switch_tatacon_desc_device;
|
||||
usbd_desc_cfg = switch_desc_cfg;
|
||||
usbd_desc_hid_report = switch_desc_hid_report;
|
||||
usbd_app_driver = &hid_app_driver;
|
||||
usbd_send_report = send_hid_switch_report;
|
||||
usbd_receive_report = NULL;
|
||||
break;
|
||||
case USB_MODE_SWITCH_HORIPAD:
|
||||
usbd_desc_device = &switch_horipad_desc_device;
|
||||
usbd_desc_cfg = switch_desc_cfg;
|
||||
usbd_desc_hid_report = switch_desc_hid_report;
|
||||
usbd_app_driver = &hid_app_driver;
|
||||
usbd_send_report = send_hid_switch_report;
|
||||
usbd_receive_report = NULL;
|
||||
break;
|
||||
case USB_MODE_DUALSHOCK3:
|
||||
usbd_desc_device = &ds3_desc_device;
|
||||
usbd_desc_cfg = ps3_desc_cfg;
|
||||
usbd_desc_hid_report = ps3_desc_hid_report;
|
||||
usbd_app_driver = &hid_app_driver;
|
||||
usbd_send_report = send_hid_ps3_report;
|
||||
usbd_receive_report = NULL;
|
||||
break;
|
||||
case USB_MODE_PS4_TATACON:
|
||||
usbd_desc_device = &ps4_tatacon_desc_device;
|
||||
usbd_desc_cfg = ps4_desc_cfg;
|
||||
usbd_desc_hid_report = ps4_desc_hid_report;
|
||||
usbd_app_driver = &hid_app_driver;
|
||||
usbd_send_report = send_hid_ps4_report;
|
||||
usbd_receive_report = NULL;
|
||||
break;
|
||||
case USB_MODE_DUALSHOCK4:
|
||||
usbd_desc_device = &ds4_desc_device;
|
||||
usbd_desc_cfg = ps4_desc_cfg;
|
||||
usbd_desc_hid_report = ps4_desc_hid_report;
|
||||
usbd_app_driver = &hid_app_driver;
|
||||
usbd_send_report = send_hid_ps4_report;
|
||||
usbd_receive_report = NULL;
|
||||
break;
|
||||
case USB_MODE_XBOX360:
|
||||
usbd_desc_device = &xinput_desc_device;
|
||||
usbd_desc_cfg = xinput_desc_cfg;
|
||||
@ -110,6 +119,10 @@ void usb_driver_send_and_receive_report(usb_report_t report) {
|
||||
}
|
||||
}
|
||||
|
||||
void usb_driver_set_player_led_cb(usbd_player_led_cb_t cb) { usbd_player_led_cb = cb; };
|
||||
|
||||
usbd_player_led_cb_t usb_driver_get_player_led_cb() { return usbd_player_led_cb; };
|
||||
|
||||
const uint8_t *tud_descriptor_device_cb(void) { return (const uint8_t *)usbd_desc_device; }
|
||||
|
||||
const uint8_t *tud_descriptor_configuration_cb(uint8_t __unused index) { return usbd_desc_cfg; }
|
||||
|
@ -111,10 +111,34 @@ static bool xinput_control_xfer_callback(uint8_t rhport, uint8_t stage, tusb_con
|
||||
|
||||
static bool xinput_xfer_callback(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
|
||||
(void)rhport;
|
||||
(void)ep_addr;
|
||||
(void)result;
|
||||
(void)xferred_bytes;
|
||||
|
||||
if (result == XFER_RESULT_SUCCESS && ep_addr == endpoint_out) {
|
||||
if (xinput_out_buffer[0] == 0x01) { // 0x00 is rumble, 0x01 is led
|
||||
usb_player_led_t player_led = {.type = USB_PLAYER_LED_ID, .id = 0};
|
||||
|
||||
switch (xinput_out_buffer[2]) {
|
||||
case 0x02:
|
||||
case 0x06:
|
||||
player_led.id = 0x01;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x07:
|
||||
player_led.id = 0x02;
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x08:
|
||||
player_led.id = 0x04;
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x09:
|
||||
player_led.id = 0x08;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
usb_driver_get_player_led_cb()(player_led);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -9,18 +9,19 @@ InputState::InputState()
|
||||
: drum({{false, 0}, {false, 0}, {false, 0}, {false, 0}}),
|
||||
controller(
|
||||
{{false, false, false, false}, {false, false, false, false, false, false, false, false, false, false}}),
|
||||
m_switch_report({}), m_ps3_report({}), m_ps4_report({}),
|
||||
m_xinput_report({0x00, sizeof(xinput_report_t), 0, 0, 0, 0, 0, 0, 0, 0, {}}) {}
|
||||
|
||||
usb_report_t InputState::getReport(usb_mode_t mode) {
|
||||
switch (mode) {
|
||||
// case USB_MODE_SWITCH_TATACON:
|
||||
// case USB_MODE_SWITCH_HORIPAD:
|
||||
// return getSwitchReport();
|
||||
// case USB_MODE_DUALSHOCK3:
|
||||
// return getPS3InputReport();
|
||||
// case USB_MODE_PS4_DIVACON:
|
||||
// case USB_MODE_DUALSHOCK4:
|
||||
// return getPS4InputReport();
|
||||
case USB_MODE_SWITCH_TATACON:
|
||||
case USB_MODE_SWITCH_HORIPAD:
|
||||
return getSwitchReport();
|
||||
case USB_MODE_DUALSHOCK3:
|
||||
return getPS3InputReport();
|
||||
case USB_MODE_PS4_TATACON:
|
||||
case USB_MODE_DUALSHOCK4:
|
||||
return getPS4InputReport();
|
||||
case USB_MODE_XBOX360:
|
||||
return getXinputReport();
|
||||
case USB_MODE_DEBUG:
|
||||
@ -29,6 +30,180 @@ usb_report_t InputState::getReport(usb_mode_t mode) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t getHidHat(const InputState::Controller::DPad dpad) {
|
||||
if (dpad.up && dpad.right) {
|
||||
return 0x01;
|
||||
} else if (dpad.down && dpad.right) {
|
||||
return 0x03;
|
||||
} else if (dpad.down && dpad.left) {
|
||||
return 0x05;
|
||||
} else if (dpad.up && dpad.left) {
|
||||
return 0x07;
|
||||
} else if (dpad.up) {
|
||||
return 0x00;
|
||||
} else if (dpad.right) {
|
||||
return 0x02;
|
||||
} else if (dpad.down) {
|
||||
return 0x04;
|
||||
} else if (dpad.left) {
|
||||
return 0x06;
|
||||
}
|
||||
|
||||
return 0x08;
|
||||
}
|
||||
|
||||
usb_report_t InputState::getSwitchReport() {
|
||||
m_switch_report.buttons = 0 //
|
||||
| (controller.buttons.west ? (1 << 0) : 0) // Y
|
||||
| (controller.buttons.south ? (1 << 1) : 0) // B
|
||||
| (controller.buttons.east ? (1 << 2) : 0) // A
|
||||
| (controller.buttons.north ? (1 << 3) : 0) // X
|
||||
| (controller.buttons.l ? (1 << 4) : 0) // L
|
||||
| (controller.buttons.r ? (1 << 5) : 0) // R
|
||||
| (drum.ka_left.triggered ? (1 << 6) : 0) // ZL
|
||||
| (drum.ka_right.triggered ? (1 << 7) : 0) // ZR
|
||||
| (controller.buttons.select ? (1 << 8) : 0) // -
|
||||
| (controller.buttons.start ? (1 << 9) : 0) // +
|
||||
| (drum.don_left.triggered ? (1 << 10) : 0) // LS
|
||||
| (drum.don_right.triggered ? (1 << 11) : 0) // RS
|
||||
| (controller.buttons.home ? (1 << 12) : 0) // Home
|
||||
| (controller.buttons.share ? (1 << 13) : 0); // Capture
|
||||
|
||||
m_switch_report.hat = getHidHat(controller.dpad);
|
||||
|
||||
// Center all sticks
|
||||
m_switch_report.lx = 0x80;
|
||||
m_switch_report.ly = 0x80;
|
||||
m_switch_report.rx = 0x80;
|
||||
m_switch_report.ry = 0x80;
|
||||
|
||||
return {(uint8_t *)&m_switch_report, sizeof(hid_switch_report_t)};
|
||||
}
|
||||
|
||||
usb_report_t InputState::getPS3InputReport() {
|
||||
memset(&m_ps3_report, 0, sizeof(m_ps3_report));
|
||||
|
||||
m_ps3_report.report_id = 0x01;
|
||||
|
||||
m_ps3_report.buttons1 = 0 //
|
||||
| (controller.buttons.select ? (1 << 0) : 0) // Select
|
||||
| (drum.don_left.triggered ? (1 << 1) : 0) // L3
|
||||
| (drum.don_right.triggered ? (1 << 2) : 0) // R3
|
||||
| (controller.buttons.start ? (1 << 3) : 0) // Start
|
||||
| (controller.dpad.up ? (1 << 4) : 0) // Up
|
||||
| (controller.dpad.right ? (1 << 5) : 0) // Right
|
||||
| (controller.dpad.down ? (1 << 6) : 0) // Down
|
||||
| (controller.dpad.left ? (1 << 7) : 0); // Left
|
||||
m_ps3_report.buttons2 = 0 | (drum.ka_left.triggered ? (1 << 0) : 0) // L2
|
||||
| (drum.ka_right.triggered ? (1 << 1) : 0) // R2
|
||||
| (controller.buttons.l ? (1 << 2) : 0) // L1
|
||||
| (controller.buttons.r ? (1 << 3) : 0) // R1
|
||||
| (controller.buttons.north ? (1 << 4) : 0) // Triangle
|
||||
| (controller.buttons.east ? (1 << 5) : 0) // Circle
|
||||
| (controller.buttons.south ? (1 << 6) : 0) // Cross
|
||||
| (controller.buttons.west ? (1 << 7) : 0); // Square
|
||||
m_ps3_report.buttons3 = 0 | (controller.buttons.home ? (1 << 0) : 0); // Home
|
||||
|
||||
// Center all sticks
|
||||
m_ps3_report.lx = 0x80;
|
||||
m_ps3_report.ly = 0x80;
|
||||
m_ps3_report.rx = 0x80;
|
||||
m_ps3_report.ry = 0x80;
|
||||
|
||||
m_ps3_report.lt = (drum.ka_left.triggered ? 0xff : 0);
|
||||
m_ps3_report.rt = (drum.ka_right.triggered ? 0xff : 0);
|
||||
|
||||
m_ps3_report.unknown_0x02_1 = 0x02;
|
||||
m_ps3_report.battery = 0xef;
|
||||
m_ps3_report.unknown_0x12 = 0x12;
|
||||
|
||||
m_ps3_report.unknown[0] = 0x12;
|
||||
m_ps3_report.unknown[1] = 0xf8;
|
||||
m_ps3_report.unknown[2] = 0x77;
|
||||
m_ps3_report.unknown[3] = 0x00;
|
||||
m_ps3_report.unknown[4] = 0x40;
|
||||
|
||||
m_ps3_report.acc_x = 511;
|
||||
m_ps3_report.acc_y = 511;
|
||||
m_ps3_report.acc_z = 511;
|
||||
|
||||
m_ps3_report.unknown_0x02_2 = 0x02;
|
||||
|
||||
return {(uint8_t *)&m_ps3_report, sizeof(hid_ps3_report_t)};
|
||||
}
|
||||
|
||||
usb_report_t InputState::getPS4InputReport() {
|
||||
static uint8_t report_counter = 0;
|
||||
static uint8_t last_timestamp = 0;
|
||||
|
||||
memset(&m_ps4_report, 0, sizeof(m_ps4_report));
|
||||
|
||||
m_ps4_report.report_id = 0x01;
|
||||
|
||||
// Center all sticks
|
||||
m_ps4_report.lx = 0x80;
|
||||
m_ps4_report.ly = 0x80;
|
||||
m_ps4_report.rx = 0x80;
|
||||
m_ps4_report.ry = 0x80;
|
||||
|
||||
m_ps4_report.buttons1 = getHidHat(controller.dpad) //
|
||||
| (controller.buttons.west ? (1 << 4) : 0) // Square
|
||||
| (controller.buttons.south ? (1 << 5) : 0) // Cross
|
||||
| (controller.buttons.east ? (1 << 6) : 0) // Circle
|
||||
| (controller.buttons.north ? (1 << 7) : 0); // Triangle
|
||||
m_ps4_report.buttons2 = 0 //
|
||||
| (controller.buttons.l ? (1 << 0) : 0) // L1
|
||||
| (controller.buttons.r ? (1 << 1) : 0) // R1
|
||||
| (drum.ka_left.triggered ? (1 << 2) : 0) // L2
|
||||
| (drum.ka_right.triggered ? (1 << 3) : 0) // R2
|
||||
| (controller.buttons.share ? (1 << 4) : 0) // Share
|
||||
| (controller.buttons.start ? (1 << 5) : 0) // Option
|
||||
| (drum.don_left.triggered ? (1 << 6) : 0) // L3
|
||||
| (drum.don_right.triggered ? (1 << 7) : 0); // R3
|
||||
m_ps4_report.buttons3 = (report_counter << 2) //
|
||||
| (controller.buttons.home ? (1 << 0) : 0) // PS
|
||||
| (controller.buttons.select ? (1 << 1) : 0); // T-Pad
|
||||
|
||||
m_ps4_report.lt = (drum.ka_left.triggered ? 0xFF : 0);
|
||||
m_ps4_report.rt = (drum.ka_right.triggered ? 0xFF : 0);
|
||||
|
||||
// Used for gyro/accel, so we don't need to be precise here.
|
||||
m_ps4_report.timestamp = last_timestamp;
|
||||
|
||||
m_ps4_report.battery = 0 | (1 << 4) | 11;
|
||||
|
||||
m_ps4_report.gyrox = 0;
|
||||
m_ps4_report.gyroy = 0;
|
||||
m_ps4_report.gyroz = 0;
|
||||
m_ps4_report.accelx = 0;
|
||||
m_ps4_report.accely = 0;
|
||||
m_ps4_report.accelz = 0;
|
||||
|
||||
m_ps4_report.extension = 0x01;
|
||||
|
||||
m_ps4_report.touchpad_event_active = 0;
|
||||
m_ps4_report.touchpad_counter = 0;
|
||||
m_ps4_report.touchpad1_touches = (1 << 7);
|
||||
m_ps4_report.touchpad2_touches = (1 << 7);
|
||||
|
||||
m_ps4_report.unknown3[1] = 0x80;
|
||||
m_ps4_report.unknown3[5] = 0x80;
|
||||
m_ps4_report.unknown3[10] = 0x80;
|
||||
m_ps4_report.unknown3[14] = 0x80;
|
||||
m_ps4_report.unknown3[19] = 0x80;
|
||||
|
||||
// This method actually gets called more often than the report is sent,
|
||||
// so counters are not consecutive ... let's see if this turns out to
|
||||
// be a problem.
|
||||
last_timestamp += 188;
|
||||
report_counter++;
|
||||
if (report_counter > (UINT8_MAX >> 2)) {
|
||||
report_counter = 0;
|
||||
}
|
||||
|
||||
return {(uint8_t *)&m_ps4_report, sizeof(hid_ps4_report_t)};
|
||||
}
|
||||
|
||||
usb_report_t InputState::getXinputReport() {
|
||||
m_xinput_report.buttons1 = 0 //
|
||||
| (controller.dpad.up ? (1 << 0) : 0) // Dpad Up
|
||||
|
Loading…
x
Reference in New Issue
Block a user