Improve pad support (#8800)

* Add support for another DS3 HID Report ID for Win7
* Add support for reading accel/gyro pad data over SCP
This commit is contained in:
SEt 2020-09-16 23:36:06 +03:00 committed by GitHub
parent 4c70864588
commit 9a6aac1662
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 3 deletions

View file

@ -96,7 +96,17 @@ bool ds3_pad_handler::Init()
#ifdef _WIN32 #ifdef _WIN32
u8 buf[0xFF]; u8 buf[0xFF];
buf[0] = 0xF2; buf[0] = 0xF2;
if (handle && (hid_get_feature_report(handle, buf, 0xFF) >= 0)) bool got_report = false;
if (handle)
{
got_report = hid_get_feature_report(handle, buf, 0xFF) >= 0;
if (!got_report)
{
buf[0] = 0;
got_report = hid_get_feature_report(handle, buf, 0xFF) >= 0;
}
}
if (got_report)
#else #else
if(handle) if(handle)
#endif #endif
@ -104,6 +114,9 @@ bool ds3_pad_handler::Init()
std::shared_ptr<ds3_device> ds3dev = std::make_shared<ds3_device>(); std::shared_ptr<ds3_device> ds3dev = std::make_shared<ds3_device>();
ds3dev->device = hid_info->path; ds3dev->device = hid_info->path;
ds3dev->handle = handle; ds3dev->handle = handle;
#ifdef _WIN32
ds3dev->report_id = buf[0];
#endif
controllers.emplace_back(ds3dev); controllers.emplace_back(ds3dev);
} }
else else
@ -286,7 +299,7 @@ ds3_pad_handler::DS3Status ds3_pad_handler::get_data(const std::shared_ptr<ds3_d
auto& dbuf = ds3dev->buf; auto& dbuf = ds3dev->buf;
#ifdef _WIN32 #ifdef _WIN32
dbuf[0] = 0xF2; dbuf[0] = ds3dev->report_id;
int result = hid_get_feature_report(ds3dev->handle, dbuf, sizeof(dbuf)); int result = hid_get_feature_report(ds3dev->handle, dbuf, sizeof(dbuf));
#else #else
int result = hid_read(ds3dev->handle, dbuf, sizeof(dbuf)); int result = hid_read(ds3dev->handle, dbuf, sizeof(dbuf));
@ -295,7 +308,7 @@ ds3_pad_handler::DS3Status ds3_pad_handler::get_data(const std::shared_ptr<ds3_d
if (result > 0) if (result > 0)
{ {
#ifdef _WIN32 #ifdef _WIN32
if(dbuf[0] == 0xF2) if (dbuf[0] == ds3dev->report_id)
#else #else
if (dbuf[0] == 0x01 && dbuf[1] != 0xFF) if (dbuf[0] == 0x01 && dbuf[1] != 0xFF)
#endif #endif

View file

@ -77,6 +77,9 @@ class ds3_pad_handler final : public PadHandlerBase
u8 large_motor = 0; u8 large_motor = 0;
u8 small_motor = 0; u8 small_motor = 0;
u8 status = DS3Status::Disconnected; u8 status = DS3Status::Disconnected;
#ifdef _WIN32
u8 report_id = 0;
#endif
}; };
const u16 DS3_VID = 0x054C; const u16 DS3_VID = 0x054C;

View file

@ -74,6 +74,7 @@ xinput_pad_handler::~xinput_pad_handler()
FreeLibrary(library); FreeLibrary(library);
library = nullptr; library = nullptr;
xinputGetExtended = nullptr; xinputGetExtended = nullptr;
xinputGetCustomData = nullptr;
xinputGetState = nullptr; xinputGetState = nullptr;
xinputSetState = nullptr; xinputSetState = nullptr;
xinputGetBatteryInformation = nullptr; xinputGetBatteryInformation = nullptr;
@ -303,6 +304,7 @@ bool xinput_pad_handler::Init()
if (library) if (library)
{ {
xinputGetExtended = reinterpret_cast<PFN_XINPUTGETEXTENDED>(GetProcAddress(library, "XInputGetExtended")); // Optional xinputGetExtended = reinterpret_cast<PFN_XINPUTGETEXTENDED>(GetProcAddress(library, "XInputGetExtended")); // Optional
xinputGetCustomData = reinterpret_cast<PFN_XINPUTGETCUSTOMDATA>(GetProcAddress(library, "XInputGetCustomData")); // Optional
xinputGetState = reinterpret_cast<PFN_XINPUTGETSTATE>(GetProcAddress(library, reinterpret_cast<LPCSTR>(100))); xinputGetState = reinterpret_cast<PFN_XINPUTGETSTATE>(GetProcAddress(library, reinterpret_cast<LPCSTR>(100)));
if (!xinputGetState) if (!xinputGetState)
xinputGetState = reinterpret_cast<PFN_XINPUTGETSTATE>(GetProcAddress(library, "XInputGetState")); xinputGetState = reinterpret_cast<PFN_XINPUTGETSTATE>(GetProcAddress(library, "XInputGetState"));
@ -319,6 +321,7 @@ bool xinput_pad_handler::Init()
FreeLibrary(library); FreeLibrary(library);
library = nullptr; library = nullptr;
xinputGetExtended = nullptr; xinputGetExtended = nullptr;
xinputGetCustomData = nullptr;
xinputGetState = nullptr; xinputGetState = nullptr;
xinputSetState = nullptr; xinputSetState = nullptr;
xinputGetBatteryInformation = nullptr; xinputGetBatteryInformation = nullptr;
@ -450,6 +453,18 @@ void xinput_pad_handler::get_extended_info(const std::shared_ptr<PadDevice>& dev
(*xinputGetBatteryInformation)(padnum, BATTERY_DEVTYPE_GAMEPAD, &battery_info); (*xinputGetBatteryInformation)(padnum, BATTERY_DEVTYPE_GAMEPAD, &battery_info);
pad->m_cable_state = battery_info.BatteryType == BATTERY_TYPE_WIRED ? 1 : 0; pad->m_cable_state = battery_info.BatteryType == BATTERY_TYPE_WIRED ? 1 : 0;
pad->m_battery_level = pad->m_cable_state ? BATTERY_LEVEL_FULL : battery_info.BatteryLevel; pad->m_battery_level = pad->m_cable_state ? BATTERY_LEVEL_FULL : battery_info.BatteryLevel;
if (xinputGetCustomData)
{
SCP_DS3_ACCEL sensors;
if (xinputGetCustomData(dev->deviceNumber, 0, &sensors) == ERROR_SUCCESS)
{
pad->m_sensors[0].m_value = sensors.SCP_ACCEL_X;
pad->m_sensors[1].m_value = sensors.SCP_ACCEL_Y;
pad->m_sensors[2].m_value = sensors.SCP_ACCEL_Z;
pad->m_sensors[3].m_value = sensors.SCP_GYRO;
}
}
} }
void xinput_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& device, const std::shared_ptr<Pad>& pad) void xinput_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& device, const std::shared_ptr<Pad>& pad)

View file

@ -40,6 +40,14 @@ struct SCP_EXTN
float SCP_PS; float SCP_PS;
}; };
struct SCP_DS3_ACCEL
{
unsigned short SCP_ACCEL_X;
unsigned short SCP_ACCEL_Z;
unsigned short SCP_ACCEL_Y;
unsigned short SCP_GYRO;
};
class xinput_pad_handler final : public PadHandlerBase class xinput_pad_handler final : public PadHandlerBase
{ {
// These are all the possible buttons on a standard xbox 360 or xbox one controller // These are all the possible buttons on a standard xbox 360 or xbox one controller
@ -103,6 +111,7 @@ public:
private: private:
typedef DWORD (WINAPI * PFN_XINPUTGETEXTENDED)(DWORD, SCP_EXTN *); typedef DWORD (WINAPI * PFN_XINPUTGETEXTENDED)(DWORD, SCP_EXTN *);
typedef DWORD (WINAPI * PFN_XINPUTGETCUSTOMDATA)(DWORD, DWORD, void *);
typedef DWORD (WINAPI * PFN_XINPUTGETSTATE)(DWORD, XINPUT_STATE *); typedef DWORD (WINAPI * PFN_XINPUTGETSTATE)(DWORD, XINPUT_STATE *);
typedef DWORD (WINAPI * PFN_XINPUTSETSTATE)(DWORD, XINPUT_VIBRATION *); typedef DWORD (WINAPI * PFN_XINPUTSETSTATE)(DWORD, XINPUT_VIBRATION *);
typedef DWORD (WINAPI * PFN_XINPUTGETBATTERYINFORMATION)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *); typedef DWORD (WINAPI * PFN_XINPUTGETBATTERYINFORMATION)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *);
@ -115,6 +124,7 @@ private:
bool is_init{ false }; bool is_init{ false };
HMODULE library{ nullptr }; HMODULE library{ nullptr };
PFN_XINPUTGETEXTENDED xinputGetExtended{ nullptr }; PFN_XINPUTGETEXTENDED xinputGetExtended{ nullptr };
PFN_XINPUTGETCUSTOMDATA xinputGetCustomData{ nullptr };
PFN_XINPUTGETSTATE xinputGetState{ nullptr }; PFN_XINPUTGETSTATE xinputGetState{ nullptr };
PFN_XINPUTSETSTATE xinputSetState{ nullptr }; PFN_XINPUTSETSTATE xinputSetState{ nullptr };
PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation{ nullptr }; PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation{ nullptr };