[DINPUT] Sync with Wine Staging 4.18. CORE-16441

This commit is contained in:
Amine Khaldi 2019-10-26 13:03:34 +01:00
parent 1477b2deb7
commit 41c8c312e1
16 changed files with 1001 additions and 376 deletions

View file

@ -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)

View file

@ -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)
{
DIDevicesData *data = (DIDevicesData*) pvRef;
data->ndevices++;
return DIENUM_CONTINUE;
}
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];
device->lpdid = lpdid;
device->ddi = *lpddi;
ConfigureDevicesData *data = (ConfigureDevicesData*) pvRef;
DeviceData *device;
int i, j;
IDirectInputDevice_AddRef(lpdid);
/* 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;
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)
{
DWORD i;
for (i=0; i < from->dwNumActions; 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;
}
}
static void reset_actions(HWND dialog)
{
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
LPDIACTIONFORMATW to = data->lpdiaf, from = data->original_lpdiaf;
DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
unsigned i, j;
copy_actions(to, from);
for (i = 0; i < data->devices_data.ndevices; i++)
{
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 save_actions(HWND dialog) {
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
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;
}

View file

@ -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,8 +941,40 @@ 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);
HeapFree(GetProcessHeap(), 0, obj_df);
@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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)

View file

@ -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);

View file

@ -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", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, 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;

View file

@ -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)
{

View file

@ -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,6 +689,44 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
return DIERR_DEVICENOTREG;
}
static int joydev_open_evdev(JoystickImpl *This)
{
int fd;
if ((fd = open(This->joydev->device, O_RDWR)) == -1)
{
if ((fd = open(This->joydev->device, O_RDONLY)) == -1)
{
/* Couldn't open the device at all */
}
else
{
/* Couldn't open in r/w but opened in read-only. */
WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device);
}
}
else
{
struct input_event event;
event.type = EV_FF;
event.code = FF_GAIN;
event.value = This->ff_gain;
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(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",
@ -693,40 +751,14 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
return res;
}
if ((This->joyfd = open(This->joydev->device, O_RDWR)) == -1)
if ((This->joyfd = joydev_open_evdev(This)) == -1)
{
if ((This->joyfd = 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
{
/* Couldn't open in r/w but opened in read-only. */
WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device);
}
}
else
{
struct input_event event;
event.type = EV_FF;
event.code = FF_GAIN;
event.value = This->ff_gain;
if (write(This->joyfd, &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)
ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno));
}
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);
}

View file

@ -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,

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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