Avoid a crash when changing the device type at runtime in the input gui

This commit is contained in:
ergo720 2021-02-08 15:00:09 +01:00
parent f750b2e4f2
commit cd362b6383
3 changed files with 44 additions and 28 deletions

View File

@ -206,6 +206,19 @@ void InputDeviceManager::UpdateDevices(int port, bool ack)
dev->SetPort(usb_port, false);
}
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
if (type != to_underlying(g_XboxControllerHostBridge[port].XboxType)) {
// this will happen when the user changes the type of an existing xbox device type connected to a port
if (g_XboxControllerHostBridge[port].bPendingRemoval == false) {
g_XboxControllerHostBridge[port].bPendingRemoval = true;
return;
}
else {
DestructHleInputDevice(port);
if (!ConstructHleInputDevice(type, port)) {
return;
}
}
}
BindHostDevice(port, usb_port, type);
}
}

View File

@ -176,7 +176,6 @@ void DestructHleInputDevice(int Port)
g_XboxControllerHostBridge[Port].XboxType = XBOX_INPUT_DEVICE::DEVICE_INVALID;
g_XboxControllerHostBridge[Port].XboxPort = PORT_INVALID;
while (g_XboxControllerHostBridge[Port].bIoInProgress) {}
std::memset(&InState[Port], 0, g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize);
g_XboxControllerHostBridge[Port].bPendingRemoval = false;
g_XboxControllerHostBridge[Port].bSignaled = false;
g_XboxControllerHostBridge[Port].bIoInProgress = false;
@ -185,6 +184,7 @@ void DestructHleInputDevice(int Port)
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize = 0;
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize = 0;
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber = 0;
std::memset(&InState[Port], 0, sizeof(CXBX_XINPUT_IN_STATE));
g_bIsDevicesEmulating = false;
}
@ -298,25 +298,22 @@ void UpdateConnectedDeviceState(xbox::PXPP_DEVICE_TYPE DeviceType) {
int Port, PortMask;
for (Port = PORT_1, PortMask = 1; Port <= PORT_4; Port++, PortMask <<= 1) {
if (DeviceType == g_XboxControllerHostBridge[Port].XboxType) {
if (!g_XboxControllerHostBridge[Port].bPendingRemoval) {
DeviceType->CurrentConnected |= PortMask;
}
else {
if (!g_XboxControllerHostBridge[Port].bSignaled) {
g_XboxControllerHostBridge[Port].bSignaled = true;
SDL_Event DeviceRemoveEvent;
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
DeviceRemoveEvent.user.data1 = new int(Port);
SDL_PushEvent(&DeviceRemoveEvent);
}
DeviceType->CurrentConnected &= ~PortMask;
}
if (DeviceType == g_XboxControllerHostBridge[Port].XboxType && !g_XboxControllerHostBridge[Port].bPendingRemoval) {
DeviceType->CurrentConnected |= PortMask;
}
else {
DeviceType->CurrentConnected &= ~PortMask;
}
if (static_cast<uint8_t>(g_XboxControllerHostBridge[Port].bPendingRemoval) &
~(static_cast<uint8_t>(g_XboxControllerHostBridge[Port].bSignaled))) {
g_XboxControllerHostBridge[Port].bSignaled = true;
SDL_Event DeviceRemoveEvent;
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
DeviceRemoveEvent.user.data1 = new int(Port);
SDL_PushEvent(&DeviceRemoveEvent);
}
}
DeviceType->ChangeConnected = DeviceType->PreviousConnected ^ DeviceType->CurrentConnected;
}

View File

@ -42,6 +42,7 @@ static INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wPara
LRESULT CALLBACK WindowsCtrlSubProcNumericFilter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
HWND g_ChildWnd = NULL;
static bool g_bHasOptChanges = false;
static bool g_bHasInputChanges[4] = { false, false, false, false };
void SyncInputSettings(int port_num, int dev_type, bool is_opt)
@ -143,8 +144,12 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
std::to_string(g_Settings->m_input_general.MoWheelRange).c_str()));
}
// Reset option changes flag
// Reset option/input changes flag
g_bHasOptChanges = false;
g_bHasInputChanges[0] = false;
g_bHasInputChanges[1] = false;
g_bHasInputChanges[2] = false;
g_bHasInputChanges[3] = false;
}
break;
@ -152,9 +157,19 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
{
if (g_bHasOptChanges) {
UpdateInputOpt(hWndDlg);
g_InputDeviceManager.UpdateOpt(true);
SyncInputSettings(0, 0, true);
}
for (int port = PORT_1; port <= PORT_4; port++) {
if (g_bHasInputChanges[port]) {
HWND hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + port);
int DeviceType = SendMessage(hHandle, CB_GETITEMDATA, SendMessage(hHandle, CB_GETCURSEL, 0, 0), 0);
g_Settings->m_input_port[port].Type = DeviceType;
SyncInputSettings(port, DeviceType, false);
}
}
g_InputDeviceManager.Shutdown();
g_ChildWnd = NULL;
EndDialog(hWndDlg, wParam);
@ -182,11 +197,6 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
assert(DeviceType > to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
DeviceType < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX));
if (g_bHasOptChanges) {
UpdateInputOpt(hWndDlg);
g_InputDeviceManager.UpdateOpt(true);
}
switch (DeviceType)
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
@ -206,8 +216,7 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
break;
}
// Also inform the kernel process if it exists
SyncInputSettings(port, DeviceType, false);
g_bHasInputChanges[port] = true;
}
}
break;
@ -234,10 +243,7 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + port), TRUE);
}
g_Settings->m_input_port[port].Type = dev_type;
// Also inform the kernel process if it exists
SyncInputSettings(port, dev_type, false);
g_bHasInputChanges[port] = true;
}
}
break;