mirror of
https://github.com/cathery/sys-con.git
synced 2024-10-04 21:39:43 +00:00
Begin implementing Dualshock 4 controller
This commit is contained in:
parent
45321fa29d
commit
8d61e5b10b
@ -36,7 +36,8 @@ enum ProductIDs
|
|||||||
PRODUCT_XBOXADAPTIVE = 0xb0a,
|
PRODUCT_XBOXADAPTIVE = 0xb0a,
|
||||||
|
|
||||||
PRODUCT_DUALSHOCK3 = 0x268,
|
PRODUCT_DUALSHOCK3 = 0x268,
|
||||||
PRODUCT_DUALSHOCK4 = 0x5c4,
|
PRODUCT_DUALSHOCK4_1X = 0x5c4,
|
||||||
|
PRODUCT_DUALSHOCK4_2X = 0x9cc,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ControllerSupport
|
enum ControllerSupport
|
||||||
|
@ -7,40 +7,68 @@
|
|||||||
|
|
||||||
struct Dualshock4ButtonData
|
struct Dualshock4ButtonData
|
||||||
{
|
{
|
||||||
uint8_t type;
|
uint8_t padding0[2];
|
||||||
uint8_t length;
|
|
||||||
|
|
||||||
bool dpad_up : 1;
|
uint8_t stick_left_x;
|
||||||
bool dpad_down : 1;
|
uint8_t stick_left_y;
|
||||||
bool dpad_left : 1;
|
uint8_t stick_right_x;
|
||||||
bool dpad_right : 1;
|
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;
|
uint8_t padding3[2];
|
||||||
bool back : 1;
|
|
||||||
bool stick_left_click : 1;
|
|
||||||
bool stick_right_click : 1;
|
|
||||||
|
|
||||||
bool bumper_left : 1;
|
uint8_t touches_count;
|
||||||
bool bumper_right : 1;
|
uint8_t touch_data_timestamp;
|
||||||
bool guide : 1;
|
uint8_t touch0_id : 7;
|
||||||
bool dummy1 : 1; // Always 0.
|
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;
|
uint8_t padding4[2];
|
||||||
bool b : 1;
|
uint32_t crc32;
|
||||||
bool x : 1;
|
};
|
||||||
bool y : 1;
|
|
||||||
|
|
||||||
uint8_t trigger_left;
|
enum Dualshock4Dpad
|
||||||
uint8_t trigger_right;
|
{
|
||||||
|
DS4_UP = 0x000,
|
||||||
int16_t stick_left_x;
|
DS4_UPRIGHT = 0x001,
|
||||||
int16_t stick_left_y;
|
DS4_RIGHT = 0x010,
|
||||||
int16_t stick_right_x;
|
DS4_DOWNRIGHT = 0x011,
|
||||||
int16_t stick_right_y;
|
DS4_DOWN = 0x100,
|
||||||
|
DS4_DOWNLEFT = 0x101,
|
||||||
// Always 0.
|
DS4_LEFT = 0x110,
|
||||||
uint32_t dummy2;
|
DS4_UPLEFT = 0x111,
|
||||||
uint16_t dummy3;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dualshock4Controller : public IController
|
class Dualshock4Controller : public IController
|
||||||
|
@ -17,6 +17,9 @@ protected:
|
|||||||
std::unique_ptr<IUSBDevice> m_device;
|
std::unique_ptr<IUSBDevice> m_device;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
uint8_t m_inputData[100];
|
||||||
|
bool m_UpdateCalled;
|
||||||
|
|
||||||
IController(std::unique_ptr<IUSBDevice> &&interface) : m_device(std::move(interface)) {}
|
IController(std::unique_ptr<IUSBDevice> &&interface) : m_device(std::move(interface)) {}
|
||||||
virtual ~IController() = default;
|
virtual ~IController() = default;
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
static ControllerConfig _dualshock4ControllerConfig{};
|
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)
|
Dualshock4Controller::Dualshock4Controller(std::unique_ptr<IUSBDevice> &&interface)
|
||||||
: IController(std::move(interface))
|
: IController(std::move(interface))
|
||||||
{
|
{
|
||||||
@ -12,6 +16,26 @@ Dualshock4Controller::~Dualshock4Controller()
|
|||||||
{
|
{
|
||||||
Exit();
|
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()
|
Status Dualshock4Controller::Initialize()
|
||||||
{
|
{
|
||||||
@ -45,27 +69,44 @@ Status Dualshock4Controller::OpenInterfaces()
|
|||||||
rc = interface->Open();
|
rc = interface->Open();
|
||||||
if (S_FAILED(rc))
|
if (S_FAILED(rc))
|
||||||
return 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);
|
for (int i = 0; i != 15; ++i)
|
||||||
if (inEndpoint->GetDescriptor()->bLength != 0)
|
|
||||||
{
|
{
|
||||||
rc = inEndpoint->Open();
|
IUSBEndpoint *inEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_IN, i);
|
||||||
if (S_FAILED(rc))
|
if (inEndpoint)
|
||||||
return 5555;
|
{
|
||||||
|
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 (!m_outPipe)
|
||||||
if (outEndpoint->GetDescriptor()->bLength != 0)
|
{
|
||||||
|
for (int i = 0; i != 15; ++i)
|
||||||
{
|
{
|
||||||
rc = outEndpoint->Open();
|
IUSBEndpoint *outEndpoint = interface->GetEndpoint(IUSBEndpoint::USB_ENDPOINT_OUT, i);
|
||||||
if (S_FAILED(rc))
|
if (outEndpoint)
|
||||||
return 6666;
|
{
|
||||||
|
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()
|
Status Dualshock4Controller::GetInput()
|
||||||
{
|
{
|
||||||
return 9;
|
|
||||||
/*
|
|
||||||
uint8_t input_bytes[64];
|
uint8_t input_bytes[64];
|
||||||
|
|
||||||
Status rc = m_inPipe->Read(input_bytes, sizeof(input_bytes));
|
Status rc = m_inPipe->Read(input_bytes, sizeof(input_bytes));
|
||||||
if (S_FAILED(rc))
|
if (S_FAILED(rc))
|
||||||
return 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];
|
uint8_t type = input_bytes[0];
|
||||||
|
|
||||||
if (type == XBONEINPUT_BUTTON) //Button data
|
if (type == 0x11) //Button data
|
||||||
{
|
{
|
||||||
m_buttonData = *reinterpret_cast<Dualshock4ButtonData *>(input_bytes);
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +194,41 @@ NormalizedButtonData Dualshock4Controller::GetNormalizedButtonData()
|
|||||||
{
|
{
|
||||||
NormalizedButtonData normalData;
|
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;
|
return normalData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "SwitchAbstractedPadHandler.h"
|
#include "SwitchAbstractedPadHandler.h"
|
||||||
#include "configFile.h"
|
#include "configFile.h"
|
||||||
|
|
||||||
#define APP_VERSION "0.4.2"
|
#define APP_VERSION "0.4.3"
|
||||||
|
|
||||||
struct VendorEvent
|
struct VendorEvent
|
||||||
{
|
{
|
||||||
@ -30,6 +30,19 @@ Result QueryInterfaces(UsbHsInterface *interfaces, size_t interfaces_size, s32 *
|
|||||||
return 1;
|
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<IUSBDevice> devicePtr;
|
||||||
std::unique_ptr<IController> controllerPtr;
|
std::unique_ptr<IController> controllerPtr;
|
||||||
bool useAbstractedPad = hosversionBetween(5, 7);
|
bool useAbstractedPad = hosversionBetween(5, 7);
|
||||||
@ -69,6 +82,7 @@ Result mainLoop()
|
|||||||
|
|
||||||
Event catchAllEvent;
|
Event catchAllEvent;
|
||||||
Event ds3Event;
|
Event ds3Event;
|
||||||
|
Event ds4Event;
|
||||||
|
|
||||||
UTimer filecheckTimer;
|
UTimer filecheckTimer;
|
||||||
Waiter filecheckTimerWaiter = waiterForUTimer(&filecheckTimer);
|
Waiter filecheckTimerWaiter = waiterForUTimer(&filecheckTimer);
|
||||||
@ -98,6 +112,25 @@ Result mainLoop()
|
|||||||
WriteToLog("Failed to open catch-all event");
|
WriteToLog("Failed to open catch-all event");
|
||||||
else
|
else
|
||||||
WriteToLog("Successfully created catch-all event");
|
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);
|
controllerInterfaces.reserve(10);
|
||||||
@ -109,8 +142,26 @@ Result mainLoop()
|
|||||||
hidScanInput();
|
hidScanInput();
|
||||||
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
|
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)
|
if (kDown & KEY_B)
|
||||||
break;
|
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
|
#endif
|
||||||
rc = eventWait(&catchAllEvent, 0);
|
rc = eventWait(&catchAllEvent, 0);
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
@ -167,13 +218,27 @@ Result mainLoop()
|
|||||||
UsbHsInterface interfaces[4];
|
UsbHsInterface interfaces[4];
|
||||||
s32 total_entries;
|
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");
|
WriteToLog("Registering DS3 controller");
|
||||||
devicePtr = std::make_unique<SwitchUSBDevice>(interfaces, total_entries);
|
devicePtr = std::make_unique<SwitchUSBDevice>(interfaces, total_entries);
|
||||||
controllerPtr = std::make_unique<Dualshock3Controller>(std::move(devicePtr));
|
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();
|
CallInitHandler();
|
||||||
|
|
||||||
//On interface change event, check if any devices were removed, and erase them from memory appropriately
|
//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");
|
WriteToLog("Destroying events");
|
||||||
usbHsDestroyInterfaceAvailableEvent(&ds3Event, 0);
|
usbHsDestroyInterfaceAvailableEvent(&ds3Event, 0);
|
||||||
usbHsDestroyInterfaceAvailableEvent(&catchAllEvent, 1);
|
usbHsDestroyInterfaceAvailableEvent(&catchAllEvent, 1);
|
||||||
|
usbHsDestroyInterfaceAvailableEvent(&ds4Event, 2);
|
||||||
|
|
||||||
//controllerInterfaces.clear();
|
//controllerInterfaces.clear();
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user