mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Windows: Make joystick autoconfigure work with DualSense / DualShock devices
This commit is contained in:
@@ -260,6 +260,7 @@ enum class SystemNotification {
|
||||
UI_STATE_CHANGED,
|
||||
AUDIO_MODE_CHANGED,
|
||||
APP_SWITCH_MODE_CHANGED,
|
||||
PAD_STATE_CHANGED,
|
||||
};
|
||||
|
||||
// I guess it's not super great architecturally to centralize this, since it's not general - but same with a lot of
|
||||
|
||||
+51
-10
@@ -839,25 +839,64 @@ bool HasBuiltinController(std::string_view name) {
|
||||
}
|
||||
|
||||
void NotifyPadConnected(InputDeviceID deviceId, std::string_view name) {
|
||||
std::lock_guard<std::recursive_mutex> guard(g_controllerMapLock);
|
||||
g_seenPads.insert(std::string(name));
|
||||
g_padNames[deviceId] = name;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(g_controllerMapLock);
|
||||
g_seenPads.insert(std::string(name));
|
||||
g_padNames[deviceId] = name;
|
||||
}
|
||||
System_Notify(SystemNotification::PAD_STATE_CHANGED);
|
||||
}
|
||||
|
||||
void NotifyPadDisconnected(InputDeviceID deviceId) {
|
||||
std::lock_guard<std::recursive_mutex> guard(g_controllerMapLock);
|
||||
auto iter = g_padNames.find(deviceId);
|
||||
if (iter != g_padNames.end()) {
|
||||
g_seenPads.erase(iter->second);
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(g_controllerMapLock);
|
||||
auto iter = g_padNames.find(deviceId);
|
||||
if (iter != g_padNames.end()) {
|
||||
g_seenPads.erase(iter->second);
|
||||
}
|
||||
g_padNames.erase(deviceId);
|
||||
}
|
||||
System_Notify(SystemNotification::PAD_STATE_CHANGED);
|
||||
}
|
||||
|
||||
void ClearControlsWithDeviceId(InputDeviceID deviceId) {
|
||||
bool modified = false;
|
||||
std::lock_guard<std::recursive_mutex> guard(g_controllerMapLock);
|
||||
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
|
||||
auto &mappings = iter->second;
|
||||
for (auto mapIter = mappings.begin(); mapIter != mappings.end(); ) {
|
||||
bool found = false;
|
||||
for (auto &mapping : mapIter->mappings) {
|
||||
if (mapping.deviceId == deviceId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
mapIter = mappings.erase(mapIter);
|
||||
modified = true;
|
||||
} else {
|
||||
++mapIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
g_controllerMapGeneration++;
|
||||
}
|
||||
g_padNames.erase(deviceId);
|
||||
}
|
||||
|
||||
void AutoConfForPad(std::string_view name) {
|
||||
std::lock_guard<std::recursive_mutex> guard(g_controllerMapLock);
|
||||
g_controllerMap.clear();
|
||||
|
||||
INFO_LOG(Log::System, "Autoconfiguring pad for '%.*s'", STR_VIEW(name));
|
||||
InputDeviceID deviceId = DEVICE_ID_PAD_0;
|
||||
for (auto [padDeviceId, padName] : g_padNames) {
|
||||
if (padName == name) {
|
||||
// Already configured.
|
||||
deviceId = padDeviceId;
|
||||
}
|
||||
}
|
||||
ClearControlsWithDeviceId(deviceId);
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
if (name.find("Xbox") != std::string::npos) {
|
||||
@@ -881,8 +920,10 @@ void AutoConfForPad(std::string_view name) {
|
||||
#endif
|
||||
|
||||
// Add a couple of convenient keyboard mappings by default, too.
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
g_controllerMap[VIRTKEY_PAUSE].push_back(MultiInputMapping(InputMapping(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE)));
|
||||
g_controllerMap[VIRTKEY_FASTFORWARD].push_back(MultiInputMapping(InputMapping(DEVICE_ID_KEYBOARD, NKCODE_TAB)));
|
||||
#endif
|
||||
g_controllerMapGeneration++;
|
||||
}
|
||||
|
||||
|
||||
+23
-11
@@ -15,6 +15,7 @@
|
||||
#include "Common/Common.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/System/OSD.h"
|
||||
#include "Core/KeyMap.h"
|
||||
|
||||
constexpr u8 LED_R = 0x05;
|
||||
constexpr u8 LED_G = 0x10;
|
||||
@@ -184,16 +185,14 @@ static const HIDControllerInfo g_psInfos[] = {
|
||||
// {PSSubType::DS5, DUALSENSE_EDGE_WIRELESS},
|
||||
};
|
||||
|
||||
static bool IsSupportedGamepad(HANDLE handle, USHORT *pidOut, HIDControllerType *subType) {
|
||||
static const HIDControllerInfo *GetGamepadInfo(HANDLE handle) {
|
||||
HIDD_ATTRIBUTES attr{sizeof(HIDD_ATTRIBUTES)};
|
||||
if (!HidD_GetAttributes(handle, &attr)) {
|
||||
return false;
|
||||
}
|
||||
for (const auto &info : g_psInfos) {
|
||||
if (attr.VendorID == info.vendorId && attr.ProductID == info.productId) {
|
||||
*pidOut = attr.ProductID;
|
||||
*subType = info.type;
|
||||
return true;
|
||||
return &info;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -279,6 +278,10 @@ static bool ShutdownDualsense(HANDLE handle, int outReportSize) {
|
||||
return WriteReport(handle, report);
|
||||
}
|
||||
|
||||
static bool InitializeSwitchPro(HANDLE handle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class DS4FeatureBits : u8 {
|
||||
VOL_L = 0x10,
|
||||
VOL_R = 0x20,
|
||||
@@ -350,7 +353,7 @@ static bool ShutdownDualShock(HANDLE handle, int outReportSize) {
|
||||
return WriteReport(handle, report);
|
||||
}
|
||||
|
||||
HANDLE OpenFirstHIDController(HIDControllerType *subType, int *reportSize, int *outReportSize) {
|
||||
static HANDLE OpenFirstHIDController(HIDControllerType *subType, int *reportSize, int *outReportSize, const HIDControllerInfo **outInfo) {
|
||||
GUID hidGuid;
|
||||
HidD_GetHidGuid(&hidGuid);
|
||||
|
||||
@@ -373,9 +376,11 @@ HANDLE OpenFirstHIDController(HIDControllerType *subType, int *reportSize, int *
|
||||
HANDLE handle = CreateFile(detailData->DevicePath, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
USHORT pid;
|
||||
if (IsSupportedGamepad(handle, &pid, subType)) {
|
||||
INFO_LOG(Log::UI, "Found supported gamepad. PID: %04x", pid);
|
||||
const HIDControllerInfo *info = GetGamepadInfo(handle);
|
||||
*outInfo = info;
|
||||
if (info) {
|
||||
*subType = info->type;
|
||||
INFO_LOG(Log::UI, "Found supported gamepad. PID: %04x", info->productId);
|
||||
HIDP_CAPS caps;
|
||||
PHIDP_PREPARSED_DATA preparsedData;
|
||||
|
||||
@@ -396,7 +401,7 @@ HANDLE OpenFirstHIDController(HIDControllerType *subType, int *reportSize, int *
|
||||
result = InitializeDualShock(handle, *outReportSize);
|
||||
break;
|
||||
case HIDControllerType::SwitchPro:
|
||||
result = true; // InitializeSwitchPro(handle, *outReportSize);
|
||||
result = InitializeSwitchPro(handle);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -677,13 +682,20 @@ InputDeviceID HidInputDevice::DeviceID(int pad) {
|
||||
}
|
||||
|
||||
int HidInputDevice::UpdateState() {
|
||||
const InputDeviceID deviceID = DeviceID(pad_);
|
||||
|
||||
if (!controller_) {
|
||||
// Poll for controllers from time to time.
|
||||
if (pollCount_ == 0) {
|
||||
pollCount_ = POLL_FREQ;
|
||||
HANDLE newController = OpenFirstHIDController(&subType_, &reportSize_, &outReportSize_);
|
||||
const HIDControllerInfo *info{};
|
||||
HANDLE newController = OpenFirstHIDController(&subType_, &reportSize_, &outReportSize_, &info);
|
||||
if (newController) {
|
||||
controller_ = newController;
|
||||
if (info) {
|
||||
name_ = info->name;
|
||||
}
|
||||
KeyMap::NotifyPadConnected(deviceID, name_);
|
||||
}
|
||||
} else {
|
||||
pollCount_--;
|
||||
@@ -706,7 +718,6 @@ int HidInputDevice::UpdateState() {
|
||||
}
|
||||
|
||||
if (result) {
|
||||
const InputDeviceID deviceID = DeviceID(pad_);
|
||||
// Process the input and generate input events.
|
||||
const u32 downMask = state.buttons & (~prevState_.buttons);
|
||||
const u32 upMask = (~state.buttons) & prevState_.buttons;
|
||||
@@ -757,6 +768,7 @@ int HidInputDevice::UpdateState() {
|
||||
return UPDATESTATE_NO_SLEEP; // The ReadFile sleeps for us, effectively.
|
||||
} else {
|
||||
// might have been disconnected. retry later.
|
||||
KeyMap::NotifyPadDisconnected(deviceID);
|
||||
ReleaseAllKeys(buttonMappings, buttonMappingsSize);
|
||||
CloseHandle(controller_);
|
||||
controller_ = NULL;
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
|
||||
HIDControllerType subType_{};
|
||||
HANDLE controller_;
|
||||
std::string name_;
|
||||
int pad_ = 0;
|
||||
int pollCount_ = 0;
|
||||
int reportSize_ = 0;
|
||||
|
||||
Reference in New Issue
Block a user