https://git.reactos.org/?p=reactos.git;a=commitdiff;h=41c8c312e1a167c179a557...
commit 41c8c312e1a167c179a557a3a435e0bd108b39af Author: Amine Khaldi amine.khaldi@reactos.org AuthorDate: Sat Oct 26 13:03:34 2019 +0100 Commit: Amine Khaldi amine.khaldi@reactos.org CommitDate: Sat Oct 26 13:03:34 2019 +0100
[DINPUT] Sync with Wine Staging 4.18. CORE-16441 --- dll/directx/wine/dinput/CMakeLists.txt | 2 +- dll/directx/wine/dinput/config.c | 203 +++++++++++++------ dll/directx/wine/dinput/device.c | 212 +++++++++++++++----- dll/directx/wine/dinput/device_private.h | 5 + dll/directx/wine/dinput/dinput_main.c | 124 +++++++----- dll/directx/wine/dinput/dinput_private.h | 1 + dll/directx/wine/dinput/effect_linuxinput.c | 6 +- dll/directx/wine/dinput/joystick.c | 271 +++++++++++++++++++------- dll/directx/wine/dinput/joystick_linux.c | 118 ++++++++--- dll/directx/wine/dinput/joystick_linuxinput.c | 255 +++++++++++++++++------- dll/directx/wine/dinput/joystick_osx.c | 116 +++++++++-- dll/directx/wine/dinput/joystick_private.h | 5 + dll/directx/wine/dinput/keyboard.c | 21 +- dll/directx/wine/dinput/mouse.c | 24 ++- dll/directx/wine/dinput/precomp.h | 2 - media/doc/README.WINE | 2 +- 16 files changed, 996 insertions(+), 371 deletions(-)
diff --git a/dll/directx/wine/dinput/CMakeLists.txt b/dll/directx/wine/dinput/CMakeLists.txt index 7244903e99f..638312f44b9 100644 --- a/dll/directx/wine/dinput/CMakeLists.txt +++ b/dll/directx/wine/dinput/CMakeLists.txt @@ -1,5 +1,5 @@
-add_definitions(-D__WINESRC__) +add_definitions(-D__WINESRC__ -DDIRECTINPUT_VERSION=0x0700) include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) spec2def(dinput.dll dinput.spec ADD_IMPORTLIB)
diff --git a/dll/directx/wine/dinput/config.c b/dll/directx/wine/dinput/config.c index 885f1f4b8ee..b8a280adac7 100644 --- a/dll/directx/wine/dinput/config.c +++ b/dll/directx/wine/dinput/config.c @@ -18,17 +18,23 @@
#define NONAMELESSUNION
+ #include "wine/unicode.h" #include "objbase.h" #include "dinput_private.h" #include "device_private.h" #include "resource.h"
+#include "wine/heap.h" + typedef struct { int nobjects; IDirectInputDevice8W *lpdid; DIDEVICEINSTANCEW ddi; DIDEVICEOBJECTINSTANCEW ddo[256]; + /* ActionFormat for every user. + * In same order as ConfigureDevicesData usernames */ + DIACTIONFORMATW *user_afs; } DeviceData;
typedef struct { @@ -38,10 +44,11 @@ typedef struct {
typedef struct { IDirectInput8W *lpDI; - LPDIACTIONFORMATW lpdiaf; LPDIACTIONFORMATW original_lpdiaf; DIDevicesData devices_data; int display_only; + int nusernames; + WCHAR **usernames; } ConfigureDevicesData;
/* @@ -57,27 +64,43 @@ static BOOL CALLBACK collect_objects(LPCDIDEVICEOBJECTINSTANCEW lpddo, LPVOID pv return DIENUM_CONTINUE; }
-static BOOL CALLBACK count_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef) +static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef) { - DIDevicesData *data = (DIDevicesData*) pvRef; + ConfigureDevicesData *data = (ConfigureDevicesData*) pvRef; + DeviceData *device; + int i, j;
- data->ndevices++; - return DIENUM_CONTINUE; -} + IDirectInputDevice_AddRef(lpdid);
-static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef) -{ - DIDevicesData *data = (DIDevicesData*) pvRef; - DeviceData *device = &data->devices[data->ndevices]; + /* alloc array for devices if this is our first device */ + if (!data->devices_data.ndevices) + data->devices_data.devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * (dwRemaining + 1)); + device = &data->devices_data.devices[data->devices_data.ndevices]; device->lpdid = lpdid; device->ddi = *lpddi;
- IDirectInputDevice_AddRef(lpdid); - device->nobjects = 0; IDirectInputDevice_EnumObjects(lpdid, collect_objects, (LPVOID) device, DIDFT_ALL);
- data->ndevices++; + device->user_afs = heap_alloc(sizeof(*device->user_afs) * data->nusernames); + memset(device->user_afs, 0, sizeof(*device->user_afs) * data->nusernames); + for (i = 0; i < data->nusernames; i++) + { + DIACTIONFORMATW *user_af = &device->user_afs[i]; + user_af->dwNumActions = data->original_lpdiaf->dwNumActions; + user_af->guidActionMap = data->original_lpdiaf->guidActionMap; + user_af->rgoAction = heap_alloc(sizeof(DIACTIONW) * data->original_lpdiaf->dwNumActions); + memset(user_af->rgoAction, 0, sizeof(DIACTIONW) * data->original_lpdiaf->dwNumActions); + for (j = 0; j < user_af->dwNumActions; j++) + { + user_af->rgoAction[j].dwSemantic = data->original_lpdiaf->rgoAction[j].dwSemantic; + user_af->rgoAction[j].dwFlags = data->original_lpdiaf->rgoAction[j].dwFlags; + user_af->rgoAction[j].u.lptszActionName = data->original_lpdiaf->rgoAction[j].u.lptszActionName; + } + IDirectInputDevice8_BuildActionMap(lpdid, user_af, data->usernames[i], 0); + } + + data->devices_data.ndevices++; return DIENUM_CONTINUE; }
@@ -170,10 +193,18 @@ static DeviceData* get_cur_device(HWND dialog) return &data->devices_data.devices[sel]; }
-static LPDIACTIONFORMATW get_cur_lpdiaf(HWND dialog) +static DIACTIONFORMATW *get_cur_lpdiaf(HWND dialog) { ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER); - return data->lpdiaf; + int controller_sel = SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_GETCURSEL, 0, 0); + int player_sel = SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_GETCURSEL, 0, 0); + return &data->devices_data.devices[controller_sel].user_afs[player_sel]; +} + +static DIACTIONFORMATW *get_original_lpdiaf(HWND dialog) +{ + ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER); + return data->original_lpdiaf; }
static int dialog_display_only(HWND dialog) @@ -182,40 +213,36 @@ static int dialog_display_only(HWND dialog) return data->display_only; }
-static void init_devices(HWND dialog, IDirectInput8W *lpDI, DIDevicesData *data, LPDIACTIONFORMATW lpdiaf) +static void init_devices(HWND dialog, ConfigureDevicesData *data) { int i;
- /* Count devices */ - data->ndevices = 0; - IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, count_devices, (LPVOID) data, 0); - - /* Allocate devices */ - data->devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * data->ndevices); - /* Collect and insert */ - data->ndevices = 0; - IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, collect_devices, (LPVOID) data, 0); + data->devices_data.ndevices = 0; + IDirectInput8_EnumDevicesBySemantics(data->lpDI, NULL, data->original_lpdiaf, collect_devices, (LPVOID) data, 0);
- for (i=0; i < data->ndevices; i++) - SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices[i].ddi.tszProductName ); + for (i = 0; i < data->devices_data.ndevices; i++) + SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices_data.devices[i].ddi.tszProductName ); + for (i = 0; i < data->nusernames; i++) + SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->usernames[i]); }
static void destroy_data(HWND dialog) { - int i; + int i, j; ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER); DIDevicesData *devices_data = &data->devices_data;
/* Free the devices */ for (i=0; i < devices_data->ndevices; i++) + { IDirectInputDevice8_Release(devices_data->devices[i].lpdid); + for (j=0; j < data->nusernames; j++) + heap_free(devices_data->devices[i].user_afs[j].rgoAction); + heap_free(devices_data->devices[i].user_afs); + }
HeapFree(GetProcessHeap(), 0, devices_data->devices); - - /* Free the backup LPDIACTIONFORMATW */ - HeapFree(GetProcessHeap(), 0, data->original_lpdiaf->rgoAction); - HeapFree(GetProcessHeap(), 0, data->original_lpdiaf); }
static void fill_device_object_list(HWND dialog) @@ -231,6 +258,7 @@ static void fill_device_object_list(HWND dialog) /* Add each object */ for (i=0; i < device->nobjects; i++) { + DWORD ddo_inst, ddo_type; int action = -1;
item.mask = LVIF_TEXT | LVIF_PARAM; @@ -241,12 +269,20 @@ static void fill_device_object_list(HWND dialog)
/* Add the item */ SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTITEMW, 0, (LPARAM) &item); + ddo_inst = DIDFT_GETINSTANCE(device->ddo[i].dwType); + ddo_type = DIDFT_GETTYPE(device->ddo[i].dwType);
- /* Search for an assigned action for this device */ + /* Search for an assigned action for this device */ for (j=0; j < lpdiaf->dwNumActions; j++) { + DWORD af_inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[j].dwObjID); + DWORD af_type = DIDFT_GETTYPE(lpdiaf->rgoAction[j].dwObjID); + if (af_type == DIDFT_PSHBUTTON) af_type = DIDFT_BUTTON; + if (af_type == DIDFT_RELAXIS) af_type = DIDFT_AXIS; + /* NOTE previously compared dwType == dwObjId but default buildActionMap actions + * were PSHBUTTON and RELAXS and didnt show up on config */ if (IsEqualGUID(&lpdiaf->rgoAction[j].guidInstance, &device->ddi.guidInstance) && - lpdiaf->rgoAction[j].dwObjID == device->ddo[i].dwType) + ddo_inst == af_inst && ddo_type & af_type) { action = j; break; @@ -260,7 +296,7 @@ static void fill_device_object_list(HWND dialog) static void show_suitable_actions(HWND dialog) { DeviceData *device = get_cur_device(dialog); - LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog); + LPDIACTIONFORMATW lpdiaf = get_original_lpdiaf(dialog); int i, added = 0; int obj = lv_get_cur_item(dialog);
@@ -298,10 +334,13 @@ static void assign_action(HWND dialog) int obj = lv_get_cur_item(dialog); int old_action = lv_get_item_data(dialog, obj); int used_obj; - - DIDEVICEOBJECTINSTANCEW ddo = device->ddo[obj]; + DWORD type;
if (old_action == action) return; + if (obj < 0) return; + if (lpdiaf->rgoAction[old_action].dwFlags & DIA_APPFIXED) return; + + type = device->ddo[obj].dwType;
/* Clear old action */ if (old_action != -1) @@ -320,7 +359,7 @@ static void assign_action(HWND dialog) lv_set_action(dialog, used_obj, -1, lpdiaf);
/* Set new action */ - lpdiaf->rgoAction[action].dwObjID = ddo.dwType; + lpdiaf->rgoAction[action].dwObjID = type; lpdiaf->rgoAction[action].guidInstance = device->ddi.guidInstance; lpdiaf->rgoAction[action].dwHow = DIAH_USERCONFIG;
@@ -328,24 +367,35 @@ static void assign_action(HWND dialog) lv_set_action(dialog, obj, action, lpdiaf); }
-static void copy_actions(LPDIACTIONFORMATW to, LPDIACTIONFORMATW from) +static void reset_actions(HWND dialog) { - DWORD i; - for (i=0; i < from->dwNumActions; i++) + ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER); + DIDevicesData *ddata = (DIDevicesData*) &data->devices_data; + unsigned i, j; + + for (i = 0; i < data->devices_data.ndevices; i++) { - to->rgoAction[i].guidInstance = from->rgoAction[i].guidInstance; - to->rgoAction[i].dwObjID = from->rgoAction[i].dwObjID; - to->rgoAction[i].dwHow = from->rgoAction[i].dwHow; - to->rgoAction[i].u.lptszActionName = from->rgoAction[i].u.lptszActionName; + DeviceData *device = &ddata->devices[i]; + for (j = 0; j < data->nusernames; j++) + IDirectInputDevice8_BuildActionMap(device->lpdid, &device->user_afs[j], data->usernames[j], DIDBAM_HWDEFAULTS); } }
-static void reset_actions(HWND dialog) -{ +static void save_actions(HWND dialog) { ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER); - LPDIACTIONFORMATW to = data->lpdiaf, from = data->original_lpdiaf; - - copy_actions(to, from); + DIDevicesData *ddata = (DIDevicesData*) &data->devices_data; + unsigned i, j; + if (!data->display_only) { + for (i = 0; i < ddata->ndevices; i++) + { + DeviceData *device = &ddata->devices[i]; + for (j = 0; j < data->nusernames; j++) + { + if (save_mapping_settings(device->lpdid, &device->user_afs[j], data->usernames[j]) != DI_OK) + MessageBoxA(dialog, "Could not save settings", 0, MB_ICONERROR); + } + } + } }
static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -357,26 +407,27 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w ConfigureDevicesData *data = (ConfigureDevicesData*) lParam;
/* Initialize action format and enumerate devices */ - init_devices(dialog, data->lpDI, &data->devices_data, data->lpdiaf); + init_devices(dialog, data);
/* Store information in the window */ SetWindowLongPtrW(dialog, DWLP_USER, (LONG_PTR) data);
init_listview_columns(dialog);
- /* Create a backup action format for CANCEL and RESET operations */ - data->original_lpdiaf = HeapAlloc(GetProcessHeap(), 0, sizeof(*data->original_lpdiaf)); - data->original_lpdiaf->dwNumActions = data->lpdiaf->dwNumActions; - data->original_lpdiaf->rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*data->lpdiaf->dwNumActions); - copy_actions(data->original_lpdiaf, data->lpdiaf); - /* Select the first device and show its actions */ SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_SETCURSEL, 0, 0); + SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_SETCURSEL, 0, 0); fill_device_object_list(dialog);
+ ShowCursor(TRUE); + break; }
+ case WM_DESTROY: + ShowCursor(FALSE); + break; + case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) @@ -407,6 +458,7 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w break;
case IDC_CONTROLLERCOMBO: + case IDC_PLAYERCOMBO:
switch (HIWORD(wParam)) { @@ -417,12 +469,12 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w break;
case IDOK: + save_actions(dialog); EndDialog(dialog, 0); destroy_data(dialog); break;
case IDCANCEL: - reset_actions(dialog); EndDialog(dialog, 0); destroy_data(dialog); break; @@ -445,15 +497,48 @@ HRESULT _configure_devices(IDirectInput8W *iface, LPVOID pvRefData ) { + int i; + DWORD size; + WCHAR *username = NULL; ConfigureDevicesData data; data.lpDI = iface; - data.lpdiaf = lpdiCDParams->lprgFormats; + data.original_lpdiaf = lpdiCDParams->lprgFormats; data.display_only = !(dwFlags & DICD_EDIT); + data.nusernames = lpdiCDParams->dwcUsers; + if (lpdiCDParams->lptszUserNames == NULL) + { + /* Get default user name */ + GetUserNameW(NULL, &size); + username = heap_alloc(size * sizeof(WCHAR) ); + GetUserNameW(username, &size); + data.nusernames = 1; + data.usernames = heap_alloc(sizeof(WCHAR *)); + data.usernames[0] = username; + } + else + { + WCHAR *p = lpdiCDParams->lptszUserNames; + data.usernames = heap_alloc(sizeof(WCHAR *) * data.nusernames); + for (i = 0; i < data.nusernames; i++) + { + if (*p) + { + data.usernames[i] = p; + while (*(p++)); + } + else + /* Return if there is an empty string */ + return DIERR_INVALIDPARAM; + } + }
InitCommonControls();
DialogBoxParamW(DINPUT_instance, (const WCHAR *)MAKEINTRESOURCE(IDD_CONFIGUREDEVICES), lpdiCDParams->hwnd, ConfigureDevicesDlgProc, (LPARAM)&data);
+ heap_free(username); + heap_free(data.usernames); + return DI_OK; } diff --git a/dll/directx/wine/dinput/device.c b/dll/directx/wine/dinput/device.c index 6c446163d16..df7a22a303b 100644 --- a/dll/directx/wine/dinput/device.c +++ b/dll/directx/wine/dinput/device.c @@ -30,6 +30,7 @@ #include <string.h> #include "wine/debug.h" #include "wine/unicode.h" +#include "wine/heap.h" #include "windef.h" #include "winbase.h" #include "winreg.h" @@ -643,12 +644,29 @@ static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic) return type | (0x0000ff00 & (obj_instance << 8)); }
+static void del_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) { + static const WCHAR subkey[] = { + 'S','o','f','t','w','a','r','e','\', + 'W','i','n','e','\', + 'D','i','r','e','c','t','I','n','p','u','t','\', + 'M','a','p','p','i','n','g','s','\','%','s','\','%','s','\','%','s','\0'}; + WCHAR *keyname; + + keyname = heap_alloc(sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid))); + sprintfW(keyname, subkey, username, device, guid); + + /* Remove old key mappings so there will be no overlapping mappings */ + RegDeleteKeyW(HKEY_CURRENT_USER, keyname); + + heap_free(keyname); +} + /* * get_mapping_key * Retrieves an open registry key to save the mapping, parametrized for an username, * specific device and specific action mapping guid. */ -static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) +static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid, BOOL create) { static const WCHAR subkey[] = { 'S','o','f','t','w','a','r','e','\', @@ -663,15 +681,18 @@ static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WC sprintfW(keyname, subkey, username, device, guid);
/* The key used is HKCU\Software\Wine\DirectInput\Mappings[username][device][mapping_guid] */ - if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey)) - hkey = 0; + if (create) { + if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey)) + hkey = 0; + } else if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &hkey)) + hkey = 0;
HeapFree(GetProcessHeap(), 0, keyname);
return hkey; }
-static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername) +HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername) { WCHAR *guid_str = NULL; DIDEVICEINSTANCEW didev; @@ -684,7 +705,9 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK) return DI_SETTINGSNOTSAVED;
- hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str); + del_mapping_key(didev.tszInstanceName, lpszUsername, guid_str); + + hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str, TRUE);
if (!hkey) { @@ -714,12 +737,12 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM return DI_OK; }
-static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) +BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) { HKEY hkey; WCHAR *guid_str; DIDEVICEINSTANCEW didev; - int i, mapped = 0; + int i;
didev.dwSize = sizeof(didev); IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev); @@ -727,7 +750,7 @@ static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMAT if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK) return FALSE;
- hkey = get_mapping_key(didev.tszInstanceName, username, guid_str); + hkey = get_mapping_key(didev.tszInstanceName, username, guid_str, FALSE);
if (!hkey) { @@ -748,15 +771,21 @@ static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMAT { lpdiaf->rgoAction[i].dwObjID = id; lpdiaf->rgoAction[i].guidInstance = didev.guidInstance; - lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT; - mapped += 1; + lpdiaf->rgoAction[i].dwHow = DIAH_USERCONFIG; + } + else + { + memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID)); + lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED; } + }
RegCloseKey(hkey); CoTaskMemFree(guid_str);
- return mapped > 0; + /* On Windows BuildActionMap can open empty mapping, so always return TRUE if get_mapping_key is success */ + return TRUE; }
HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) @@ -779,13 +808,18 @@ HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, load_success = load_mapping_settings(This, lpdiaf, username); }
- if (load_success) return DI_OK; + if (load_success) { + /* Update dwCRC to track if action format has changed */ + for (i=0; i < lpdiaf->dwNumActions; i++) + { + lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2)); + lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5))); + } + return DI_OK; + }
for (i=0; i < lpdiaf->dwNumActions; i++) { - /* Don't touch a user configured action */ - if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue; - if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask) { DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic); @@ -816,6 +850,14 @@ HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, } }
+ /* Update dwCRC to track if action format has changed */ + lpdiaf->dwCRC = 0; + for (i=0; i < lpdiaf->dwNumActions; i++) + { + lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2)); + lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5))); + } + if (!has_actions) return DI_NOEFFECT;
return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags); @@ -831,6 +873,7 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L DIPROPSTRING dps; WCHAR username[MAX_PATH]; DWORD username_size = MAX_PATH; + DWORD new_crc = 0; int i, action = 0, num_actions = 0; unsigned int offset = 0;
@@ -841,12 +884,30 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L data_format.dwFlags = DIDF_RELAXIS; data_format.dwDataSize = lpdiaf->dwDataSize;
+ /* Calculate checksum for actionformat */ + for (i=0; i < lpdiaf->dwNumActions; i++) + { + new_crc ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2)); + new_crc ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5))); + } + /* Count the actions */ for (i=0; i < lpdiaf->dwNumActions; i++) - if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance)) + { + if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance) || + (IsEqualGUID(&IID_NULL, &lpdiaf->rgoAction[i].guidInstance) && + ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre || + (lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */) )) + { num_actions++; + } + }
- if (num_actions == 0) return DI_NOEFFECT; + /* Should return DI_NOEFFECT if we dont have any actions and actionformat has not changed */ + if (num_actions == 0 && lpdiaf->dwCRC == new_crc && !(dwFlags & DIDSAM_FORCESAVE)) return DI_NOEFFECT; + + /* update dwCRC to track if action format has changed */ + lpdiaf->dwCRC = new_crc;
This->num_actions = num_actions;
@@ -880,7 +941,39 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
action++; } + else if ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre || + (lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */) + { + DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic); + DWORD type = DIDFT_GETTYPE(obj_id); + DWORD inst = DIDFT_GETINSTANCE(obj_id); + LPDIOBJECTDATAFORMAT obj; + + if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON; + else if (type == DIDFT_RELAXIS) type = DIDFT_AXIS; + + obj = dataformat_to_odf_by_type(df, inst, type); + TRACE("obj %p, inst 0x%08x, type 0x%08x\n", obj, inst, type); + if(obj) + { + memcpy(&obj_df[action], obj, df->dwObjSize); + + This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData; + This->action_map[action].offset = offset; + obj_df[action].dwOfs = offset; + offset += (type & DIDFT_BUTTON) ? 1 : 4; + + action++; + } + } + } + + if (action == 0) + { + HeapFree(GetProcessHeap(), 0, obj_df); + return DI_NOEFFECT; } + data_format.dwNumObjs = action;
IDirectInputDevice8_SetDataFormat(iface, &data_format);
@@ -1140,7 +1233,7 @@ ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface) IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); ULONG ref = InterlockedDecrement(&(This->ref));
- TRACE("(%p) releasing from %d\n", This, ref + 1); + TRACE("(%p) ref %d\n", This, ref);
if (ref) return ref;
@@ -1168,7 +1261,7 @@ ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
HeapFree(GetProcessHeap(), 0, This);
- return DI_OK; + return ref; }
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface) @@ -1181,7 +1274,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa { IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p this=%p,%s,%p)\n", iface, This, debugstr_guid(riid), ppobj); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj); if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDirectInputDeviceA, riid) || IsEqualGUID(&IID_IDirectInputDevice2A, riid) || @@ -1203,7 +1296,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa }
WARN("Unsupported interface!\n"); - return E_FAIL; + return E_NOINTERFACE; }
HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj) @@ -1215,7 +1308,9 @@ HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A ifa ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface) { IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE( "(%p) ref %d\n", This, ref ); + return ref; }
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface) @@ -1231,7 +1326,7 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface, DIDEVICEOBJECTINSTANCEA ddoi; int i;
- TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags); + TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags); TRACE(" - flags = "); _dump_EnumObjects_flags(dwFlags); TRACE("\n"); @@ -1261,7 +1356,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface, DIDEVICEOBJECTINSTANCEW ddoi; int i;
- TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags); + TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags); TRACE(" - flags = "); _dump_EnumObjects_flags(dwFlags); TRACE("\n"); @@ -1292,7 +1387,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, { IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); _dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK; @@ -1357,7 +1452,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( { IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); _dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK; @@ -1596,7 +1691,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A ifac
HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags) { - FIXME("(this=%p,%p,0x%08x): stub!\n", iface, hwndOwner, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("%p)->(%p,0x%08x): stub!\n", This, hwndOwner, dwFlags);
return DI_OK; } @@ -1610,7 +1706,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A if HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) { - FIXME("(this=%p,%p,%d,%s): stub!\n", iface, hinst, dwVersion, debugstr_guid(rguid)); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%d,%s): stub!\n", This, hinst, dwVersion, debugstr_guid(rguid)); return DI_OK; }
@@ -1628,7 +1725,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) { - FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%s,%p,%p,%p): stub!\n", This, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
FIXME("not available in the generic implementation\n"); *ppdef = NULL; @@ -1648,9 +1746,9 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects( LPVOID lpvRef, DWORD dwFlags) { - FIXME("(this=%p,%p,%p,0x%08x): stub!\n", - iface, lpCallback, lpvRef, dwFlags); - + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); + FIXME("%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags); + return DI_OK; }
@@ -1660,9 +1758,9 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects( LPVOID lpvRef, DWORD dwFlags) { - FIXME("(this=%p,%p,%p,0x%08x): stub!\n", - iface, lpCallback, lpvRef, dwFlags); - + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags); + return DI_OK; }
@@ -1671,8 +1769,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo( LPDIEFFECTINFOA lpdei, REFGUID rguid) { - FIXME("(this=%p,%p,%s): stub!\n", - iface, lpdei, debugstr_guid(rguid)); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); + FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid)); return DI_OK; }
@@ -1681,14 +1779,15 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo( LPDIEFFECTINFOW lpdei, REFGUID rguid) { - FIXME("(this=%p,%p,%s): stub!\n", - iface, lpdei, debugstr_guid(rguid)); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid)); return DI_OK; }
HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) { - FIXME("(this=%p,%p): stub!\n", iface, pdwOut); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p): stub!\n", This, pdwOut); return DI_OK; }
@@ -1700,7 +1799,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVIC
HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) { - TRACE("(%p) 0x%08x:\n", iface, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + TRACE("(%p)->(0x%08x)\n", This, dwFlags); return DI_NOEFFECT; }
@@ -1713,7 +1813,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDE HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags) { - FIXME("(this=%p,%p,%p,0x%08x): stub!\n", iface, lpCallback, lpvRef, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)0>(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags); return DI_OK; }
@@ -1726,7 +1827,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDE
HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc) { - FIXME("(this=%p,%p): stub!\n", iface, lpDIEEsc); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p): stub!\n", This, lpDIEEsc); return DI_OK; }
@@ -1756,7 +1858,8 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W ifa LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) { - FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n", iface, cbObjectData, rgdod, pdwInOut, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(0x%08x,%p,%p,0x%08x): stub!\n", This, cbObjectData, rgdod, pdwInOut, dwFlags);
return DI_OK; } @@ -1776,7 +1879,8 @@ HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A LPVOID pvRef, DWORD dwFlags) { - FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); + FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, lpszFileName, pec, pvRef, dwFlags);
return DI_OK; } @@ -1787,7 +1891,8 @@ HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W LPVOID pvRef, DWORD dwFlags) { - FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
return DI_OK; } @@ -1798,7 +1903,8 @@ HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) { - FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); + FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
return DI_OK; } @@ -1809,7 +1915,8 @@ HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) { - FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
return DI_OK; } @@ -1819,7 +1926,8 @@ HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifa LPCWSTR lpszUserName, DWORD dwFlags) { - FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags); #define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n"); X(DIDBAM_DEFAULT) X(DIDBAM_PRESERVE) @@ -1833,7 +1941,8 @@ HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifa HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) { - FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); + FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
return DI_OK; } @@ -1841,7 +1950,8 @@ HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) { - FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader); + IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
return DI_OK; } diff --git a/dll/directx/wine/dinput/device_private.h b/dll/directx/wine/dinput/device_private.h index d9e2997eaaf..114e3971ed8 100644 --- a/dll/directx/wine/dinput/device_private.h +++ b/dll/directx/wine/dinput/device_private.h @@ -114,6 +114,8 @@ typedef struct LPDIRECTINPUTEFFECT ref; } effect_list_item;
+extern const GUID DInput_PIDVID_Product_GUID DECLSPEC_HIDDEN; + /* Various debug tools */ extern void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) DECLSPEC_HIDDEN; extern void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) DECLSPEC_HIDDEN; @@ -123,6 +125,9 @@ extern const char *_dump_dinput_GUID(const GUID *guid) DECLSPEC_HIDDEN;
extern LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) DECLSPEC_HIDDEN;
+extern HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername) DECLSPEC_HIDDEN; +extern BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) DECLSPEC_HIDDEN; + extern HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN; extern HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
diff --git a/dll/directx/wine/dinput/dinput_main.c b/dll/directx/wine/dinput/dinput_main.c index 4b058891d93..645d29dfd87 100644 --- a/dll/directx/wine/dinput/dinput_main.c +++ b/dll/directx/wine/dinput/dinput_main.c @@ -30,7 +30,6 @@ * - Fallout : works great in X and DGA mode */
-#include "config.h" #include <assert.h> #include <stdarg.h> #include <string.h> @@ -39,7 +38,9 @@ #define NONAMELESSUNION
#include "wine/debug.h" +#include "wine/heap.h" #include "wine/unicode.h" +#include "wine/asm.h" #include "windef.h" #include "winbase.h" #include "winuser.h" @@ -47,6 +48,7 @@ #include "objbase.h" #include "rpcproxy.h" #include "initguid.h" +#include "devguid.h" #include "dinput_private.h" #include "device_private.h" #include "dinputd.h" @@ -289,6 +291,20 @@ static void _dump_EnumDevices_dwFlags(DWORD dwFlags) TRACE("\n"); }
+static const char *dump_semantic(DWORD semantic) +{ + if((semantic & 0xff000000) == 0xff000000) + return "Any AXIS"; + else if((semantic & 0x82000000) == 0x82000000) + return "Mouse"; + else if((semantic & 0x81000000) == 0x81000000) + return "Keybaord"; + else if((semantic & DIVIRTUAL_FLYING_HELICOPTER) == DIVIRTUAL_FLYING_HELICOPTER) + return "Helicopter"; + + return "Unknown"; +} + static void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat) { unsigned int i; @@ -311,7 +327,7 @@ static void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat) { TRACE("diaf.rgoAction[%u]:\n", i); TRACE("\tuAppData=0x%lx\n", lpdiActionFormat->rgoAction[i].uAppData); - TRACE("\tdwSemantic=0x%08x\n", lpdiActionFormat->rgoAction[i].dwSemantic); + TRACE("\tdwSemantic=0x%08x (%s)\n", lpdiActionFormat->rgoAction[i].dwSemantic, dump_semantic(lpdiActionFormat->rgoAction[i].dwSemantic)); TRACE("\tdwFlags=0x%x\n", lpdiActionFormat->rgoAction[i].dwFlags); TRACE("\tszActionName=%s\n", debugstr_a(lpdiActionFormat->rgoAction[i].u.lptszActionName)); TRACE("\tguidInstance=%s\n", debugstr_guid(&lpdiActionFormat->rgoAction[i].guidInstance)); @@ -467,9 +483,10 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
for (i = 0; i < ARRAY_SIZE(dinput_devices); i++) { if (!dinput_devices[i]->enum_deviceA) continue; + + TRACE(" Checking device %u ('%s')\n", i, dinput_devices[i]->name); for (j = 0, r = S_OK; SUCCEEDED(r); j++) { devInstance.dwSize = sizeof(devInstance); - TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name); r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j); if (r == S_OK) if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP) @@ -525,7 +542,7 @@ static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface) IDirectInputImpl *This = impl_from_IDirectInput7A( iface ); ULONG ref = InterlockedIncrement(&This->ref);
- TRACE( "(%p) incrementing from %d\n", This, ref - 1); + TRACE( "(%p) ref %d\n", This, ref ); return ref; }
@@ -540,7 +557,7 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface) IDirectInputImpl *This = impl_from_IDirectInput7A( iface ); ULONG ref = InterlockedDecrement( &This->ref );
- TRACE( "(%p) releasing from %d\n", This, ref + 1 ); + TRACE( "(%p) ref %d\n", This, ref );
if (ref == 0) { @@ -566,53 +583,39 @@ static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, RE if (!riid || !ppobj) return E_POINTER;
+ *ppobj = NULL; + +#if DIRECTINPUT_VERSION == 0x0700 if (IsEqualGUID( &IID_IUnknown, riid ) || - IsEqualGUID( &IID_IDirectInputA, riid ) || - IsEqualGUID( &IID_IDirectInput2A, riid ) || - IsEqualGUID( &IID_IDirectInput7A, riid )) - { + IsEqualGUID( &IID_IDirectInputA, riid ) || + IsEqualGUID( &IID_IDirectInput2A, riid ) || + IsEqualGUID( &IID_IDirectInput7A, riid )) *ppobj = &This->IDirectInput7A_iface; - IUnknown_AddRef( (IUnknown*)*ppobj ); - - return DI_OK; - } - - if (IsEqualGUID( &IID_IDirectInputW, riid ) || - IsEqualGUID( &IID_IDirectInput2W, riid ) || - IsEqualGUID( &IID_IDirectInput7W, riid )) - { + else if (IsEqualGUID( &IID_IDirectInputW, riid ) || + IsEqualGUID( &IID_IDirectInput2W, riid ) || + IsEqualGUID( &IID_IDirectInput7W, riid )) *ppobj = &This->IDirectInput7W_iface; - IUnknown_AddRef( (IUnknown*)*ppobj ); - - return DI_OK; - }
- if (IsEqualGUID( &IID_IDirectInput8A, riid )) - { +#else + if (IsEqualGUID( &IID_IUnknown, riid ) || + IsEqualGUID( &IID_IDirectInput8A, riid )) *ppobj = &This->IDirectInput8A_iface; - IUnknown_AddRef( (IUnknown*)*ppobj ); - - return DI_OK; - }
- if (IsEqualGUID( &IID_IDirectInput8W, riid )) - { + else if (IsEqualGUID( &IID_IDirectInput8W, riid )) *ppobj = &This->IDirectInput8W_iface; - IUnknown_AddRef( (IUnknown*)*ppobj );
- return DI_OK; - } +#endif
if (IsEqualGUID( &IID_IDirectInputJoyConfig8, riid )) - { *ppobj = &This->IDirectInputJoyConfig8_iface; - IUnknown_AddRef( (IUnknown*)*ppobj );
+ if(*ppobj) + { + IUnknown_AddRef( (IUnknown*)*ppobj ); return DI_OK; }
- FIXME( "Unsupported interface: %s\n", debugstr_guid(riid)); - *ppobj = NULL; + WARN( "Unsupported interface: %s\n", debugstr_guid(riid)); return E_NOINTERFACE; }
@@ -690,7 +693,7 @@ static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTA { IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
- TRACE("(%p)->(%p, 0x%04x)\n", iface, hinst, version); + TRACE("(%p)->(%p, 0x%04x)\n", This, hinst, version);
if (!hinst) return DIERR_INVALIDPARAM; @@ -947,7 +950,7 @@ static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINST { IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
- TRACE("(%p)->(%p, 0x%04x)\n", iface, hinst, version); + TRACE("(%p)->(%p, 0x%04x)\n", This, hinst, version);
if (!hinst) return DIERR_INVALIDPARAM; @@ -1104,10 +1107,12 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
if (lpCallback(&didevis[i], lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP) { + IDirectInputDevice_Release(lpdid); HeapFree(GetProcessHeap(), 0, didevis); HeapFree(GetProcessHeap(), 0, username_w); return DI_OK; } + IDirectInputDevice_Release(lpdid); }
HeapFree(GetProcessHeap(), 0, didevis); @@ -1130,9 +1135,11 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP) { + IDirectInputDevice_Release(lpdid); HeapFree(GetProcessHeap(), 0, username_w); return DI_OK; } + IDirectInputDevice_Release(lpdid); } }
@@ -1260,9 +1267,34 @@ static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
/* Copy parameters */ diCDParamsW.dwSize = sizeof(DICONFIGUREDEVICESPARAMSW); + diCDParamsW.dwcUsers = lpdiCDParams->dwcUsers; diCDParamsW.dwcFormats = lpdiCDParams->dwcFormats; diCDParamsW.lprgFormats = &diafW; diCDParamsW.hwnd = lpdiCDParams->hwnd; + diCDParamsW.lptszUserNames = NULL; + + if (lpdiCDParams->lptszUserNames) { + char *start = lpdiCDParams->lptszUserNames; + WCHAR *to = NULL; + int total_len = 0; + for (i = 0; i < lpdiCDParams->dwcUsers; i++) + { + char *end = start + 1; + int len; + while (*(end++)); + len = MultiByteToWideChar(CP_ACP, 0, start, end - start, NULL, 0); + total_len += len + 2; /* length of string and two null char */ + if (to) + to = HeapReAlloc(GetProcessHeap(), 0, to, sizeof(WCHAR) * total_len); + else + to = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * total_len); + + MultiByteToWideChar(CP_ACP, 0, start, end - start, to + (total_len - len - 2), len); + to[total_len] = 0; + to[total_len - 1] = 0; + } + diCDParamsW.lptszUserNames = to; + }
diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiCDParams->lprgFormats->dwNumActions); _copy_diactionformatAtoW(&diafW, lpdiCDParams->lprgFormats); @@ -1290,6 +1322,8 @@ static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
+ heap_free((void*) diCDParamsW.lptszUserNames); + return hr; }
@@ -1777,7 +1811,7 @@ static DWORD WINAPI hook_thread_proc(void *param) DispatchMessageW(&msg); }
- return 0; + FreeLibraryAndExitThread(DINPUT_instance, 0); }
static DWORD hook_thread_id; @@ -1794,15 +1828,16 @@ static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0 static BOOL check_hook_thread(void) { static HANDLE hook_thread; + HMODULE module;
EnterCriticalSection(&dinput_hook_crit);
TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list)); if (!list_empty(&direct_input_list) && !hook_thread) { + GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)DINPUT_instance, &module); hook_thread_event = CreateEventW(NULL, FALSE, FALSE, NULL); hook_thread = CreateThread(NULL, 0, hook_thread_proc, hook_thread_event, 0, &hook_thread_id); - LeaveCriticalSection(&dinput_hook_crit); } else if (list_empty(&direct_input_list) && hook_thread) { @@ -1817,16 +1852,11 @@ static BOOL check_hook_thread(void)
hook_thread_id = 0; PostThreadMessageW(tid, WM_USER+0x10, 0, 0); - LeaveCriticalSection(&dinput_hook_crit); - - /* wait for hook thread to exit */ - WaitForSingleObject(hook_thread, INFINITE); CloseHandle(hook_thread); hook_thread = NULL; } - else - LeaveCriticalSection(&dinput_hook_crit);
+ LeaveCriticalSection(&dinput_hook_crit); return hook_thread_id != 0; }
diff --git a/dll/directx/wine/dinput/dinput_private.h b/dll/directx/wine/dinput/dinput_private.h index acda6c80485..289b2f1f63d 100644 --- a/dll/directx/wine/dinput/dinput_private.h +++ b/dll/directx/wine/dinput/dinput_private.h @@ -81,6 +81,7 @@ extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLS extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN;
extern WCHAR* get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN; +extern DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN;
#define IS_DIPROP(x) (((ULONG_PTR)(x) >> 16) == 0)
diff --git a/dll/directx/wine/dinput/effect_linuxinput.c b/dll/directx/wine/dinput/effect_linuxinput.c index 7477bc757da..4b2f317ce37 100644 --- a/dll/directx/wine/dinput/effect_linuxinput.c +++ b/dll/directx/wine/dinput/effect_linuxinput.c @@ -167,7 +167,9 @@ static ULONG WINAPI LinuxInputEffectImpl_AddRef( LPDIRECTINPUTEFFECT iface) { LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE( "(%p) ref %d\n", This, ref ); + return ref; }
static HRESULT WINAPI LinuxInputEffectImpl_Download( @@ -759,6 +761,8 @@ static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface) LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE( "(%p) ref %d\n", This, ref ); + if (ref == 0) { LinuxInputEffectImpl_Stop(iface); diff --git a/dll/directx/wine/dinput/joystick.c b/dll/directx/wine/dinput/joystick.c index 0ec1ceb2497..9d7baf411a4 100644 --- a/dll/directx/wine/dinput/joystick.c +++ b/dll/directx/wine/dinput/joystick.c @@ -28,12 +28,40 @@
#include <stdio.h>
+#include "device_private.h" #include "joystick_private.h" #include "wine/debug.h" +#include "wine/heap.h" #include "winreg.h"
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+#define VID_MICROSOFT 0x045e + +static const WORD PID_XBOX_CONTROLLERS[] = { + 0x0202, /* Xbox Controller */ + 0x0285, /* Xbox Controller S */ + 0x0289, /* Xbox Controller S */ + 0x028e, /* Xbox360 Controller */ + 0x028f, /* Xbox360 Wireless Controller */ + 0x02d1, /* Xbox One Controller */ + 0x02dd, /* Xbox One Controller (Covert Forces/Firmware 2015) */ + 0x02e0, /* Xbox One X Controller */ + 0x02e3, /* Xbox One Elite Controller */ + 0x02e6, /* Wireless XBox Controller Dongle */ + 0x02ea, /* Xbox One S Controller */ + 0x02fd, /* Xbox One S Controller (Firmware 2017) */ + 0x0719, /* Xbox 360 Wireless Adapter */ +}; + +/* Windows uses this GUID for guidProduct on non-keyboard/mouse devices. + * Data1 contains the device VID (low word) and PID (high word). + * Data4 ends with the ASCII bytes "PIDVID". + */ +const GUID DInput_PIDVID_Product_GUID = { /* device_pidvid-0000-0000-0000-504944564944 */ + 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44} +}; + static inline JoystickGenericImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface) { return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), JoystickGenericImpl, base); @@ -76,6 +104,16 @@ DWORD typeFromGUID(REFGUID guid) } }
+DWORD get_device_type(DWORD version, BOOL is_joystick) +{ + if (is_joystick) + return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) : + DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + + return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) : + DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8); +} + static void _dump_DIEFFECT_flags(DWORD dwFlags) { if (TRACE_ON(dinput)) { @@ -271,6 +309,89 @@ BOOL device_disabled_registry(const char* name) return do_disable; }
+BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) +{ + int i; + + if (vid == VID_MICROSOFT) + { + for (i = 0; i < ARRAY_SIZE(PID_XBOX_CONTROLLERS); i++) + if (pid == PID_XBOX_CONTROLLERS[i]) return TRUE; + } + + return (devcaps->dwAxes == 6 && devcaps->dwButtons >= 14); +} + +static void remap_init(JoystickGenericImpl *This, int obj, ObjProps *remap_props) +{ + /* Configure as if nothing changed so the helper functions can only change + * what they need, thus reducing code duplication. */ + remap_props->lDevMin = remap_props->lMin = This->props[obj].lMin; + remap_props->lDevMax = remap_props->lMax = This->props[obj].lMax; + + remap_props->lDeadZone = This->props[obj].lDeadZone; + remap_props->lSaturation = This->props[obj].lSaturation; +} + +static void remap_apply(JoystickGenericImpl *This, int obj, ObjProps *remap_props) +{ + /* Many games poll the joystick immediately after setting the range + * for calibration purposes, so the old values need to be remapped + * to the new range before it does so */ + switch (This->base.data_format.wine_df->rgodf[obj].dwOfs){ + case DIJOFS_X : This->js.lX = joystick_map_axis(remap_props, This->js.lX); break; + case DIJOFS_Y : This->js.lY = joystick_map_axis(remap_props, This->js.lY); break; + case DIJOFS_Z : This->js.lZ = joystick_map_axis(remap_props, This->js.lZ); break; + case DIJOFS_RX : This->js.lRx = joystick_map_axis(remap_props, This->js.lRx); break; + case DIJOFS_RY : This->js.lRy = joystick_map_axis(remap_props, This->js.lRy); break; + case DIJOFS_RZ : This->js.lRz = joystick_map_axis(remap_props, This->js.lRz); break; + case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(remap_props, This->js.rglSlider[0]); break; + case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(remap_props, This->js.rglSlider[1]); break; + default: break; + } +} + +static void remap_range(JoystickGenericImpl *This, int obj, LPCDIPROPRANGE pr) +{ + ObjProps remap_props; + remap_init(This, obj, &remap_props); + + remap_props.lMin = pr->lMin; + remap_props.lMax = pr->lMax; + + remap_apply(This, obj, &remap_props); + + /* Store new values */ + This->props[obj].lMin = pr->lMin; + This->props[obj].lMax = pr->lMax; +} + +static void remap_deadzone(JoystickGenericImpl *This, int obj, LPCDIPROPDWORD pd) +{ + ObjProps remap_props; + remap_init(This, obj, &remap_props); + + remap_props.lDeadZone = pd->dwData; + + remap_apply(This, obj, &remap_props); + + /* Store new value */ + This->props[obj].lDeadZone = pd->dwData; +} + +static void remap_saturation(JoystickGenericImpl *This, int obj, LPCDIPROPDWORD pd) +{ + ObjProps remap_props; + remap_init(This, obj, &remap_props); + + remap_props.lSaturation = pd->dwData; + + remap_apply(This, obj, &remap_props); + + /* Store new value */ + This->props[obj].lSaturation = pd->dwData; +} + /****************************************************************************** * SetProperty : change input device properties */ @@ -278,7 +399,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF { JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); DWORD i; - ObjProps remap_props;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
@@ -295,69 +415,15 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF case (DWORD_PTR)DIPROP_RANGE: { LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph; if (ph->dwHow == DIPH_DEVICE) { - - /* Many games poll the joystick immediately after setting the range - * for calibration purposes, so the old values need to be remapped - * to the new range before it does so */ - TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax); - for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) { - - remap_props.lDevMin = This->props[i].lMin; - remap_props.lDevMax = This->props[i].lMax; - - remap_props.lDeadZone = This->props[i].lDeadZone; - remap_props.lSaturation = This->props[i].lSaturation; - - remap_props.lMin = pr->lMin; - remap_props.lMax = pr->lMax; - - switch (This->base.data_format.wine_df->rgodf[i].dwOfs) { - case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; - case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; - case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; - case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break; - case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break; - case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break; - case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break; - case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break; - default: break; - } - - This->props[i].lMin = pr->lMin; - This->props[i].lMax = pr->lMax; - } + for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) + remap_range(This, i, pr); } else { int obj = find_property(&This->base.data_format, ph);
TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj); - if (obj >= 0) { - - remap_props.lDevMin = This->props[obj].lMin; - remap_props.lDevMax = This->props[obj].lMax; - - remap_props.lDeadZone = This->props[obj].lDeadZone; - remap_props.lSaturation = This->props[obj].lSaturation; - - remap_props.lMin = pr->lMin; - remap_props.lMax = pr->lMax; - - switch (This->base.data_format.wine_df->rgodf[obj].dwOfs) { - case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; - case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; - case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; - case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break; - case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break; - case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break; - case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break; - case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break; - default: break; - } - - This->props[obj].lMin = pr->lMin; - This->props[obj].lMax = pr->lMax; - return DI_OK; - } + if (obj >= 0) + remap_range(This, obj, pr); } break; } @@ -366,15 +432,13 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF if (ph->dwHow == DIPH_DEVICE) { TRACE("deadzone(%d) all\n", pd->dwData); for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) - This->props[i].lDeadZone = pd->dwData; + remap_deadzone(This, i, pd); } else { int obj = find_property(&This->base.data_format, ph);
TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj); - if (obj >= 0) { - This->props[obj].lDeadZone = pd->dwData; - return DI_OK; - } + if (obj >= 0) + remap_deadzone(This, obj, pd); } break; } @@ -383,18 +447,21 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF if (ph->dwHow == DIPH_DEVICE) { TRACE("saturation(%d) all\n", pd->dwData); for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) - This->props[i].lSaturation = pd->dwData; + remap_saturation(This, i, pd); } else { int obj = find_property(&This->base.data_format, ph);
TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); - if (obj >= 0) { - This->props[obj].lSaturation = pd->dwData; - return DI_OK; - } + if (obj >= 0) + remap_saturation(This, obj, pd); } break; } + case (DWORD_PTR)DIPROP_CALIBRATIONMODE: { + LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; + FIXME("DIPROP_CALIBRATIONMODE(%d)\n", pd->dwData); + break; + } default: return IDirectInputDevice2WImpl_SetProperty(iface, rguid, ph); } @@ -461,7 +528,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); int size;
- TRACE("%p->(%p)\n",iface,lpDIDevCaps); + TRACE("%p->(%p)\n",This,lpDIDevCaps);
if (lpDIDevCaps == NULL) { WARN("invalid pointer\n"); @@ -544,7 +611,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF { JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph); + TRACE("(%p,%s,%p)\n", This, debugstr_guid(rguid), pdiph);
if (TRACE_ON(dinput)) _dump_DIPROPHEADER(pdiph); @@ -627,7 +694,7 @@ HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo( DIPROPDWORD pd; DWORD index = 0;
- TRACE("(%p,%p)\n", iface, pdidi); + TRACE("(%p,%p)\n", This, pdidi);
if (pdidi == NULL) { WARN("invalid pointer\n"); @@ -654,7 +721,7 @@ HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo( /* we only support traditional joysticks for now */ pdidi->dwDevType = This->devcaps.dwDevType; snprintf(pdidi->tszInstanceName, MAX_PATH, "Joystick %d", index); - strcpy(pdidi->tszProductName, This->name); + lstrcpynA(pdidi->tszProductName, This->name, MAX_PATH); if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3A)) { pdidi->guidFFDriver = GUID_NULL; pdidi->wUsagePage = 0; @@ -771,8 +838,31 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); unsigned int i, j; BOOL has_actions = FALSE; + WCHAR *username; + DWORD size; + BOOL load_success = FALSE; + + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
- FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); + /* Unless asked the contrary by these flags, try to load a previous mapping */ + if (!(dwFlags & DIDBAM_HWDEFAULTS)) + { + if (!lpszUserName) + GetUserNameW(NULL, &size); + else + size = lstrlenW(lpszUserName) + 1; + + username = heap_alloc(size * sizeof(WCHAR)); + if (!lpszUserName) + GetUserNameW(username, &size); + else + lstrcpynW(username, lpszUserName, size); + + load_success = load_mapping_settings(&This->base, lpdiaf, username); + heap_free(username); + } + + if (load_success) return DI_OK;
for (i=0; i < lpdiaf->dwNumActions; i++) { @@ -850,7 +940,7 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, { JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
- FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, This->base.data_format.wine_df); } @@ -878,6 +968,8 @@ HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
hr = JoystickWGenericImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
+ lpdiaf->dwCRC = diafW.dwCRC; + HeapFree(GetProcessHeap(), 0, diafW.rgoAction); HeapFree(GetProcessHeap(), 0, lpszUserNameW);
@@ -950,6 +1042,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_ int tokens = 0; int axis = 0; int pov = 0; + int button;
get_app_key(&hkey, &appkey);
@@ -961,6 +1054,34 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_ TRACE("setting default deadzone to: "%s" %d\n", buffer, This->deadzone); }
+ for (button = 0; button < MAX_MAP_BUTTONS; button++) + This->button_map[button] = button; + + if (!get_config_key(hkey, appkey, "ButtonMap", buffer, sizeof(buffer))) + { + static const char *delim = ","; + int button = 0; + char *token; + + TRACE("ButtonMap = "%s"\n", buffer); + for (token = strtok(buffer, delim); + token != NULL && button < MAX_MAP_BUTTONS; + token = strtok(NULL, delim), button++) + { + char *s; + int value = strtol(token, &s, 10); + if (value < 0 || *s != '\0') + { + ERR("invalid button number: "%s"", token); + } + else + { + TRACE("mapping physical button %d to DInput button %d", value, button); + This->button_map[value] = button; + } + } + } + This->axis_map = HeapAlloc(GetProcessHeap(), 0, This->device_axis_count * sizeof(int)); if (!This->axis_map) return DIERR_OUTOFMEMORY;
diff --git a/dll/directx/wine/dinput/joystick_linux.c b/dll/directx/wine/dinput/joystick_linux.c index 963e62f017c..3ecbf441aad 100644 --- a/dll/directx/wine/dinput/joystick_linux.c +++ b/dll/directx/wine/dinput/joystick_linux.c @@ -59,6 +59,7 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" +#include "devguid.h" #include "dinput.h"
#include "dinput_private.h" @@ -84,6 +85,8 @@ struct JoyDev int *dev_axes_map;
WORD vendor_id, product_id, bus_type; + + BOOL is_joystick; };
typedef struct JoystickImpl JoystickImpl; @@ -123,19 +126,6 @@ static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7} };
-/* - * Construct the GUID in the same way of Windows doing this. - * Data1 is concatenation of productid and vendorid. - * Data2 and Data3 are NULL. - * Data4 seems to be a constant. - */ -static const GUID DInput_Wine_Joystick_Constant_Part_GUID = { - 0x000000000, - 0x0000, - 0x0000, - {0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44} -}; - #define MAX_JOYSTICKS 64 static INT joystick_devices_count = -1; static struct JoyDev *joystick_devices; @@ -177,6 +167,8 @@ static INT find_joystick_devices(void) int fd; struct JoyDev joydev, *new_joydevs; BYTE axes_map[ABS_MAX + 1]; + SHORT btn_map[KEY_MAX - BTN_MISC + 1]; + BOOL is_stylus = FALSE;
snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i); if ((fd = open(joydev.device, O_RDONLY)) == -1) @@ -220,6 +212,52 @@ static INT find_joystick_devices(void) joydev.button_count = 2; #endif
+ joydev.is_joystick = FALSE; + if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0) + { + WARN("ioctl(%s,JSIOCGBTNMAP) failed: %s\n", joydev.device, strerror(errno)); + } + else + { + INT j; + /* in lieu of properly reporting HID usage, detect presence of + * "joystick buttons" and report those devices as joysticks instead of + * gamepads */ + for (j = 0; !joydev.is_joystick && j < joydev.button_count; j++) + { + switch (btn_map[j]) + { + case BTN_TRIGGER: + case BTN_THUMB: + case BTN_THUMB2: + case BTN_TOP: + case BTN_TOP2: + case BTN_PINKIE: + case BTN_BASE: + case BTN_BASE2: + case BTN_BASE3: + case BTN_BASE4: + case BTN_BASE5: + case BTN_BASE6: + case BTN_DEAD: + joydev.is_joystick = TRUE; + break; + case BTN_STYLUS: + is_stylus = TRUE; + break; + default: + break; + } + } + } + + if(is_stylus) + { + TRACE("Stylus detected. Skipping\n"); + close(fd); + continue; + } + if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0) { WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno)); @@ -239,6 +277,14 @@ static INT find_joystick_devices(void) joydev.dev_axes_map[j] = j; found_axes++; } + else if (axes_map[j] <= 10) + { + /* Axes 8 through 10 are Wheel, Gas and Brake, + * remap to 0, 1 and 2 + */ + joydev.dev_axes_map[j] = axes_map[j] - 8; + found_axes++; + } else if (axes_map[j] == 16 || axes_map[j] == 17) { @@ -279,7 +325,7 @@ static INT find_joystick_devices(void) else { /* Concatenate product_id with vendor_id to mimic Windows behaviour */ - joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID; + joydev.guid_product = DInput_PIDVID_Product_GUID; joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id); }
@@ -314,11 +360,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver lpddi->guidInstance = DInput_Wine_Joystick_GUID; lpddi->guidInstance.Data3 = id; lpddi->guidProduct = joystick_devices[id].guid_product; - /* we only support traditional joysticks for now */ - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + lpddi->dwDevType = get_device_type(version, joystick_devices[id].is_joystick);
/* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ if (joystick_devices[id].bus_type == BUS_USB && @@ -326,7 +368,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver { lpddi->dwDevType |= DIDEVTYPE_HID; lpddi->wUsagePage = 0x01; /* Desktop */ - if (lpddi->dwDevType == DI8DEVTYPE_JOYSTICK || lpddi->dwDevType == DIDEVTYPE_JOYSTICK) + if (joystick_devices[id].is_joystick) lpddi->wUsage = 0x04; /* Joystick */ else lpddi->wUsage = 0x05; /* Game Pad */ @@ -372,7 +414,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS }
if ((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { /* check whether we have a joystick */ if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1) @@ -401,7 +443,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS }
if ((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { /* check whether we have a joystick */ if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1) @@ -673,7 +715,7 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface { JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); _dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK; @@ -699,6 +741,29 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface break; }
+ case (DWORD_PTR) DIPROP_GUIDANDPATH: + { + static const WCHAR formatW[] = {'\','\','?','\','h','i','d','#','v','i','d','_','%','0','4','x','&', + 'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0}; + static const WCHAR miW[] = {'m','i',0}; + static const WCHAR igW[] = {'i','g',0}; + + BOOL is_gamepad; + LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; + WORD vid = This->joydev->vendor_id; + WORD pid = This->joydev->product_id; + + if (!pid || !vid) + return DIERR_UNSUPPORTED; + + is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); + pd->guidClass = GUID_DEVCLASS_HIDCLASS; + sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid)); + + TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); + break; + } + default: return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); } @@ -807,10 +872,13 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface) jse.type,jse.number,jse.value); if (jse.type & JS_EVENT_BUTTON) { + int button; if (jse.number >= This->generic.devcaps.dwButtons) return;
- inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON; - This->generic.js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00; + button = This->generic.button_map[jse.number]; + + inst_id = DIDFT_MAKEINSTANCE(button) | DIDFT_PSHBUTTON; + This->generic.js.rgbButtons[button] = value = jse.value ? 0x80 : 0x00; } else if (jse.type & JS_EVENT_AXIS) { diff --git a/dll/directx/wine/dinput/joystick_linuxinput.c b/dll/directx/wine/dinput/joystick_linuxinput.c index 910e755d3ed..8865532d9d1 100644 --- a/dll/directx/wine/dinput/joystick_linuxinput.c +++ b/dll/directx/wine/dinput/joystick_linuxinput.c @@ -57,6 +57,7 @@ #include "winbase.h" #include "winerror.h" #include "winreg.h" +#include "devguid.h" #include "dinput.h"
#include "dinput_private.h" @@ -83,6 +84,13 @@ struct wine_input_absinfo { LONG flat; };
+enum wine_joystick_linuxinput_fd_state { + WINE_FD_STATE_CLOSED = 0, /* No device has been opened yet */ + WINE_FD_STATE_OK, /* File descriptor is open and ready for reading */ + WINE_FD_STATE_DISCONNECTED, /* Read error occurred; might be able to reopen later */ + WINE_FD_STATE_INVALID, /* Device is no longer available at original pathname */ +}; + /* implemented in effect_linuxinput.c */ HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff); HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info); @@ -100,7 +108,7 @@ struct JoyDev { GUID guid; GUID guid_product;
- BOOL has_ff; + BOOL has_ff, is_joystick; int num_effects;
/* data returned by EVIOCGBIT for caps, EV_ABS, EV_KEY, and EV_FF */ @@ -122,6 +130,7 @@ struct JoystickImpl
/* joystick private */ int joyfd; + enum wine_joystick_linuxinput_fd_state joyfd_state;
int dev_axes_to_di[ABS_MAX]; POINTL povs[4]; @@ -164,19 +173,6 @@ static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a- {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7} };
-/* - * Construct the GUID in the same way of Windows doing this. - * Data1 is concatenation of productid and vendorid. - * Data2 and Data3 are NULL. - * Data4 seems to be a constant. - */ -static const GUID DInput_Wine_Joystick_Constant_Part_GUID = { - 0x000000000, - 0x0000, - 0x0000, - {0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44} -}; - #define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
#define MAX_JOYDEV 64 @@ -211,10 +207,7 @@ static void find_joydevs(void) }
if (fd == -1) - { - WARN("Failed to open "%s": %d %s\n", buf, errno, strerror(errno)); continue; - }
if (ioctl(fd, EVIOCGBIT(0, sizeof(joydev.evbits)), joydev.evbits) == -1) { @@ -237,15 +230,41 @@ static void find_joydevs(void)
/* A true joystick has at least axis X and Y, and at least 1 * button. copied from linux/drivers/input/joydev.c */ - if (!test_bit(joydev.absbits, ABS_X) || !test_bit(joydev.absbits, ABS_Y) || + if (((!test_bit(joydev.absbits, ABS_X) || !test_bit(joydev.absbits, ABS_Y)) && + !test_bit(joydev.absbits, ABS_WHEEL) && + !test_bit(joydev.absbits, ABS_GAS) && + !test_bit(joydev.absbits, ABS_BRAKE)) || !(test_bit(joydev.keybits, BTN_TRIGGER) || test_bit(joydev.keybits, BTN_A) || - test_bit(joydev.keybits, BTN_1))) + test_bit(joydev.keybits, BTN_1) || + test_bit(joydev.keybits, BTN_BASE) || + test_bit(joydev.keybits, BTN_GEAR_UP) || + test_bit(joydev.keybits, BTN_GEAR_DOWN))) { close(fd); continue; }
+ /* in lieu of properly reporting HID usage, detect presence of + * "joystick buttons" and report those devices as joysticks instead of + * gamepads */ + joydev.is_joystick = + test_bit(joydev.keybits, BTN_TRIGGER) || + test_bit(joydev.keybits, BTN_THUMB) || + test_bit(joydev.keybits, BTN_THUMB2) || + test_bit(joydev.keybits, BTN_TOP) || + test_bit(joydev.keybits, BTN_TOP2) || + test_bit(joydev.keybits, BTN_PINKIE) || + test_bit(joydev.keybits, BTN_BASE) || + test_bit(joydev.keybits, BTN_BASE2) || + test_bit(joydev.keybits, BTN_BASE3) || + test_bit(joydev.keybits, BTN_BASE4) || + test_bit(joydev.keybits, BTN_BASE5) || + test_bit(joydev.keybits, BTN_BASE6) || + test_bit(joydev.keybits, BTN_GEAR_UP) || + test_bit(joydev.keybits, BTN_GEAR_DOWN) || + test_bit(joydev.keybits, BTN_DEAD); + if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1))) { close(fd); @@ -320,7 +339,7 @@ static void find_joydevs(void) joydev.bus_type = device_id.bustype;
/* Concatenate product_id with vendor_id to mimic Windows behaviour */ - joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID; + joydev.guid_product = DInput_PIDVID_Product_GUID; joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id); }
@@ -353,11 +372,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver lpddi->guidInstance = joydevs[id].guid; lpddi->guidProduct = joydevs[id].guid_product; lpddi->guidFFDriver = GUID_NULL; - - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + lpddi->dwDevType = get_device_type(version, joydevs[id].is_joystick);
/* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ if (joydevs[id].bus_type == BUS_USB && @@ -365,7 +380,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver { lpddi->dwDevType |= DIDEVTYPE_HID; lpddi->wUsagePage = 0x01; /* Desktop */ - if (lpddi->dwDevType == DI8DEVTYPE_JOYSTICK || lpddi->dwDevType == DIDEVTYPE_JOYSTICK) + if (joydevs[id].is_joystick) lpddi->wUsage = 0x04; /* Joystick */ else lpddi->wUsage = 0x05; /* Game Pad */ @@ -391,8 +406,8 @@ static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD ver lpddi->guidInstance = lpddiW.guidInstance; lpddi->guidProduct = lpddiW.guidProduct; lpddi->dwDevType = lpddiW.dwDevType; - strcpy(lpddi->tszInstanceName, joydevs[id].name); - strcpy(lpddi->tszProductName, joydevs[id].name); + lstrcpynA(lpddi->tszInstanceName, joydevs[id].name, MAX_PATH); + lstrcpynA(lpddi->tszProductName, joydevs[id].name, MAX_PATH); lpddi->guidFFDriver = lpddiW.guidFFDriver; lpddi->wUsagePage = lpddiW.wUsagePage; lpddi->wUsage = lpddiW.wUsage; @@ -407,7 +422,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS }
if (!((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800)))) return S_FALSE;
@@ -432,7 +447,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS }
if (!((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800)))) return S_FALSE;
@@ -466,6 +481,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig newDevice->generic.base.dinput = dinput; newDevice->generic.joy_polldev = joy_polldev; newDevice->joyfd = -1; + newDevice->joyfd_state = WINE_FD_STATE_CLOSED; newDevice->joydev = &joydevs[index]; newDevice->generic.name = newDevice->joydev->name; list_init(&newDevice->ff_effects); @@ -483,14 +499,18 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig /* Count number of available axes - supported Axis & POVs */ for (i = 0; i < ABS_MAX; i++) { - if (i < WINE_JOYSTICK_MAX_AXES && + if (idx < WINE_JOYSTICK_MAX_AXES && + i < ABS_HAT0X && test_bit(newDevice->joydev->absbits, i)) { newDevice->generic.device_axis_count++; newDevice->dev_axes_to_di[i] = idx; newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum; newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum; - default_axis_map[idx] = i; + if (i >= 8 && i <= 10) /* If it's a wheel axis... */ + default_axis_map[idx] = i - 8; /* ... remap to X/Y/Z */ + else + default_axis_map[idx] = i; idx++; } else @@ -669,38 +689,15 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF return DIERR_DEVICENOTREG; }
- -const struct dinput_device joystick_linuxinput_device = { - "Wine Linux-input joystick driver", - joydev_enum_deviceA, - joydev_enum_deviceW, - joydev_create_device -}; - -/****************************************************************************** - * Acquire : gets exclusive control of the joystick - */ -static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) +static int joydev_open_evdev(JoystickImpl *This) { - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - HRESULT res; + int fd;
- TRACE("(this=%p)\n",This); - - if ((res = IDirectInputDevice2WImpl_Acquire(iface)) != DI_OK) - { - WARN("Failed to acquire: %x\n", res); - return res; - } - - if ((This->joyfd = open(This->joydev->device, O_RDWR)) == -1) + if ((fd = open(This->joydev->device, O_RDWR)) == -1) { - if ((This->joyfd = open(This->joydev->device, O_RDONLY)) == -1) + if ((fd = open(This->joydev->device, O_RDONLY)) == -1) { /* Couldn't open the device at all */ - ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno)); - IDirectInputDevice2WImpl_Unacquire(iface); - return DIERR_NOTFOUND; } else { @@ -715,18 +712,53 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) event.type = EV_FF; event.code = FF_GAIN; event.value = This->ff_gain; - if (write(This->joyfd, &event, sizeof(event)) == -1) + if (write(fd, &event, sizeof(event)) == -1) ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno)); if (!This->ff_autocenter) { /* Disable autocenter. */ event.code = FF_AUTOCENTER; event.value = 0; - if (write(This->joyfd, &event, sizeof(event)) == -1) + if (write(fd, &event, sizeof(event)) == -1) ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno)); } }
+ return fd; +} + + +const struct dinput_device joystick_linuxinput_device = { + "Wine Linux-input joystick driver", + joydev_enum_deviceA, + joydev_enum_deviceW, + joydev_create_device +}; + +/****************************************************************************** + * Acquire : gets exclusive control of the joystick + */ +static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); + HRESULT res; + + TRACE("(this=%p)\n",This); + + if ((res = IDirectInputDevice2WImpl_Acquire(iface)) != DI_OK) + { + WARN("Failed to acquire: %x\n", res); + return res; + } + + if ((This->joyfd = joydev_open_evdev(This)) == -1) + { + ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno)); + IDirectInputDevice2WImpl_Unacquire(iface); + return DIERR_NOTFOUND; + } + + This->joyfd_state = WINE_FD_STATE_OK; return DI_OK; }
@@ -764,6 +796,7 @@ static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
close(This->joyfd); This->joyfd = -1; + This->joyfd_state = WINE_FD_STATE_CLOSED; } return res; } @@ -808,23 +841,79 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface) struct input_event ie; JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
- if (This->joyfd==-1) - return; + if (This->joyfd == -1) + { + int fd; + char namebuf[MAX_PATH + 8]; /* 8 == strlen(EVDEVDRIVER) */ + + if (This->joyfd_state != WINE_FD_STATE_DISCONNECTED) + return; + /* Try to reconnect to the device. */ + fd = joydev_open_evdev(This); + if (fd == -1) + return; + namebuf[sizeof(namebuf) - strlen(EVDEVDRIVER) - 1] = 0; + if (ioctl(fd, EVIOCGNAME(sizeof(namebuf) - strlen(EVDEVDRIVER) - 1), namebuf) == -1) + { + /* Couldn't get the name; assume it's a different device. */ + ERR("EVIOCGNAME(%s) failed: %d %s", This->joydev->device, errno, strerror(errno)); + This->joyfd_state = WINE_FD_STATE_INVALID; + return; + } + strcat(namebuf, EVDEVDRIVER); /* Guaranteed to be safe. */ + if (strcmp(namebuf, This->joydev->name) != 0) + { + ERR("Device %s changed from "%s" to "%s"! Can't reconnect.\n", This->joydev->device, This->joydev->name, namebuf); + This->joyfd_state = WINE_FD_STATE_INVALID; + return; + } + if (InterlockedCompareExchange(&This->joyfd, fd, -1) == -1) + { + This->joyfd_state = WINE_FD_STATE_OK; + TRACE("Reconnected to "%s" on %s", This->joydev->name, This->joydev->device); + } + else + { + /* Somebody beat us to it! Throw away our fd and use theirs. */ + close(fd); + } + }
while (1) { LONG value = 0; int inst_id = -1; + int result;
plfd.fd = This->joyfd; plfd.events = POLLIN;
- if (poll(&plfd,1,0) != 1) - return; + result = poll(&plfd,1,0); + if (result != 1) + { + if (result == -1) + { + ERR("poll failed: %d %s\n", errno, strerror(errno)); + close(This->joyfd); + This->joyfd = -1; + This->joyfd_state = WINE_FD_STATE_DISCONNECTED; + } + return; + }
/* we have one event, so we can read */ - if (sizeof(ie)!=read(This->joyfd,&ie,sizeof(ie))) - return; + result = read(This->joyfd,&ie,sizeof(ie)); + if (result != sizeof(ie)) + { + if (result == -1) + { + ERR("read failed: %d %s\n", errno, strerror(errno)); + close(This->joyfd); + This->joyfd = -1; + This->joyfd_state = WINE_FD_STATE_DISCONNECTED; + } + return; + }
TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value); switch (ie.type) { @@ -836,6 +925,8 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface) if (btn & 0x80) { btn &= 0x7F; + btn = This->generic.button_map[btn]; + inst_id = DIDFT_MAKEINSTANCE(btn) | DIDFT_PSHBUTTON; This->generic.js.rgbButtons[btn] = value = ie.value ? 0x80 : 0x00; } @@ -923,11 +1014,6 @@ static HRESULT WINAPI JoystickWImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
if (IS_DIPROP(rguid)) { switch (LOWORD(rguid)) { - case (DWORD_PTR)DIPROP_CALIBRATIONMODE: { - LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - FIXME("DIPROP_CALIBRATIONMODE(%d)\n", pd->dwData); - break; - } case (DWORD_PTR)DIPROP_AUTOCENTER: { LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
@@ -973,7 +1059,7 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF { JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); _dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK; @@ -1016,6 +1102,29 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF break; }
+ case (DWORD_PTR) DIPROP_GUIDANDPATH: + { + static const WCHAR formatW[] = {'\','\','?','\','h','i','d','#','v','i','d','_','%','0','4','x','&', + 'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0}; + static const WCHAR miW[] = {'m','i',0}; + static const WCHAR igW[] = {'i','g',0}; + + BOOL is_gamepad; + LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; + WORD vid = This->joydev->vendor_id; + WORD pid = This->joydev->product_id; + + if (!pid || !vid) + return DIERR_UNSUPPORTED; + + is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); + pd->guidClass = GUID_DEVCLASS_HIDCLASS; + sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid)); + + TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); + break; + } + default: return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); } diff --git a/dll/directx/wine/dinput/joystick_osx.c b/dll/directx/wine/dinput/joystick_osx.c index 0701b9f42cc..061423afaa0 100644 --- a/dll/directx/wine/dinput/joystick_osx.c +++ b/dll/directx/wine/dinput/joystick_osx.c @@ -85,6 +85,7 @@ #include "winbase.h" #include "winerror.h" #include "winreg.h" +#include "devguid.h" #include "dinput.h"
#include "dinput_private.h" @@ -124,6 +125,11 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W JoystickGenericImpl, base), JoystickImpl, generic); }
+static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This) +{ + return &This->generic.base.IDirectInputDevice8W_iface; +} + typedef struct _EffectImpl { IDirectInputEffect IDirectInputEffect_iface; LONG ref; @@ -801,7 +807,11 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface) TRACE("kIOHIDElementTypeInput_Button\n"); if(button_idx < 128) { - IOHIDDeviceGetValue(hid_device, element, &valueRef); + valueRef = NULL; + if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess) + return; + if (valueRef == NULL) + return; val = IOHIDValueGetIntegerValue(valueRef); newVal = val ? 0x80 : 0x0; oldVal = device->generic.js.rgbButtons[button_idx]; @@ -809,6 +819,8 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface) TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal); if (oldVal != newVal) { + button_idx = device->generic.button_map[button_idx]; + inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON; queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++); } @@ -823,7 +835,11 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface) case kHIDUsage_GD_Hatswitch: { TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n"); - IOHIDDeviceGetValue(hid_device, element, &valueRef); + valueRef = NULL; + if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess) + return; + if (valueRef == NULL) + return; val = IOHIDValueGetIntegerValue(valueRef); oldVal = device->generic.js.rgdwPOV[pov_idx]; if (val >= 8) @@ -850,7 +866,11 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface) { int wine_obj = -1;
- IOHIDDeviceGetValue(hid_device, element, &valueRef); + valueRef = NULL; + if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess) + return; + if (valueRef == NULL) + return; val = IOHIDValueGetIntegerValue(valueRef); newVal = joystick_map_axis(&device->generic.props[idx], val); switch (usage) @@ -945,6 +965,7 @@ static DWORD make_vid_pid(IOHIDDeviceRef device) static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) { IOHIDDeviceRef device; + BOOL is_joystick;
TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
@@ -953,7 +974,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS device = get_device_ref(id);
if ((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { if (dwFlags & DIEDFL_FORCEFEEDBACK) { @@ -962,16 +983,19 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS if(get_ff(device, NULL) != S_OK) return S_FALSE; } + is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick; /* Return joystick */ lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID; lpddi->guidInstance.Data3 = id; - lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID; + lpddi->guidProduct = DInput_PIDVID_Product_GUID; lpddi->guidProduct.Data1 = make_vid_pid(device); - /* we only support traditional joysticks for now */ - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + lpddi->dwDevType = get_device_type(version, is_joystick); + lpddi->dwDevType |= DIDEVTYPE_HID; + lpddi->wUsagePage = 0x01; /* Desktop */ + if (is_joystick) + lpddi->wUsage = 0x04; /* Joystick */ else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + lpddi->wUsage = 0x05; /* Game Pad */ sprintf(lpddi->tszInstanceName, "Joystick %d", id);
/* get the device name */ @@ -989,6 +1013,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS char name[MAX_PATH]; char friendly[32]; IOHIDDeviceRef device; + BOOL is_joystick;
TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
@@ -997,7 +1022,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS device = get_device_ref(id);
if ((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
if (dwFlags & DIEDFL_FORCEFEEDBACK) { @@ -1006,18 +1031,22 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS if(get_ff(device, NULL) != S_OK) return S_FALSE; } + is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick; /* Return joystick */ lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID; lpddi->guidInstance.Data3 = id; - lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID; + lpddi->guidProduct = DInput_PIDVID_Product_GUID; lpddi->guidProduct.Data1 = make_vid_pid(device); - /* we only support traditional joysticks for now */ - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + lpddi->dwDevType = get_device_type(version, is_joystick); + lpddi->dwDevType |= DIDEVTYPE_HID; + lpddi->wUsagePage = 0x01; /* Desktop */ + if (is_joystick) + lpddi->wUsage = 0x04; /* Joystick */ else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + lpddi->wUsage = 0x05; /* Game Pad */ sprintf(friendly, "Joystick %d", id); MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH); + /* get the device name */ get_osx_device_name(id, name, MAX_PATH);
@@ -1082,7 +1111,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID; newDevice->generic.guidInstance.Data3 = index; - newDevice->generic.guidProduct = DInput_Wine_OsX_Joystick_GUID; + newDevice->generic.guidProduct = DInput_PIDVID_Product_GUID; newDevice->generic.guidProduct.Data1 = make_vid_pid(device); newDevice->generic.joy_polldev = poll_osx_device_state;
@@ -1327,6 +1356,53 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF return DIERR_DEVICENOTREG; }
+static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); + + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); + _dump_DIPROPHEADER(pdiph); + + if (!IS_DIPROP(rguid)) return DI_OK; + + switch (LOWORD(rguid)) { + case (DWORD_PTR) DIPROP_GUIDANDPATH: + { + static const WCHAR formatW[] = {'\','\','?','\','h','i','d','#','v','i','d','_','%','0','4','x','&', + 'p','i','d','_','%','0','4','x','&','%','s','_','%','i',0}; + static const WCHAR miW[] = {'m','i',0}; + static const WCHAR igW[] = {'i','g',0}; + + BOOL is_gamepad; + IOHIDDeviceRef device = get_device_ref(This->id); + LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; + WORD vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); + WORD pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); + + if (!pid || !vid) + return DIERR_UNSUPPORTED; + + is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); + pd->guidClass = GUID_DEVCLASS_HIDCLASS; + sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, This->id); + + TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); + break; + } + + default: + return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); + } + + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8A(iface); + return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); +} + static HRESULT osx_set_autocenter(JoystickImpl *This, const DIPROPDWORD *header) { @@ -1418,7 +1494,7 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface, EffectImpl *effect; HRESULT hr;
- TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer); + TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer); dump_DIEFFECT(params, type, 0);
if(!This->ff){ @@ -1459,7 +1535,7 @@ static HRESULT WINAPI JoystickAImpl_CreateEffect(IDirectInputDevice8A *iface, { JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
- TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer); + TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer);
return JoystickWImpl_CreateEffect(&This->generic.base.IDirectInputDevice8W_iface, type, params, out, outer); @@ -1509,7 +1585,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = IDirectInputDevice2AImpl_Release, JoystickAGenericImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, - JoystickAGenericImpl_GetProperty, + JoystickAImpl_GetProperty, JoystickAImpl_SetProperty, IDirectInputDevice2AImpl_Acquire, IDirectInputDevice2AImpl_Unacquire, @@ -1545,7 +1621,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt = IDirectInputDevice2WImpl_Release, JoystickWGenericImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, - JoystickWGenericImpl_GetProperty, + JoystickWImpl_GetProperty, JoystickWImpl_SetProperty, IDirectInputDevice2WImpl_Acquire, IDirectInputDevice2WImpl_Unacquire, diff --git a/dll/directx/wine/dinput/joystick_private.h b/dll/directx/wine/dinput/joystick_private.h index e758cacf6df..545304eabce 100644 --- a/dll/directx/wine/dinput/joystick_private.h +++ b/dll/directx/wine/dinput/joystick_private.h @@ -33,6 +33,9 @@ #define MAX_PROPS 164 struct JoystickGenericImpl;
+/* Number of buttons for which to allow remapping */ +#define MAX_MAP_BUTTONS 32 + typedef void joy_polldev_handler(LPDIRECTINPUTDEVICE8A iface);
typedef struct JoystickGenericImpl @@ -47,6 +50,7 @@ typedef struct JoystickGenericImpl char *name; int device_axis_count; /* Total number of axes in the device */ int *axis_map; /* User axes remapping */ + int button_map[MAX_MAP_BUTTONS]; /* User button remapping */ LONG deadzone; /* Default dead-zone */
joy_polldev_handler *joy_polldev; @@ -96,5 +100,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LP
DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN; void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) DECLSPEC_HIDDEN; +BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) DECLSPEC_HIDDEN;
#endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */ diff --git a/dll/directx/wine/dinput/keyboard.c b/dll/directx/wine/dinput/keyboard.c index 642d0c0beb8..0747f5d8c8b 100644 --- a/dll/directx/wine/dinput/keyboard.c +++ b/dll/directx/wine/dinput/keyboard.c @@ -215,6 +215,9 @@ static HRESULT keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVI if (id != 0) return E_FAIL;
+ if (dwFlags & DIEDFL_FORCEFEEDBACK) + return S_FALSE; + if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) || (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) { @@ -233,6 +236,9 @@ static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVI if (id != 0) return E_FAIL;
+ if (dwFlags & DIEDFL_FORCEFEEDBACK) + return S_FALSE; + if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) || (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) { @@ -520,11 +526,6 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); TRACE("(this=%p,%p)\n", This, pdidi);
- if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) { - WARN(" dinput3 not supported yet...\n"); - return DI_OK; - } - fill_keyboard_dideviceinstanceA(pdidi, This->base.dinput->dwVersion, This->subtype);
return DI_OK; @@ -553,7 +554,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, { SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph); + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); _dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK; @@ -619,7 +620,8 @@ static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifac LPCWSTR lpszUserName, DWORD dwFlags) { - FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); + SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
return _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIKEYBOARD_MASK, &c_dfDIKeyboard); } @@ -659,7 +661,8 @@ static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszUserName, DWORD dwFlags) { - FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); + SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIKeyboard); } @@ -687,6 +690,8 @@ static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
+ lpdiaf->dwCRC = diafW.dwCRC; + HeapFree(GetProcessHeap(), 0, diafW.rgoAction); HeapFree(GetProcessHeap(), 0, lpszUserNameW);
diff --git a/dll/directx/wine/dinput/mouse.c b/dll/directx/wine/dinput/mouse.c index 71333593515..ef408bbad5e 100644 --- a/dll/directx/wine/dinput/mouse.c +++ b/dll/directx/wine/dinput/mouse.c @@ -28,6 +28,7 @@ #include "windef.h" #include "winbase.h" #include "wingdi.h" +#include "wine/winternl.h" #include "winuser.h" #include "winerror.h" #include "winreg.h" @@ -157,6 +158,9 @@ static HRESULT mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI if (id != 0) return E_FAIL;
+ if (dwFlags & DIEDFL_FORCEFEEDBACK) + return S_FALSE; + if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) || (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) { @@ -175,6 +179,9 @@ static HRESULT mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI if (id != 0) return E_FAIL;
+ if (dwFlags & DIEDFL_FORCEFEEDBACK) + return S_FALSE; + if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) || (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) { @@ -211,9 +218,9 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) get_app_key(&hkey, &appkey); if (!get_config_key(hkey, appkey, "MouseWarpOverride", buffer, sizeof(buffer))) { - if (!strcasecmp(buffer, "disable")) + if (!_strnicmp(buffer, "disable", -1)) newDevice->warp_override = WARP_DISABLE; - else if (!strcasecmp(buffer, "force")) + else if (!_strnicmp(buffer, "force", -1)) newDevice->warp_override = WARP_FORCE_ON; } if (appkey) RegCloseKey(appkey); @@ -723,6 +730,9 @@ static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, else if (pdidoi->dwType & DIDFT_BUTTON) wsprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType) - 3);
+ if(pdidoi->dwType & DIDFT_AXIS) + pdidoi->dwFlags |= DIDOI_ASPECTPOSITION; + _dump_OBJECTINSTANCEW(pdidoi); return res; } @@ -758,11 +768,6 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo( SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface); TRACE("(this=%p,%p)\n", This, pdidi);
- if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) { - WARN(" dinput3 not supported yet...\n"); - return DI_OK; - } - fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
return DI_OK; @@ -828,7 +833,8 @@ static HRESULT WINAPI SysMouseWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszUserName, DWORD dwFlags) { - FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); + SysMouseImpl *This = impl_from_IDirectInputDevice8W(iface); + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIMouse2); } @@ -856,6 +862,8 @@ static HRESULT WINAPI SysMouseAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
hr = SysMouseWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
+ lpdiaf->dwCRC = diafW.dwCRC; + HeapFree(GetProcessHeap(), 0, diafW.rgoAction); HeapFree(GetProcessHeap(), 0, lpszUserNameW);
diff --git a/dll/directx/wine/dinput/precomp.h b/dll/directx/wine/dinput/precomp.h index 9504beb6961..d7693306500 100644 --- a/dll/directx/wine/dinput/precomp.h +++ b/dll/directx/wine/dinput/precomp.h @@ -2,8 +2,6 @@ #ifndef __WINE_DINPUT_PRECOMP_H #define __WINE_DINPUT_PRECOMP_H
-#include <wine/config.h> - #define WIN32_NO_STATUS #define _INC_WINDOWS #define COM_NO_WINDOWS_H diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 7fc878f7c5c..4146f4e260d 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -30,7 +30,7 @@ dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-4.0 dll/directx/wine/d3dxof # Synced to WineStaging-3.17 dll/directx/wine/ddraw # Synced to WineStaging-3.3 dll/directx/wine/devenum # Synced to WineStaging-4.18 -dll/directx/wine/dinput # Synced to WineStaging-4.0 +dll/directx/wine/dinput # Synced to WineStaging-4.18 dll/directx/wine/dinput8 # Synced to WineStaging-3.3 dll/directx/wine/dmusic # Synced to WineStaging-4.0 dll/directx/wine/dplay # Synced to WineStaging-3.3