Signed-off-by: Andrew Eikum aeikum@codeweavers.com --- dlls/xinput1_3/hid.c | 239 ++++++++++++++++---------------- dlls/xinput1_3/xinput_main.c | 95 ++++++++++++- dlls/xinput1_3/xinput_private.h | 7 +- 3 files changed, 210 insertions(+), 131 deletions(-)
diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c index 38c93beb80f..477d5304cac 100644 --- a/dlls/xinput1_3/hid.c +++ b/dlls/xinput1_3/hid.c @@ -47,15 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(xinput);
#define XINPUT_GAMEPAD_GUIDE 0x0400
-static CRITICAL_SECTION hid_xinput_crit; -static CRITICAL_SECTION_DEBUG hid_critsect_debug = -{ - 0, 0, &hid_xinput_crit, - { &hid_critsect_debug.ProcessLocksList, &hid_critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": hid_xinput_crit") } -}; -static CRITICAL_SECTION hid_xinput_crit = { &hid_critsect_debug, -1, 0, 0, 0, 0 }; - struct axis_info { LONG min; @@ -69,8 +60,6 @@ struct hid_platform_private { WCHAR *device_path; BOOL enabled;
- CRITICAL_SECTION crit; - DWORD report_length; BYTE current_report; CHAR *reports[2]; @@ -195,9 +184,6 @@ static void build_private(struct hid_platform_private *private, PHIDP_PREPARSED_ private->device_path = HeapAlloc(GetProcessHeap(), 0, size); memcpy(private->device_path, path, size); private->enabled = TRUE; - - InitializeCriticalSection(&private->crit); - private->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit"); }
void HID_find_gamepads(xinput_controller *devices) @@ -208,20 +194,26 @@ void HID_find_gamepads(xinput_controller *devices) SP_DEVICE_INTERFACE_DETAIL_DATA_W *data; PHIDP_PREPARSED_DATA ppd; DWORD detail_size = MAX_PATH * sizeof(WCHAR); - HANDLE device = INVALID_HANDLE_VALUE; + HANDLE device; HIDP_CAPS Caps; - DWORD idx,didx; - int i; + DWORD idx; + int i, open_device_idx;
idx = GetTickCount(); if ((idx - last_check) < 2000) return; + + EnterCriticalSection(&xinput_crit); + + if ((idx - last_check) < 2000) + { + LeaveCriticalSection(&xinput_crit); + return; + } last_check = idx;
HidD_GetHidGuid(&hid_guid);
- EnterCriticalSection(&hid_xinput_crit); - device_info_set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
data = HeapAlloc(GetProcessHeap(), 0 , sizeof(*data) + detail_size); @@ -230,9 +222,9 @@ void HID_find_gamepads(xinput_controller *devices) ZeroMemory(&interface_data, sizeof(interface_data)); interface_data.cbSize = sizeof(interface_data);
- idx = didx = 0; + idx = 0; while (SetupDiEnumDeviceInterfaces(device_info_set, NULL, &hid_guid, idx++, - &interface_data) && didx < XUSER_MAX_COUNT) + &interface_data)) { static const WCHAR ig[] = {'I','G','_',0}; if (!SetupDiGetDeviceInterfaceDetailW(device_info_set, @@ -242,14 +234,24 @@ void HID_find_gamepads(xinput_controller *devices) if (!wcsstr(data->DevicePath, ig)) continue;
+ open_device_idx = -1; for (i = 0; i < XUSER_MAX_COUNT; i++) { struct hid_platform_private *private = devices[i].platform_private; - if (devices[i].connected && !wcscmp(data->DevicePath, private->device_path)) - break; + if (devices[i].connected) + { + if (!wcscmp(data->DevicePath, private->device_path)) + break; + } + else if(open_device_idx < 0) + open_device_idx = i; } if (i != XUSER_MAX_COUNT) + /* this device is already opened */ continue; + if (open_device_idx < 0) + /* no open device slots */ + break; device = CreateFileW(data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); if (device == INVALID_HANDLE_VALUE) continue; @@ -262,13 +264,12 @@ void HID_find_gamepads(xinput_controller *devices) Caps.Usage == 0x8 /* Multi-axis Controller */)) { struct hid_platform_private *private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct hid_platform_private)); - if (VerifyGamepad(ppd, &(devices[didx].caps), private, &Caps)) + if (VerifyGamepad(ppd, &devices[open_device_idx].caps, private, &Caps)) { - TRACE("Found gamepad %i %s\n",didx, debugstr_w(data->DevicePath)); - devices[didx].connected = TRUE; + TRACE("Found gamepad %i %s\n", open_device_idx, debugstr_w(data->DevicePath)); build_private(private, ppd, &Caps, device, data->DevicePath); - devices[didx].platform_private = private; - didx++; + devices[open_device_idx].platform_private = private; + devices[open_device_idx].connected = TRUE; } else { @@ -282,41 +283,39 @@ void HID_find_gamepads(xinput_controller *devices) CloseHandle(device); HidD_FreePreparsedData(ppd); } - device = INVALID_HANDLE_VALUE; } HeapFree(GetProcessHeap(), 0, data); SetupDiDestroyDeviceInfoList(device_info_set); - LeaveCriticalSection(&hid_xinput_crit); - return; + LeaveCriticalSection(&xinput_crit); }
static void remove_gamepad(xinput_controller *device) { + EnterCriticalSection(&device->crit); + if (device->connected) { struct hid_platform_private *private = device->platform_private;
- EnterCriticalSection(&private->crit); + device->connected = FALSE; + CloseHandle(private->device); HeapFree(GetProcessHeap(), 0, private->reports[0]); HeapFree(GetProcessHeap(), 0, private->reports[1]); HeapFree(GetProcessHeap(), 0, private->device_path); HidD_FreePreparsedData(private->ppd); device->platform_private = NULL; - device->connected = FALSE; - LeaveCriticalSection(&private->crit); - DeleteCriticalSection(&private->crit); HeapFree(GetProcessHeap(), 0, private); } + + LeaveCriticalSection(&device->crit); }
void HID_destroy_gamepads(xinput_controller *devices) { int i; - EnterCriticalSection(&hid_xinput_crit); for (i = 0; i < XUSER_MAX_COUNT; i++) remove_gamepad(&devices[i]); - LeaveCriticalSection(&hid_xinput_crit); }
static SHORT scale_short(LONG value, const struct axis_info *axis) @@ -329,7 +328,7 @@ static BYTE scale_byte(LONG value, const struct axis_info *axis) return (((ULONGLONG)(value - axis->min)) * 0xff) / axis->range; }
-void HID_update_state(xinput_controller* device) +void HID_update_state(xinput_controller *device, XINPUT_STATE *state) { struct hid_platform_private *private = device->platform_private; int i; @@ -343,107 +342,107 @@ void HID_update_state(xinput_controller* device) if (!private->enabled) return;
- EnterCriticalSection(&private->crit); if (!HidD_GetInputReport(private->device, target_report, private->report_length)) { if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_HANDLE) + { + EnterCriticalSection(&xinput_crit); remove_gamepad(device); + LeaveCriticalSection(&xinput_crit); + } else ERR("Failed to get Input Report (%x)\n", GetLastError()); - LeaveCriticalSection(&private->crit); return; } - if (memcmp(report, target_report, private->report_length) == 0) + if (memcmp(report, target_report, private->report_length) != 0) { - LeaveCriticalSection(&private->crit); - return; - } - - private->current_report = (private->current_report+1)%2; + private->current_report = (private->current_report+1)%2;
- device->state.dwPacketNumber++; - button_length = ARRAY_SIZE(buttons); - HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, buttons, &button_length, private->ppd, target_report, private->report_length); + device->state.dwPacketNumber++; + button_length = ARRAY_SIZE(buttons); + HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, buttons, &button_length, private->ppd, target_report, private->report_length);
- device->state.Gamepad.wButtons = 0; - for (i = 0; i < button_length; i++) - { - switch (buttons[i]) + device->state.Gamepad.wButtons = 0; + for (i = 0; i < button_length; i++) { - case 1: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break; - case 2: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break; - case 3: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break; - case 4: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break; - case 5: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break; - case 6: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break; - case 7: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break; - case 8: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break; - case 9: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break; - case 10: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break; - case 11: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break; + switch (buttons[i]) + { + case 1: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break; + case 2: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break; + case 3: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break; + case 4: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break; + case 5: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break; + case 6: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break; + case 7: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break; + case 8: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break; + case 9: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break; + case 10: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break; + case 11: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break; + } } - }
- if(HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, &hat_value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - { - switch(hat_value){ - /* 8 1 2 - * 7 0 3 - * 6 5 4 */ - case 0: - break; - case 1: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; - break; - case 2: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_RIGHT; - break; - case 3: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; - break; - case 4: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_DPAD_DOWN; - break; - case 5: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; - break; - case 6: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT; - break; - case 7: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; - break; - case 8: - device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP; - break; + if(HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, &hat_value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + { + switch(hat_value){ + /* 8 1 2 + * 7 0 3 + * 6 5 4 */ + case 0: + break; + case 1: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; + break; + case 2: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_RIGHT; + break; + case 3: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; + break; + case 4: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_DPAD_DOWN; + break; + case 5: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; + break; + case 6: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT; + break; + case 7: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; + break; + case 8: + device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP; + break; + } } - }
- if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - device->state.Gamepad.sThumbLX = scale_short(value, &private->lx); + if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + device->state.Gamepad.sThumbLX = scale_short(value, &private->lx);
- if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - device->state.Gamepad.sThumbLY = -scale_short(value, &private->ly) - 1; + if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + device->state.Gamepad.sThumbLY = -scale_short(value, &private->ly) - 1;
- if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - device->state.Gamepad.sThumbRX = scale_short(value, &private->rx); + if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + device->state.Gamepad.sThumbRX = scale_short(value, &private->rx);
- if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - device->state.Gamepad.sThumbRY = -scale_short(value, &private->ry) - 1; + if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + device->state.Gamepad.sThumbRY = -scale_short(value, &private->ry) - 1;
- if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - device->state.Gamepad.bRightTrigger = scale_byte(value, &private->rtrigger); + if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + device->state.Gamepad.bRightTrigger = scale_byte(value, &private->rtrigger); + + if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value, + private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) + device->state.Gamepad.bLeftTrigger = scale_byte(value, &private->ltrigger); + }
- if(HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value, - private->ppd, target_report, private->report_length) == HIDP_STATUS_SUCCESS) - device->state.Gamepad.bLeftTrigger = scale_byte(value, &private->ltrigger); - LeaveCriticalSection(&private->crit); + memcpy(state, &device->state, sizeof(*state)); }
DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) @@ -474,9 +473,7 @@ DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) report.right = (BYTE)(state->wRightMotorSpeed / 256); memset(&report.pad2, 0, sizeof(report.pad2));
- EnterCriticalSection(&private->crit); rc = HidD_SetOutputReport(private->device, &report, sizeof(report)); - LeaveCriticalSection(&private->crit); if (rc) return ERROR_SUCCESS; return GetLastError(); @@ -492,7 +489,6 @@ void HID_enable(xinput_controller* device, BOOL enable)
if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED) { - EnterCriticalSection(&private->crit); if (private->enabled && !enable) { XINPUT_VIBRATION state; @@ -504,7 +500,6 @@ void HID_enable(xinput_controller* device, BOOL enable) { HID_set_state(device, &device->vibration); } - LeaveCriticalSection(&private->crit); }
private->enabled = enable; diff --git a/dlls/xinput1_3/xinput_main.c b/dlls/xinput1_3/xinput_main.c index a417fec7ad1..5c83e87fb13 100644 --- a/dlls/xinput1_3/xinput_main.c +++ b/dlls/xinput1_3/xinput_main.c @@ -34,7 +34,66 @@
WINE_DEFAULT_DEBUG_CHANNEL(xinput);
-xinput_controller controllers[XUSER_MAX_COUNT]; +/* xinput_crit guards controllers array */ +static CRITICAL_SECTION_DEBUG xinput_critsect_debug = +{ + 0, 0, &xinput_crit, + { &xinput_critsect_debug.ProcessLocksList, &xinput_critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": xinput_crit") } +}; +CRITICAL_SECTION xinput_crit = { &xinput_critsect_debug, -1, 0, 0, 0, 0 }; + +static CRITICAL_SECTION_DEBUG controller_critsect_debug[XUSER_MAX_COUNT] = +{ + { + 0, 0, &controllers[0].crit, + { &controller_critsect_debug[0].ProcessLocksList, &controller_critsect_debug[0].ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[0].crit") } + }, + { + 0, 0, &controllers[1].crit, + { &controller_critsect_debug[1].ProcessLocksList, &controller_critsect_debug[1].ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[1].crit") } + }, + { + 0, 0, &controllers[2].crit, + { &controller_critsect_debug[2].ProcessLocksList, &controller_critsect_debug[2].ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[2].crit") } + }, + { + 0, 0, &controllers[3].crit, + { &controller_critsect_debug[3].ProcessLocksList, &controller_critsect_debug[3].ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[3].crit") } + }, +}; + +xinput_controller controllers[XUSER_MAX_COUNT] = { + {{ &controller_critsect_debug[0], -1, 0, 0, 0, 0 }}, + {{ &controller_critsect_debug[1], -1, 0, 0, 0, 0 }}, + {{ &controller_critsect_debug[2], -1, 0, 0, 0, 0 }}, + {{ &controller_critsect_debug[3], -1, 0, 0, 0, 0 }}, +}; + +static BOOL verify_and_lock_device(xinput_controller *device) +{ + if (!device->connected) + return FALSE; + + EnterCriticalSection(&device->crit); + + if (!device->connected) + { + LeaveCriticalSection(&device->crit); + return FALSE; + } + + return TRUE; +} + +static void unlock_device(xinput_controller *device) +{ + LeaveCriticalSection(&device->crit); +}
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { @@ -65,23 +124,30 @@ void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
for (index = 0; index < XUSER_MAX_COUNT; index ++) { - if (!controllers[index].connected) continue; + if (!verify_and_lock_device(&controllers[index])) continue; HID_enable(&controllers[index], enable); + unlock_device(&controllers[index]); } }
DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION* vibration) { + DWORD ret; + TRACE("(index %u, vibration %p)\n", index, vibration);
HID_find_gamepads(controllers);
if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; - if (!controllers[index].connected) + if (!verify_and_lock_device(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED;
- return HID_set_state(&controllers[index], vibration); + ret = HID_set_state(&controllers[index], vibration); + + unlock_device(&controllers[index]); + + return ret; }
/* Some versions of SteamOverlayRenderer hot-patch XInputGetStateEx() and call @@ -95,11 +161,19 @@ static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; + if (!verify_and_lock_device(&controllers[index])) + return ERROR_DEVICE_NOT_CONNECTED; + + HID_update_state(&controllers[index], state); + if (!controllers[index].connected) + { + /* update_state may have disconnected the controller */ + unlock_device(&controllers[index]); return ERROR_DEVICE_NOT_CONNECTED; + }
- HID_update_state(&controllers[index]); - memcpy(state, &controllers[index].state, sizeof(XINPUT_STATE)); + unlock_device(&controllers[index]);
return ERROR_SUCCESS; } @@ -151,13 +225,20 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, X
if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; - if (!controllers[index].connected) + + if (!verify_and_lock_device(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED; + if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD) + { + unlock_device(&controllers[index]); return ERROR_DEVICE_NOT_CONNECTED; + }
memcpy(capabilities, &controllers[index].caps, sizeof(*capabilities));
+ unlock_device(&controllers[index]); + return ERROR_SUCCESS; }
diff --git a/dlls/xinput1_3/xinput_private.h b/dlls/xinput1_3/xinput_private.h index d6e0e9614ee..74cf318a6fb 100644 --- a/dlls/xinput1_3/xinput_private.h +++ b/dlls/xinput1_3/xinput_private.h @@ -19,16 +19,19 @@
typedef struct _xinput_controller { - BOOL connected; + CRITICAL_SECTION crit; + BOOL connected; /* only TRUE when device is valid; may be used without holding crit */ XINPUT_CAPABILITIES caps; void *platform_private; XINPUT_STATE state; XINPUT_VIBRATION vibration; } xinput_controller;
+CRITICAL_SECTION xinput_crit; +xinput_controller controllers[XUSER_MAX_COUNT];
void HID_find_gamepads(xinput_controller *devices) DECLSPEC_HIDDEN; void HID_destroy_gamepads(xinput_controller *devices) DECLSPEC_HIDDEN; -void HID_update_state(xinput_controller* device) DECLSPEC_HIDDEN; +void HID_update_state(xinput_controller* device, XINPUT_STATE *state) DECLSPEC_HIDDEN; DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) DECLSPEC_HIDDEN; void HID_enable(xinput_controller* device, BOOL enable) DECLSPEC_HIDDEN;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=58240
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/xinput1_3/hid.c:47 error: patch failed: dlls/xinput1_3/xinput_main.c:34 error: patch failed: dlls/xinput1_3/xinput_private.h:19 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/xinput1_3/hid.c:47 error: patch failed: dlls/xinput1_3/xinput_main.c:34 error: patch failed: dlls/xinput1_3/xinput_private.h:19 Task: Patch failed to apply
On Tue, 22 Oct 2019, Marvin wrote: [...]
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=58240
[...]
=== debian10 (build log) ===
error: patch failed: dlls/xinput1_3/hid.c:47 error: patch failed: dlls/xinput1_3/xinput_main.c:34 error: patch failed: dlls/xinput1_3/xinput_private.h:19 Task: Patch failed to apply
In case anyone is wondering what happened here, the reason why it did not apply is that by the time the TestBot got around to running this job this patchset had been committed and pushed:
* 15:00:26 -0500 Alexandre receives the patch (based on AuthorDate) * 15:05:09 -0500 The TestBot receives the patch * 16:04:27 -0500 Alexandre commits the patch * 16:59:53 -0500? Alexandre pushes the commits to winehq * 18:07:20 -0500 The TestBot updates its Wine source * 19:27:58 -0500 The TestBot tries to apply the patch on top of the new Wine source
So why did it take so long for the TestBot to start testing this patch?
At the time it was busy testing the kernel32 patch series where 8 patches required a long compilation (rougly 14 minutes for each of the 3 builds, the joys of modify global headers).