1
0
mirror of https://github.com/cathery/sys-con.git synced 2024-07-05 10:48:46 +00:00

Begin implementing Dualshock 4 controller

This commit is contained in:
cathery 2019-11-11 22:43:19 +03:00
parent 45321fa29d
commit 8d61e5b10b
5 changed files with 227 additions and 75 deletions

View File

@ -36,7 +36,8 @@ enum ProductIDs
PRODUCT_XBOXADAPTIVE = 0xb0a,
PRODUCT_DUALSHOCK3 = 0x268,
PRODUCT_DUALSHOCK4 = 0x5c4,
PRODUCT_DUALSHOCK4_1X = 0x5c4,
PRODUCT_DUALSHOCK4_2X = 0x9cc,
};
enum ControllerSupport

View File

@ -7,40 +7,68 @@
struct Dualshock4ButtonData
{
uint8_t type;
uint8_t length;
uint8_t padding0[2];
bool dpad_up : 1;
bool dpad_down : 1;
bool dpad_left : 1;
bool dpad_right : 1;
uint8_t stick_left_x;
uint8_t stick_left_y;
uint8_t stick_right_x;
uint8_t stick_right_y;
uint8_t dpad : 4;
bool square : 1;
bool cross : 1;
bool circle : 1;
bool triangle : 1;
bool l1 : 1;
bool r1 : 1;
bool l2 : 1;
bool r2 : 1;
bool share : 1;
bool options : 1;
bool l3 : 1;
bool r3 : 1;
bool psbutton : 1;
bool touchpad_press : 1;
uint8_t sequence_number : 6;
uint8_t l2_pressure;
uint8_t r2_pressure;
uint16_t timestamp;
uint8_t sensor_temperature;
uint16_t gyro_pitch;
uint16_t gyro_yaw;
uint16_t gyro_roll;
uint16_t accelerometer_x;
uint16_t accelerometer_y;
uint16_t accelerometer_z;
uint8_t padding1[5];
uint8_t battery_info : 5;
uint8_t padding2 : 2;
bool extension_detection : 1;
bool start : 1;
bool back : 1;
bool stick_left_click : 1;
bool stick_right_click : 1;
uint8_t padding3[2];
bool bumper_left : 1;
bool bumper_right : 1;
bool guide : 1;
bool dummy1 : 1; // Always 0.
uint8_t touches_count;
uint8_t touch_data_timestamp;
uint8_t touch0_id : 7;
bool touch0_is_invalid : 1;
uint8_t touch0_data[3];
uint8_t touch1_id : 7;
bool touch1_is_invalid : 1;
uint8_t touch1_data[3];
bool a : 1;
bool b : 1;
bool x : 1;
bool y : 1;
uint8_t padding4[2];
uint32_t crc32;
};
uint8_t trigger_left;
uint8_t trigger_right;
int16_t stick_left_x;
int16_t stick_left_y;
int16_t stick_right_x;
int16_t stick_right_y;
// Always 0.
uint32_t dummy2;
uint16_t dummy3;
enum Dualshock4Dpad
{
DS4_UP = 0x000,
DS4_UPRIGHT = 0x001,
DS4_RIGHT = 0x010,
DS4_DOWNRIGHT = 0x011,
DS4_DOWN = 0x100,
DS4_DOWNLEFT = 0x101,
DS4_LEFT = 0x110,
DS4_UPLEFT = 0x111,
};
class Dualshock4Controller : public IController

View File

@ -17,6 +17,9 @@ protected:
std::unique_ptr<IUSBDevice> m_device;
public:
uint8_t m_inputData[100];
bool m_UpdateCalled;
IController(std::unique_ptr<IUSBDevice> &&interface) : m_device(std::move(interface)) {}
virtual ~IController() = default;

View File

@ -3,6 +3,10 @@
static ControllerConfig _dualshock4ControllerConfig{};
const uint8_t kRumbleMagnitudeMax = 0xff;
const float kAxisMax = 255.0f;
const float kDpadMax = 7.0f;
Dualshock4Controller::Dualshock4Controller(std::unique_ptr<IUSBDevice> &&interface)
: IController(std::move(interface))
{
@ -12,6 +16,26 @@ Dualshock4Controller::~Dualshock4Controller()
{
Exit();
}
/*
uint32_t ComputeDualshock4Checksum(const uint8_t *report_data, uint16_t length)
{
constexpr uint8_t bt_header = 0xa2;
uint32_t crc = crc32(0xffffffff, &bt_header, 1);
return unaligned_crc32(crc, report_data, length);
}
*/
Status Dualshock4Controller::SendInitBytes()
{
uint8_t init_bytes[32] = {
//for bluetooth connection
//0x11, 0xC4, 0x00, 0x07, 0x00, 0x00,
0x05, 0x07, 0x00, 0x00,
0xFF, 0xFF,
0x00, 0x00, 0x40,
0x00, 0x00};
return m_outPipe->Write(init_bytes, sizeof(init_bytes));
}
Status Dualshock4Controller::Initialize()
{
@ -45,27 +69,44 @@ Status Dualshock4Controller::OpenInterfaces()
rc = interface->Open();
if (S_FAILED(rc))
return rc;
//TODO: check for numEndpoints before trying to open them!
if (interface->GetDescriptor()->bNumEndpoints >= 2)
if (interface->GetDescriptor()->bInterfaceProtocol != 0)
continue;
if (interface->GetDescriptor()->bNumEndpoints < 2)
continue;
if (!m_inPipe)
{
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, 1);
if (inEndpoint->GetDescriptor()->bLength != 0)
for (int i = 0; i != 15; ++i)
{
rc = inEndpoint->Open();
if (S_FAILED(rc))
return 5555;
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, i);
if (inEndpoint)
{
rc = inEndpoint->Open();
if (S_FAILED(rc))
return 61;
m_inPipe = inEndpoint;
m_inPipe = inEndpoint;
break;
}
}
}
IUSBEndpoint *outEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_OUT, 1);
if (outEndpoint->GetDescriptor()->bLength != 0)
if (!m_outPipe)
{
for (int i = 0; i != 15; ++i)
{
rc = outEndpoint->Open();
if (S_FAILED(rc))
return 6666;
IUSBEndpoint *outEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_OUT, i);
if (outEndpoint)
{
rc = outEndpoint->Open();
if (S_FAILED(rc))
return 62;
m_outPipe = outEndpoint;
m_outPipe = outEndpoint;
break;
}
}
}
}
@ -83,46 +124,24 @@ void Dualshock4Controller::CloseInterfaces()
Status Dualshock4Controller::GetInput()
{
return 9;
/*
uint8_t input_bytes[64];
Status rc = m_inPipe->Read(input_bytes, sizeof(input_bytes));
if (S_FAILED(rc))
return rc;
for (int i = 0; i != 64; ++i)
{
m_inputData[i] = input_bytes[i];
}
m_UpdateCalled = true;
uint8_t type = input_bytes[0];
if (type == XBONEINPUT_BUTTON) //Button data
if (type == 0x11) //Button data
{
m_buttonData = *reinterpret_cast<Dualshock4ButtonData *>(input_bytes);
}
else if (type == XBONEINPUT_GUIDEBUTTON) //Guide button status
{
m_buttonData.sync = input_bytes[4];
//Xbox one S needs to be sent an ack report for guide buttons
//TODO: needs testing
if (input_bytes[1] == 0x30)
{
rc = WriteAckGuideReport(input_bytes[2]);
if (S_FAILED(rc))
return rc;
}
//TODO: add ack check and send ack report!
}
return rc;
*/
}
Status Dualshock4Controller::SendInitBytes()
{
uint8_t init_bytes[]{
0x05,
0x20, 0x00, 0x01, 0x00};
Status rc = m_outPipe->Write(init_bytes, sizeof(init_bytes));
return rc;
}
@ -175,6 +194,41 @@ NormalizedButtonData Dualshock4Controller::GetNormalizedButtonData()
{
NormalizedButtonData normalData;
normalData.triggers[0] = NormalizeTrigger(m_buttonData.l2_pressure);
normalData.triggers[1] = NormalizeTrigger(m_buttonData.r2_pressure);
NormalizeAxis(m_buttonData.stick_left_x, m_buttonData.stick_left_y, _dualshock4ControllerConfig.leftStickDeadzonePercent,
&normalData.sticks[0].axis_x, &normalData.sticks[0].axis_y);
NormalizeAxis(m_buttonData.stick_right_x, m_buttonData.stick_right_y, _dualshock4ControllerConfig.rightStickDeadzonePercent,
&normalData.sticks[1].axis_x, &normalData.sticks[1].axis_y);
bool buttons[NUM_CONTROLLERBUTTONS] = {
m_buttonData.triangle,
m_buttonData.circle,
m_buttonData.cross,
m_buttonData.square,
m_buttonData.l3,
m_buttonData.r3,
m_buttonData.l1,
m_buttonData.r1,
m_buttonData.l2,
m_buttonData.r2,
m_buttonData.share,
m_buttonData.options,
m_buttonData.dpad & DS4_UP,
m_buttonData.dpad & DS4_RIGHT,
m_buttonData.dpad & DS4_DOWN,
m_buttonData.dpad & DS4_LEFT,
m_buttonData.touchpad_press,
m_buttonData.psbutton,
};
for (int i = 0; i != NUM_CONTROLLERBUTTONS; ++i)
{
ControllerButton button = _dualshock4ControllerConfig.buttons[i];
normalData.buttons[(button != NOT_SET ? button : i)] = buttons[i];
}
return normalData;
}

View File

@ -8,7 +8,7 @@
#include "SwitchAbstractedPadHandler.h"
#include "configFile.h"
#define APP_VERSION "0.4.2"
#define APP_VERSION "0.4.3"
struct VendorEvent
{
@ -30,6 +30,19 @@ Result QueryInterfaces(UsbHsInterface *interfaces, size_t interfaces_size, s32 *
return 1;
}
Result QueryVendorProduct(UsbHsInterface *interfaces, size_t interfaces_size, s32 *total_entries, uint16_t vendor_id, uint16_t product_id)
{
UsbHsInterfaceFilter filter;
filter.Flags = UsbHsInterfaceFilterFlags_idVendor | UsbHsInterfaceFilterFlags_idProduct;
filter.idVendor = vendor_id;
filter.idProduct = product_id;
Result rc = usbHsQueryAvailableInterfaces(&filter, interfaces, interfaces_size, total_entries);
if (R_SUCCEEDED(rc) && *total_entries != 0)
return 0;
else
return 1;
}
std::unique_ptr<IUSBDevice> devicePtr;
std::unique_ptr<IController> controllerPtr;
bool useAbstractedPad = hosversionBetween(5, 7);
@ -69,6 +82,7 @@ Result mainLoop()
Event catchAllEvent;
Event ds3Event;
Event ds4Event;
UTimer filecheckTimer;
Waiter filecheckTimerWaiter = waiterForUTimer(&filecheckTimer);
@ -98,6 +112,25 @@ Result mainLoop()
WriteToLog("Failed to open catch-all event");
else
WriteToLog("Successfully created catch-all event");
filter.Flags = UsbHsInterfaceFilterFlags_idVendor | UsbHsInterfaceFilterFlags_idProduct;
filter.idVendor = VENDOR_SONY;
filter.idProduct = PRODUCT_DUALSHOCK4_2X;
rc = usbHsCreateInterfaceAvailableEvent(&ds4Event, true, 2, &filter);
if (R_FAILED(rc))
WriteToLog("Failed to open event for Dualshock 4 2x");
else
WriteToLog("Successfully created event for Dualshock 4 2x");
/*
filter.Flags = UsbHsInterfaceFilterFlags_idVendor | UsbHsInterfaceFilterFlags_idProduct;
filter.idVendor = VENDOR_SONY;
filter.idProduct = PRODUCT_DUALSHOCK4_1X;
rc = usbHsCreateInterfaceAvailableEvent(&ds4Event, true, 2, &filter);
if (R_FAILED(rc))
WriteToLog("Failed to open event for Dualshock 4 1x");
else
WriteToLog("Successfully created event for Dualshock 4 1x");
*/
}
controllerInterfaces.reserve(10);
@ -109,8 +142,26 @@ Result mainLoop()
hidScanInput();
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
for (int i = 0; i != 8; ++i)
{
u64 kHeld = hidKeysDown(static_cast<HidControllerID>(i));
if (kHeld != 0)
WriteToLog("Player ", i + 1, ": ", kHeld);
}
if (kDown & KEY_B)
break;
for (auto &&handler : controllerInterfaces)
{
if (handler->GetController()->m_UpdateCalled)
{
for (int i = 0; i != 64; ++i)
printf("0x%02X ", handler->GetController()->m_inputData[i]);
printf("\n");
handler->GetController()->m_UpdateCalled = false;
}
}
#endif
rc = eventWait(&catchAllEvent, 0);
if (R_SUCCEEDED(rc))
@ -167,13 +218,27 @@ Result mainLoop()
UsbHsInterface interfaces[4];
s32 total_entries;
if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_HID, 0, 0)))
if (R_SUCCEEDED(QueryVendorProduct(interfaces, sizeof(interfaces), &total_entries, VENDOR_SONY, PRODUCT_DUALSHOCK3)))
{
WriteToLog("Registering DS3 controller");
devicePtr = std::make_unique<SwitchUSBDevice>(interfaces, total_entries);
controllerPtr = std::make_unique<Dualshock3Controller>(std::move(devicePtr));
}
}
rc = eventWait(&ds4Event, 0);
if (R_SUCCEEDED(rc))
{
WriteToLog("Dualshock 4 event went off");
UsbHsInterface interfaces[4];
s32 total_entries;
if (R_SUCCEEDED(QueryInterfaces(interfaces, sizeof(interfaces), &total_entries, USB_CLASS_HID, 0, 0)))
{
WriteToLog("Registering DS4 controller");
devicePtr = std::make_unique<SwitchUSBDevice>(interfaces, total_entries);
controllerPtr = std::make_unique<Dualshock4Controller>(std::move(devicePtr));
}
}
CallInitHandler();
//On interface change event, check if any devices were removed, and erase them from memory appropriately
@ -238,6 +303,7 @@ Result mainLoop()
WriteToLog("Destroying events");
usbHsDestroyInterfaceAvailableEvent(&ds3Event, 0);
usbHsDestroyInterfaceAvailableEvent(&catchAllEvent, 1);
usbHsDestroyInterfaceAvailableEvent(&ds4Event, 2);
//controllerInterfaces.clear();
return rc;