mirror of
https://github.com/ravinrabbid/DonCon2040.git
synced 2025-02-07 06:51:15 +01:00
Add xinput driver
This commit is contained in:
parent
50486c3f20
commit
43aa53382c
@ -19,7 +19,7 @@ typedef enum {
|
||||
// USB_MODE_SWITCH_HORIPAD,
|
||||
// USB_MODE_DUALSHOCK3,
|
||||
// USB_MODE_DUALSHOCK4,
|
||||
// USB_MODE_XBOX360,
|
||||
USB_MODE_XBOX360,
|
||||
USB_MODE_DEBUG,
|
||||
} usb_mode_t;
|
||||
|
||||
|
41
include/usb/xinput_driver.h
Normal file
41
include/usb/xinput_driver.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _USB_XINPUT_DRIVER_H_
|
||||
#define _USB_XINPUT_DRIVER_H_
|
||||
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USBD_XINPUT_NAME "XInput Gamepad"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct __attribute((packed, aligned(1))) {
|
||||
uint8_t report_id;
|
||||
uint8_t report_size;
|
||||
uint8_t buttons1;
|
||||
uint8_t buttons2;
|
||||
uint8_t lt;
|
||||
uint8_t rt;
|
||||
int16_t lx;
|
||||
int16_t ly;
|
||||
int16_t rx;
|
||||
int16_t ry;
|
||||
uint8_t _reserved[6];
|
||||
} xinput_report_t;
|
||||
|
||||
bool receive_xinput_report(void);
|
||||
bool send_xinput_report(usb_report_t report);
|
||||
|
||||
extern const tusb_desc_device_t xinput_desc_device;
|
||||
extern const uint8_t xinput_desc_cfg[];
|
||||
extern const usbd_class_driver_t xinput_app_driver;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _USB_XINPUT_DRIVER_H_
|
@ -2,6 +2,7 @@
|
||||
#define _UTILS_INPUTSTATE_H_
|
||||
|
||||
#include "usb/usb_driver.h"
|
||||
#include "usb/xinput_driver.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
@ -18,8 +19,10 @@ struct InputState {
|
||||
Drum drum;
|
||||
|
||||
private:
|
||||
xinput_report_t m_xinput_report;
|
||||
std::string m_debug_report;
|
||||
|
||||
usb_report_t getXinputReport();
|
||||
usb_report_t getDebugReport();
|
||||
|
||||
public:
|
||||
|
@ -36,7 +36,7 @@ int main() {
|
||||
|
||||
Utils::InputState input_state;
|
||||
Peripherals::Drum drum(Config::Default::drum_config);
|
||||
usb_mode_t mode = USB_MODE_DEBUG;
|
||||
usb_mode_t mode = USB_MODE_XBOX360;
|
||||
|
||||
usb_driver_init(mode);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "usb/usb_driver.h"
|
||||
#include "usb/debug_driver.h"
|
||||
// #include "usb/hid_driver.h"
|
||||
// #include "usb/xinput_driver.h"
|
||||
#include "usb/xinput_driver.h"
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "pico/unique_id.h"
|
||||
@ -18,13 +18,13 @@ 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_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_XINPUT] = USBD_XINPUT_NAME, //
|
||||
[USBD_STR_CDC] = USBD_DEBUG_CDC_NAME, //
|
||||
[USBD_STR_RPI_RESET] = USBD_DEBUG_RESET_NAME, //
|
||||
};
|
||||
@ -65,13 +65,13 @@ void usb_driver_init(usb_mode_t mode) {
|
||||
// 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;
|
||||
// usbd_app_driver = &xinput_app_driver;
|
||||
// usbd_send_report = send_xinput_report;
|
||||
// usbd_receive_report = receive_xinput_report;
|
||||
// break;
|
||||
case USB_MODE_XBOX360:
|
||||
usbd_desc_device = &xinput_desc_device;
|
||||
usbd_desc_cfg = xinput_desc_cfg;
|
||||
usbd_app_driver = &xinput_app_driver;
|
||||
usbd_send_report = send_xinput_report;
|
||||
usbd_receive_report = receive_xinput_report;
|
||||
break;
|
||||
case USB_MODE_DEBUG:
|
||||
usbd_desc_device = &debug_desc_device;
|
||||
usbd_desc_cfg = debug_desc_cfg;
|
||||
|
130
src/usb/xinput_driver.c
Normal file
130
src/usb/xinput_driver.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include "usb/xinput_driver.h"
|
||||
#include "usb/usb_driver.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
#define XINPUT_OUT_SIZE 32
|
||||
#define XINPUT_INTERFACE_SUBCLASS (0x5D)
|
||||
#define XINPUT_INTERFACE_PROTOCOL (0x01)
|
||||
#define TUD_XINPUT_DESC_LEN (39)
|
||||
|
||||
const tusb_desc_device_t xinput_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_VENDOR_SPECIFIC,
|
||||
.bDeviceSubClass = 0xFF,
|
||||
.bDeviceProtocol = 0xFF,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = 0x045E,
|
||||
.idProduct = 0x028E,
|
||||
.bcdDevice = 0x0114,
|
||||
.iManufacturer = USBD_STR_MANUFACTURER,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
USBD_ITF_XINPUT,
|
||||
USBD_ITF_MAX,
|
||||
};
|
||||
|
||||
#define TUD_XINPUT_DESCRIPTOR(_itfnum, _stridx) \
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, XINPUT_INTERFACE_SUBCLASS, \
|
||||
XINPUT_INTERFACE_PROTOCOL, _stridx, 0x10, 0x21, 0x10, 0x01, 0x01, 0x24, 0x81, 0x14, 0x03, 0x00, 0x03, 0x13, \
|
||||
0x01, 0x00, 0x03, 0x00, 0x07, 0x05, 0x81, 0x03, 0x20, 0x00, 0x01, 0x07, 0x05, 0x01, 0x03, 0x20, 0x00, 0x08
|
||||
|
||||
#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_XINPUT_DESC_LEN)
|
||||
|
||||
const uint8_t xinput_desc_cfg[USBD_DESC_LEN] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_LANGUAGE, USBD_DESC_LEN, 0, USBD_MAX_POWER_MAX),
|
||||
TUD_XINPUT_DESCRIPTOR(USBD_ITF_XINPUT, USBD_STR_XINPUT),
|
||||
};
|
||||
|
||||
static uint8_t endpoint_in = 0;
|
||||
static uint8_t endpoint_out = 0;
|
||||
static uint8_t xinput_out_buffer[XINPUT_OUT_SIZE] = {};
|
||||
|
||||
bool receive_xinput_report(void) {
|
||||
bool success = false;
|
||||
|
||||
if (tud_ready() && (endpoint_out != 0) && (!usbd_edpt_busy(0, endpoint_out))) {
|
||||
usbd_edpt_claim(0, endpoint_out); // Take control of OUT endpoint
|
||||
success = usbd_edpt_xfer(0, endpoint_out, xinput_out_buffer, XINPUT_OUT_SIZE); // Retrieve report buffer
|
||||
usbd_edpt_release(0, endpoint_out); // Release control of OUT endpoint
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool send_xinput_report(usb_report_t report) {
|
||||
bool success = false;
|
||||
|
||||
if (tud_ready() && // Is the device ready?
|
||||
(endpoint_in != 0) && (!usbd_edpt_busy(0, endpoint_in)) // Is the IN endpoint available?
|
||||
) {
|
||||
usbd_edpt_claim(0, endpoint_in); // Take control of IN endpoint
|
||||
success = usbd_edpt_xfer(0, endpoint_in, report.data, report.size); // Send report buffer
|
||||
usbd_edpt_release(0, endpoint_in); // Release control of IN endpoint
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void xinput_init(void) {}
|
||||
|
||||
static void xinput_reset(uint8_t rhport) { (void)rhport; }
|
||||
|
||||
static uint16_t xinput_open(uint8_t rhport, tusb_desc_interface_t const *itf_descriptor, uint16_t max_length) {
|
||||
uint16_t driver_length =
|
||||
sizeof(tusb_desc_interface_t) + (itf_descriptor->bNumEndpoints * sizeof(tusb_desc_endpoint_t)) + 16;
|
||||
|
||||
TU_VERIFY(max_length >= driver_length, 0);
|
||||
|
||||
uint8_t const *current_descriptor = tu_desc_next(itf_descriptor);
|
||||
uint8_t found_endpoints = 0;
|
||||
while ((found_endpoints < itf_descriptor->bNumEndpoints) && (driver_length <= max_length)) {
|
||||
tusb_desc_endpoint_t const *endpoint_descriptor = (tusb_desc_endpoint_t const *)current_descriptor;
|
||||
if (TUSB_DESC_ENDPOINT == tu_desc_type(endpoint_descriptor)) {
|
||||
TU_ASSERT(usbd_edpt_open(rhport, endpoint_descriptor));
|
||||
|
||||
if (tu_edpt_dir(endpoint_descriptor->bEndpointAddress) == TUSB_DIR_IN)
|
||||
endpoint_in = endpoint_descriptor->bEndpointAddress;
|
||||
else
|
||||
endpoint_out = endpoint_descriptor->bEndpointAddress;
|
||||
|
||||
++found_endpoints;
|
||||
}
|
||||
|
||||
current_descriptor = tu_desc_next(current_descriptor);
|
||||
}
|
||||
return driver_length;
|
||||
}
|
||||
|
||||
static bool xinput_control_xfer_callback(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) {
|
||||
(void)rhport;
|
||||
(void)stage;
|
||||
(void)request;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const usbd_class_driver_t xinput_app_driver = {
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
.name = "XINPUT",
|
||||
#endif
|
||||
.init = xinput_init,
|
||||
.reset = xinput_reset,
|
||||
.open = xinput_open,
|
||||
.control_xfer_cb = xinput_control_xfer_callback,
|
||||
.xfer_cb = xinput_xfer_callback,
|
||||
.sof = NULL};
|
@ -4,7 +4,9 @@
|
||||
|
||||
namespace Doncon::Utils {
|
||||
|
||||
InputState::InputState() : drum({false, false, false, false}) {}
|
||||
InputState::InputState()
|
||||
: drum({false, false, false, false}), 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) {
|
||||
@ -16,14 +18,45 @@ usb_report_t InputState::getReport(usb_mode_t mode) {
|
||||
// case USB_MODE_PS4_DIVACON:
|
||||
// case USB_MODE_DUALSHOCK4:
|
||||
// return getPS4InputReport();
|
||||
// case USB_MODE_XBOX360:
|
||||
// return getXinputReport();
|
||||
case USB_MODE_XBOX360:
|
||||
return getXinputReport();
|
||||
case USB_MODE_DEBUG:
|
||||
default:
|
||||
return getDebugReport();
|
||||
}
|
||||
}
|
||||
|
||||
usb_report_t InputState::getXinputReport() {
|
||||
m_xinput_report.buttons1 = 0 //
|
||||
| (false ? (1 << 0) : 0) // Dpad Up
|
||||
| (drum.don_left ? (1 << 1) : 0) // Dpad Down
|
||||
| (drum.ka_left ? (1 << 2) : 0) // Dpad Left
|
||||
| (false ? (1 << 3) : 0) // Dpad Right
|
||||
| (false ? (1 << 4) : 0) // Start
|
||||
| (false ? (1 << 5) : 0) // Select
|
||||
| (false ? (1 << 6) : 0) // L3
|
||||
| (false ? (1 << 7) : 0); // R3
|
||||
|
||||
m_xinput_report.buttons2 = 0 //
|
||||
| (false ? (1 << 0) : 0) // L1
|
||||
| (false ? (1 << 1) : 0) // R1
|
||||
| (false ? (1 << 2) : 0) // Guide
|
||||
| (drum.don_right ? (1 << 4) : 0) // A
|
||||
| (drum.ka_right ? (1 << 5) : 0) // B
|
||||
| (false ? (1 << 6) : 0) // X
|
||||
| (false ? (1 << 7) : 0); // Y
|
||||
|
||||
m_xinput_report.lt = 0;
|
||||
m_xinput_report.rt = 0;
|
||||
|
||||
m_xinput_report.lx = 0;
|
||||
m_xinput_report.ly = 0;
|
||||
m_xinput_report.rx = 0;
|
||||
m_xinput_report.ry = 0;
|
||||
|
||||
return {(uint8_t *)&m_xinput_report, sizeof(xinput_report_t)};
|
||||
}
|
||||
|
||||
usb_report_t InputState::getDebugReport() {
|
||||
std::stringstream out;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user