Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device.c | 229 +++++++++++++---------------------- dlls/dinput/device_private.h | 4 - dlls/dinput/joystick_hid.c | 21 ++-- dlls/dinput8/tests/hid.c | 1 - 4 files changed, 99 insertions(+), 156 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 6601d705462..ed9bdee98ea 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -334,73 +334,9 @@ BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL *override ) return disable; }
-/* Conversion between internal data buffer and external data buffer */ -static void fill_DataFormat( void *out, DWORD size, const void *in, const DataFormat *df ) -{ - int i; - const char *in_c = in; - char *out_c = out; - - memset(out, 0, size); - for (i = 0; i < df->size; i++) { - if (df->dt[i].offset_in >= 0) { - switch (df->dt[i].size) { - case 1: - TRACE("Copying (c) to %d from %d (value %d)\n", - df->dt[i].offset_out, df->dt[i].offset_in, *(in_c + df->dt[i].offset_in)); - *(out_c + df->dt[i].offset_out) = *(in_c + df->dt[i].offset_in); - break; - - case 2: - TRACE("Copying (s) to %d from %d (value %d)\n", - df->dt[i].offset_out, df->dt[i].offset_in, *((const short *)(in_c + df->dt[i].offset_in))); - *((short *)(out_c + df->dt[i].offset_out)) = *((const short *)(in_c + df->dt[i].offset_in)); - break; - - case 4: - TRACE("Copying (i) to %d from %d (value %d)\n", - df->dt[i].offset_out, df->dt[i].offset_in, *((const int *)(in_c + df->dt[i].offset_in))); - *((int *)(out_c + df->dt[i].offset_out)) = *((const int *)(in_c + df->dt[i].offset_in)); - break; - - default: - memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size); - break; - } - } else { - switch (df->dt[i].size) { - case 1: - TRACE("Copying (c) to %d default value %d\n", - df->dt[i].offset_out, df->dt[i].value); - *(out_c + df->dt[i].offset_out) = (char) df->dt[i].value; - break; - - case 2: - TRACE("Copying (s) to %d default value %d\n", - df->dt[i].offset_out, df->dt[i].value); - *((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value; - break; - - case 4: - TRACE("Copying (i) to %d default value %d\n", - df->dt[i].offset_out, df->dt[i].value); - *((int *) (out_c + df->dt[i].offset_out)) = df->dt[i].value; - break; - - default: - memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size); - break; - } - } - } -} - static void dinput_device_release_user_format( struct dinput_device *impl ) { - free( impl->data_format.dt ); - impl->data_format.dt = NULL; - free( impl->data_format.offsets ); - impl->data_format.offsets = NULL; + if (impl->user_format) free( impl->user_format->rgodf ); free( impl->user_format ); impl->user_format = NULL; } @@ -436,33 +372,35 @@ LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD
static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const DIDATAFORMAT *asked_format ) { + DIOBJECTDATAFORMAT *device_obj, *user_obj; DataFormat *format = &impl->data_format; - DataTransform *dt; + DIDATAFORMAT *user_format = NULL; unsigned int i, j; int *done; - int index = 0; - DWORD next = 0;
if (!format->wine_df) return DIERR_INVALIDPARAM; done = calloc( asked_format->dwNumObjs, sizeof(int) ); - dt = malloc( asked_format->dwNumObjs * sizeof(DataTransform) ); - if (!dt || !done) goto failed; + if (!done) goto failed;
- if (!(format->offsets = malloc( format->wine_df->dwNumObjs * sizeof(int) ))) goto failed; - if (!(impl->user_format = malloc( asked_format->dwSize ))) goto failed; - memcpy( impl->user_format, asked_format, asked_format->dwSize ); + if (!(user_format = malloc( sizeof(DIDATAFORMAT) ))) goto failed; + *user_format = *format->wine_df; + user_format->dwFlags = asked_format->dwFlags; + user_format->dwDataSize = asked_format->dwDataSize; + user_format->dwNumObjs += asked_format->dwNumObjs; + if (!(user_format->rgodf = calloc( user_format->dwNumObjs, sizeof(DIOBJECTDATAFORMAT) ))) goto failed;
TRACE("Creating DataTransform :\n");
for (i = 0; i < format->wine_df->dwNumObjs; i++) { - format->offsets[i] = -1; + device_obj = format->wine_df->rgodf + i; + user_obj = user_format->rgodf + i;
- for (j = 0; j < asked_format->dwNumObjs; j++) { - if (done[j] == 1) - continue; - - if (/* Check if the application either requests any GUID and if not, it if matches + for (j = 0; j < asked_format->dwNumObjs; j++) + { + if (done[j] == 1) continue; + + if (/* Check if the application either requests any GUID and if not, it if matches * the GUID of the Wine object. */ ((asked_format->rgodf[j].pguid == NULL) || @@ -501,26 +439,19 @@ static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const TRACE(" "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n"); TRACE(" * dwFlags: 0x%08x\n", format->wine_df->rgodf[i].dwFlags); TRACE(" "); _dump_ObjectDataFormat_flags(format->wine_df->rgodf[i].dwFlags); TRACE("\n"); - - if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON) - dt[index].size = sizeof(BYTE); - else - dt[index].size = sizeof(DWORD); - dt[index].offset_in = format->wine_df->rgodf[i].dwOfs; - dt[index].offset_out = asked_format->rgodf[j].dwOfs; - format->offsets[i] = asked_format->rgodf[j].dwOfs; - dt[index].value = 0; - next = next + dt[index].size;
- index++; - break; - } - } + *user_obj = *device_obj; + user_obj->dwOfs = asked_format->rgodf[j].dwOfs; + break; + } + } }
TRACE("Setting to default value :\n"); for (j = 0; j < asked_format->dwNumObjs; j++) { - if (done[j] == 0) { + user_obj = user_format->rgodf + format->wine_df->dwNumObjs + j; + + if (done[j] == 0) { TRACE(" - Asked (%d) :\n", j); TRACE(" * GUID: %s ('%s')\n", debugstr_guid(asked_format->rgodf[j].pguid), @@ -534,55 +465,40 @@ static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const if (!(asked_format->rgodf[j].dwType & DIDFT_POV)) continue; /* fill_DataFormat memsets the buffer to 0 */
- if (asked_format->rgodf[j].dwType & DIDFT_BUTTON) - dt[index].size = sizeof(BYTE); - else - dt[index].size = sizeof(DWORD); - dt[index].offset_in = -1; - dt[index].offset_out = asked_format->rgodf[j].dwOfs; - dt[index].value = -1; - index++; - } + *user_obj = asked_format->rgodf[j]; + } }
- format->size = index; - format->dt = dt; - free( done );
+ impl->user_format = user_format; return DI_OK;
failed: free( done ); - free( dt ); - format->dt = NULL; - free( format->offsets ); - format->offsets = NULL; - free( impl->user_format ); - impl->user_format = NULL; + if (user_format) free( user_format->rgodf ); + free( user_format );
return DIERR_OUTOFMEMORY; }
-static int id_to_object( LPCDIDATAFORMAT df, int id ) +static int id_to_offset( struct dinput_device *impl, int id ) { - int i; + DIDATAFORMAT *device_format = impl->data_format.wine_df, *user_format = impl->user_format; + DIOBJECTDATAFORMAT *user_obj;
- id &= 0x00ffffff; - for (i = 0; i < df->dwNumObjs; i++) - if ((dataformat_to_odf(df, i)->dwType & 0x00ffffff) == id) - return i; + if (!user_format) return -1; + + user_obj = user_format->rgodf + device_format->dwNumObjs; + while (user_obj-- > user_format->rgodf) + { + if (!user_obj->dwType) continue; + if ((user_obj->dwType & 0x00ffffff) == (id & 0x00ffffff)) return user_obj->dwOfs; + }
return -1; }
-static int id_to_offset(const DataFormat *df, int id) -{ - int obj = id_to_object(df->wine_df, id); - - return obj >= 0 && df->offsets ? df->offsets[obj] : -1; -} - static DWORD semantic_to_obj_id( struct dinput_device *This, DWORD dwSemantic ) { DWORD type = (0x0000ff00 & dwSemantic) >> 8; @@ -769,7 +685,7 @@ void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD ti { static ULONGLONG notify_ms = 0; struct dinput_device *This = impl_from_IDirectInputDevice8W( iface ); - int next_pos, ofs = id_to_offset(&This->data_format, inst_id); + int next_pos, ofs = id_to_offset( This, inst_id ); ULONGLONG time_ms = GetTickCount64();
if (time_ms - notify_ms > 1000) @@ -1138,19 +1054,25 @@ static HRESULT WINAPI dinput_device_EnumObjects( IDirectInputDevice8W *iface,
static HRESULT enum_object_filter_init( struct dinput_device *impl, DIPROPHEADER *filter ) { - DIDATAFORMAT *format = impl->data_format.wine_df; - int i, *offsets = impl->data_format.offsets; + DIDATAFORMAT *device_format = impl->data_format.wine_df, *user_format = impl->user_format; + DIOBJECTDATAFORMAT *device_obj, *user_obj;
if (filter->dwHow > DIPH_BYUSAGE) return DIERR_INVALIDPARAM; if (filter->dwHow == DIPH_BYUSAGE && !(impl->instance.dwDevType & DIDEVTYPE_HID)) return DIERR_UNSUPPORTED; if (filter->dwHow != DIPH_BYOFFSET) return DI_OK;
- if (!offsets) return DIERR_NOTFOUND; + if (!impl->user_format) return DIERR_NOTFOUND;
- for (i = 0; i < format->dwNumObjs; ++i) if (offsets[i] == filter->dwObj) break; - if (i == format->dwNumObjs) return DIERR_NOTFOUND; + user_obj = user_format->rgodf + device_format->dwNumObjs; + device_obj = device_format->rgodf + device_format->dwNumObjs; + while (user_obj-- > user_format->rgodf && device_obj-- > device_format->rgodf) + { + if (!user_obj->dwType) continue; + if (user_obj->dwOfs == filter->dwObj) break; + } + if (user_obj < user_format->rgodf) return DIERR_NOTFOUND;
- filter->dwObj = format->rgodf[i].dwOfs; + filter->dwObj = device_obj->dwOfs; return DI_OK; }
@@ -1397,7 +1319,7 @@ static HRESULT WINAPI dinput_device_SetProperty( IDirectInputDevice8W *iface, co hr = impl->vtbl->enum_objects( iface, &filter, object_mask, find_object, &instance ); if (FAILED(hr)) return hr; if (hr == DIENUM_CONTINUE) return DIERR_OBJECTNOTFOUND; - if ((user_offset = id_to_offset( &impl->data_format, instance.dwType )) < 0) return DIERR_OBJECTNOTFOUND; + if ((user_offset = id_to_offset( impl, instance.dwType )) < 0) return DIERR_OBJECTNOTFOUND; if (!set_app_data( impl, user_offset, value->uData )) return DIERR_OUTOFMEMORY; return DI_OK; } @@ -1469,15 +1391,12 @@ static HRESULT WINAPI dinput_device_GetObjectInfo( IDirectInputDevice8W *iface, return DI_OK; }
-static BOOL CALLBACK reset_axis_data( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) -{ - *(ULONG *)((char *)data + instance->dwOfs) = 0; - return DIENUM_CONTINUE; -} - static HRESULT WINAPI dinput_device_GetDeviceState( IDirectInputDevice8W *iface, DWORD size, void *data ) { struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); + DIDATAFORMAT *device_format = impl->data_format.wine_df, *user_format; + DIOBJECTDATAFORMAT *device_obj, *user_obj; + BYTE *user_state = data; DIPROPHEADER filter = { .dwSize = sizeof(filter), @@ -1496,13 +1415,37 @@ static HRESULT WINAPI dinput_device_GetDeviceState( IDirectInputDevice8W *iface, EnterCriticalSection( &impl->crit ); if (!impl->acquired) hr = DIERR_NOTACQUIRED; - else if (size != impl->user_format->dwDataSize) + else if (!(user_format = impl->user_format)) + hr = DIERR_INVALIDPARAM; + else if (size != user_format->dwDataSize) hr = DIERR_INVALIDPARAM; else { - fill_DataFormat( data, size, impl->device_state, &impl->data_format ); - if (!(impl->user_format->dwFlags & DIDF_ABSAXIS)) - impl->vtbl->enum_objects( iface, &filter, DIDFT_RELAXIS, reset_axis_data, impl->device_state ); + memset( user_state, 0, size ); + + user_obj = user_format->rgodf + device_format->dwNumObjs; + device_obj = device_format->rgodf + device_format->dwNumObjs; + while (user_obj-- > user_format->rgodf && device_obj-- > device_format->rgodf) + { + if (user_obj->dwType & DIDFT_BUTTON) + user_state[user_obj->dwOfs] = impl->device_state[device_obj->dwOfs]; + } + + /* reset optional POVs to their default */ + user_obj = user_format->rgodf + user_format->dwNumObjs; + while (user_obj-- > user_format->rgodf + device_format->dwNumObjs) + if (user_obj->dwType & DIDFT_POV) *(ULONG *)(user_state + user_obj->dwOfs) = 0xffffffff; + + user_obj = user_format->rgodf + device_format->dwNumObjs; + device_obj = device_format->rgodf + device_format->dwNumObjs; + while (user_obj-- > user_format->rgodf && device_obj-- > device_format->rgodf) + { + if (user_obj->dwType & (DIDFT_POV | DIDFT_AXIS)) + *(ULONG *)(user_state + user_obj->dwOfs) = *(ULONG *)(impl->device_state + device_obj->dwOfs); + if (!(user_format->dwFlags & DIDF_ABSAXIS) && (device_obj->dwType & DIDFT_RELAXIS)) + *(ULONG *)(impl->device_state + device_obj->dwOfs) = 0; + } + hr = DI_OK; } LeaveCriticalSection( &impl->crit ); diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 1b81a374058..3f07a3a0f8a 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -38,10 +38,6 @@ typedef struct
typedef struct { - int size; - DataTransform *dt; - - int *offsets; /* object offsets */ LPDIDATAFORMAT wine_df; /* wine internal data format */ } DataFormat;
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 3a8c7213ebc..13d71a270b6 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2009,16 +2009,21 @@ static BOOL get_parameters_object_id( struct hid_joystick *impl, struct hid_valu static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_value_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - DIDATAFORMAT *format = impl->base.data_format.wine_df; - int *offsets = impl->base.data_format.offsets; - ULONG i; + DIDATAFORMAT *device_format = impl->base.data_format.wine_df, *user_format = impl->base.user_format; + DIOBJECTDATAFORMAT *device_obj, *user_obj;
- if (!offsets) return DIENUM_CONTINUE; - for (i = 0; i < format->dwNumObjs; ++i) - if (format->rgodf[i].dwOfs == instance->dwOfs) break; - if (i == format->dwNumObjs) return DIENUM_CONTINUE; - *(DWORD *)data = offsets[i]; + if (!user_format) return DIENUM_CONTINUE;
+ user_obj = user_format->rgodf + device_format->dwNumObjs; + device_obj = device_format->rgodf + device_format->dwNumObjs; + while (user_obj-- > user_format->rgodf && device_obj-- > device_format->rgodf) + { + if (!user_obj->dwType) continue; + if (device_obj->dwType == instance->dwType) break; + } + if (user_obj < user_format->rgodf) return DIENUM_CONTINUE; + + *(DWORD *)data = user_obj->dwOfs; return DIENUM_STOP; }
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 2f2efbe09e3..dab6ea4478e 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -4539,7 +4539,6 @@ static void test_simple_joystick(void)
hr = IDirectInputDevice8_GetDeviceState( device, dataformat.dwDataSize, buffer ); ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr ); - todo_wine ok( ((ULONG *)buffer)[0] == 0x512b, "got %#x, expected %#x\n", ((ULONG *)buffer)[0], 0x512b ); ok( ((ULONG *)buffer)[1] == 0, "got %#x, expected %#x\n", ((ULONG *)buffer)[1], 0 ); ok( ((ULONG *)buffer)[2] == 0x7fff, "got %#x, expected %#x\n", ((ULONG *)buffer)[2], 0x7fff );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device.c | 282 +++++++---------------------------- dlls/dinput/device_private.h | 8 - dlls/dinput8/tests/hid.c | 5 - 3 files changed, 56 insertions(+), 239 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index ed9bdee98ea..1eed223f51c 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -107,138 +107,6 @@ static void _dump_cooperativelevel_DI(DWORD dwFlags) { } }
-static void _dump_ObjectDataFormat_flags(DWORD dwFlags) { - unsigned int i; - static const struct { - DWORD mask; - const char *name; - } flags[] = { -#define FE(x) { x, #x} - FE(DIDOI_FFACTUATOR), - FE(DIDOI_FFEFFECTTRIGGER), - FE(DIDOI_POLLED), - FE(DIDOI_GUIDISUSAGE) -#undef FE - }; - - if (!dwFlags) return; - - TRACE("Flags:"); - - /* First the flags */ - for (i = 0; i < ARRAY_SIZE(flags); i++) { - if (flags[i].mask & dwFlags) - TRACE(" %s",flags[i].name); - } - - /* Now specific values */ -#define FE(x) case x: TRACE(" "#x); break - switch (dwFlags & DIDOI_ASPECTMASK) { - FE(DIDOI_ASPECTACCEL); - FE(DIDOI_ASPECTFORCE); - FE(DIDOI_ASPECTPOSITION); - FE(DIDOI_ASPECTVELOCITY); - } -#undef FE - -} - -static void _dump_EnumObjects_flags(DWORD dwFlags) { - if (TRACE_ON(dinput)) { - unsigned int i; - DWORD type, instance; - static const struct { - DWORD mask; - const char *name; - } flags[] = { -#define FE(x) { x, #x} - FE(DIDFT_RELAXIS), - FE(DIDFT_ABSAXIS), - FE(DIDFT_PSHBUTTON), - FE(DIDFT_TGLBUTTON), - FE(DIDFT_POV), - FE(DIDFT_COLLECTION), - FE(DIDFT_NODATA), - FE(DIDFT_FFACTUATOR), - FE(DIDFT_FFEFFECTTRIGGER), - FE(DIDFT_OUTPUT), - FE(DIDFT_VENDORDEFINED), - FE(DIDFT_ALIAS), - FE(DIDFT_OPTIONAL) -#undef FE - }; - type = (dwFlags & 0xFF0000FF); - instance = ((dwFlags >> 8) & 0xFFFF); - TRACE("Type:"); - if (type == DIDFT_ALL) { - TRACE(" DIDFT_ALL"); - } else { - for (i = 0; i < ARRAY_SIZE(flags); i++) { - if (flags[i].mask & type) { - type &= ~flags[i].mask; - TRACE(" %s",flags[i].name); - } - } - if (type) { - TRACE(" (unhandled: %08x)", type); - } - } - TRACE(" / Instance: "); - if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) { - TRACE("DIDFT_ANYINSTANCE"); - } else { - TRACE("%3d", instance); - } - } -} - -/* This function is a helper to convert a GUID into any possible DInput GUID out there */ -static const char *_dump_dinput_GUID( const GUID *guid ) -{ - unsigned int i; - static const struct { - const GUID *guid; - const char *name; - } guids[] = { -#define FE(x) { &x, #x} - FE(GUID_XAxis), - FE(GUID_YAxis), - FE(GUID_ZAxis), - FE(GUID_RxAxis), - FE(GUID_RyAxis), - FE(GUID_RzAxis), - FE(GUID_Slider), - FE(GUID_Button), - FE(GUID_Key), - FE(GUID_POV), - FE(GUID_Unknown), - FE(GUID_SysMouse), - FE(GUID_SysKeyboard), - FE(GUID_Joystick), - FE(GUID_ConstantForce), - FE(GUID_RampForce), - FE(GUID_Square), - FE(GUID_Sine), - FE(GUID_Triangle), - FE(GUID_SawtoothUp), - FE(GUID_SawtoothDown), - FE(GUID_Spring), - FE(GUID_Damper), - FE(GUID_Inertia), - FE(GUID_Friction), - FE(GUID_CustomForce) -#undef FE - }; - if (guid == NULL) - return "null GUID"; - for (i = 0; i < ARRAY_SIZE(guids); i++) { - if (IsEqualGUID(guids[i].guid, guid)) { - return guids[i].name; - } - } - return debugstr_guid(guid); -} - /****************************************************************************** * Get the default and the app-specific config keys. */ @@ -370,116 +238,78 @@ LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD return NULL; }
-static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const DIDATAFORMAT *asked_format ) +static BOOL match_device_object( DIDATAFORMAT *device_format, DIDATAFORMAT *user_format, + const DIDATAFORMAT *format, const DIOBJECTDATAFORMAT *match_obj ) { + DWORD i, device_instance, instance = DIDFT_GETINSTANCE( match_obj->dwType ); DIOBJECTDATAFORMAT *device_obj, *user_obj; - DataFormat *format = &impl->data_format; - DIDATAFORMAT *user_format = NULL; - unsigned int i, j; - int *done;
- if (!format->wine_df) return DIERR_INVALIDPARAM; - done = calloc( asked_format->dwNumObjs, sizeof(int) ); - if (!done) goto failed; - - if (!(user_format = malloc( sizeof(DIDATAFORMAT) ))) goto failed; - *user_format = *format->wine_df; - user_format->dwFlags = asked_format->dwFlags; - user_format->dwDataSize = asked_format->dwDataSize; - user_format->dwNumObjs += asked_format->dwNumObjs; - if (!(user_format->rgodf = calloc( user_format->dwNumObjs, sizeof(DIOBJECTDATAFORMAT) ))) goto failed; - - TRACE("Creating DataTransform :\n"); - - for (i = 0; i < format->wine_df->dwNumObjs; i++) + for (i = 0; i < device_format->dwNumObjs; i++) { - device_obj = format->wine_df->rgodf + i; user_obj = user_format->rgodf + i; + device_obj = device_format->rgodf + i; + device_instance = DIDFT_GETINSTANCE( device_obj->dwType );
- for (j = 0; j < asked_format->dwNumObjs; j++) + if (!(user_obj->dwType & DIDFT_OPTIONAL)) continue; /* already matched */ + if (match_obj->pguid && device_obj->pguid && !IsEqualGUID( device_obj->pguid, match_obj->pguid )) continue; + if (instance != DIDFT_GETINSTANCE( DIDFT_ANYINSTANCE ) && instance != device_instance) continue; + if (!(DIDFT_GETTYPE( match_obj->dwType ) & DIDFT_GETTYPE( device_obj->dwType ))) continue; + + TRACE( "match %s with device %s\n", debugstr_diobjectdataformat( match_obj ), + debugstr_diobjectdataformat( device_obj ) ); + + *user_obj = *device_obj; + user_obj->dwOfs = match_obj->dwOfs; + return TRUE; + } + + return FALSE; +} + +static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const DIDATAFORMAT *format ) +{ + DIDATAFORMAT *user_format, *device_format = impl->data_format.wine_df; + DIOBJECTDATAFORMAT *user_obj, *match_obj; + DWORD i; + + if (!device_format) return DIERR_INVALIDPARAM; + if (!(user_format = malloc( sizeof(DIDATAFORMAT) ))) return DIERR_OUTOFMEMORY; + *user_format = *device_format; + user_format->dwFlags = format->dwFlags; + user_format->dwDataSize = format->dwDataSize; + user_format->dwNumObjs += format->dwNumObjs; + if (!(user_format->rgodf = calloc( user_format->dwNumObjs, sizeof(DIOBJECTDATAFORMAT) ))) + { + free( user_format ); + return DIERR_OUTOFMEMORY; + } + + user_obj = user_format->rgodf + user_format->dwNumObjs; + while (user_obj-- > user_format->rgodf) user_obj->dwType |= DIDFT_OPTIONAL; + + for (i = 0; i < format->dwNumObjs; ++i) + { + match_obj = format->rgodf + i; + + if (!match_device_object( device_format, user_format, format, match_obj )) { - if (done[j] == 1) continue; - - if (/* Check if the application either requests any GUID and if not, it if matches - * the GUID of the Wine object. - */ - ((asked_format->rgodf[j].pguid == NULL) || - (format->wine_df->rgodf[i].pguid == NULL) || - (IsEqualGUID(format->wine_df->rgodf[i].pguid, asked_format->rgodf[j].pguid))) - && - (/* Then check if it accepts any instance id, and if not, if it matches Wine's - * instance id. - */ - ((asked_format->rgodf[j].dwType & DIDFT_INSTANCEMASK) == DIDFT_ANYINSTANCE) || - (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == 0x00FF) || /* This is mentioned in no DX docs, but it works fine - tested on WinXP */ - (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == DIDFT_GETINSTANCE(format->wine_df->rgodf[i].dwType))) - && - ( /* Then if the asked type matches the one Wine provides */ - DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType)) - { - done[j] = 1; - - TRACE("Matching :\n"); - TRACE(" - Asked (%d) :\n", j); - TRACE(" * GUID: %s ('%s')\n", - debugstr_guid(asked_format->rgodf[j].pguid), - _dump_dinput_GUID(asked_format->rgodf[j].pguid)); - TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs); - TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType); - TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n"); - TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags); - TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n"); - - TRACE(" - Wine (%d) :\n", i); - TRACE(" * GUID: %s ('%s')\n", - debugstr_guid(format->wine_df->rgodf[i].pguid), - _dump_dinput_GUID(format->wine_df->rgodf[i].pguid)); - TRACE(" * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs); - TRACE(" * dwType: 0x%08x\n", format->wine_df->rgodf[i].dwType); - TRACE(" "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n"); - TRACE(" * dwFlags: 0x%08x\n", format->wine_df->rgodf[i].dwFlags); - TRACE(" "); _dump_ObjectDataFormat_flags(format->wine_df->rgodf[i].dwFlags); TRACE("\n"); - - *user_obj = *device_obj; - user_obj->dwOfs = asked_format->rgodf[j].dwOfs; - break; - } + WARN( "object %s not found\n", debugstr_diobjectdataformat( match_obj ) ); + if (!(match_obj->dwType & DIDFT_OPTIONAL)) goto failed; + user_obj = user_format->rgodf + device_format->dwNumObjs + i; + *user_obj = *match_obj; } }
- TRACE("Setting to default value :\n"); - for (j = 0; j < asked_format->dwNumObjs; j++) { - user_obj = user_format->rgodf + format->wine_df->dwNumObjs + j; - - if (done[j] == 0) { - TRACE(" - Asked (%d) :\n", j); - TRACE(" * GUID: %s ('%s')\n", - debugstr_guid(asked_format->rgodf[j].pguid), - _dump_dinput_GUID(asked_format->rgodf[j].pguid)); - TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs); - TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType); - TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n"); - TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags); - TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n"); - - if (!(asked_format->rgodf[j].dwType & DIDFT_POV)) - continue; /* fill_DataFormat memsets the buffer to 0 */ - - *user_obj = asked_format->rgodf[j]; - } - } - - free( done ); + user_obj = user_format->rgodf + user_format->dwNumObjs; + while (user_obj-- > user_format->rgodf) user_obj->dwType &= ~DIDFT_OPTIONAL;
impl->user_format = user_format; return DI_OK;
failed: - free( done ); - if (user_format) free( user_format->rgodf ); + free( user_format->rgodf ); free( user_format ); - - return DIERR_OUTOFMEMORY; + return DIERR_INVALIDPARAM; }
static int id_to_offset( struct dinput_device *impl, int id ) diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 3f07a3a0f8a..190e2c16ffe 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -28,14 +28,6 @@ #include "wine/list.h" #include "dinput_private.h"
-typedef struct -{ - int size; - int offset_in; - int offset_out; - int value; -} DataTransform; - typedef struct { LPDIDATAFORMAT wine_df; /* wine internal data format */ diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index dab6ea4478e..c6d01b8bee7 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -4475,26 +4475,21 @@ static void test_simple_joystick(void) objdataformat[3].dwType = 0xff|DIDFT_ANYINSTANCE; objdataformat[3].dwFlags = 0; hr = IDirectInputDevice8_SetDataFormat( device, &dataformat ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr ); objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 12 ); hr = IDirectInputDevice8_SetDataFormat( device, &dataformat ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr ); objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0xff ); hr = IDirectInputDevice8_SetDataFormat( device, &dataformat ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr ); objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 1 ); hr = IDirectInputDevice8_SetDataFormat( device, &dataformat ); ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr ); objdataformat[1].pguid = &GUID_RzAxis; hr = IDirectInputDevice8_SetDataFormat( device, &dataformat ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr ); objdataformat[1].pguid = &GUID_Unknown; hr = IDirectInputDevice8_SetDataFormat( device, &dataformat ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr ); objdataformat[1].pguid = &GUID_YAxis; hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device.c | 26 +++++++++++++------------- dlls/dinput/device_private.h | 7 +------ dlls/dinput/joystick_hid.c | 4 ++-- 3 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 1eed223f51c..d375229e2c0 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -268,7 +268,7 @@ static BOOL match_device_object( DIDATAFORMAT *device_format, DIDATAFORMAT *user
static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const DIDATAFORMAT *format ) { - DIDATAFORMAT *user_format, *device_format = impl->data_format.wine_df; + DIDATAFORMAT *user_format, *device_format = impl->device_format; DIOBJECTDATAFORMAT *user_obj, *match_obj; DWORD i;
@@ -314,7 +314,7 @@ failed:
static int id_to_offset( struct dinput_device *impl, int id ) { - DIDATAFORMAT *device_format = impl->data_format.wine_df, *user_format = impl->user_format; + DIDATAFORMAT *device_format = impl->device_format, *user_format = impl->user_format; DIOBJECTDATAFORMAT *user_obj;
if (!user_format) return -1; @@ -338,9 +338,9 @@ static DWORD semantic_to_obj_id( struct dinput_device *This, DWORD dwSemantic ) DWORD instance; int i;
- for (i = 0; i < This->data_format.wine_df->dwNumObjs && !found; i++) + for (i = 0; i < This->device_format->dwNumObjs && !found; i++) { - LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i); + LPDIOBJECTDATAFORMAT odf = dataformat_to_odf( This->device_format, i );
if (byofs && value != odf->dwOfs) continue; if (!byofs && value != DIDFT_GETINSTANCE(odf->dwType)) continue; @@ -747,8 +747,8 @@ void dinput_device_destroy( IDirectInputDevice8W *iface ) free( This->data_queue );
/* Free data format */ - free( This->data_format.wine_df->rgodf ); - free( This->data_format.wine_df ); + free( This->device_format->rgodf ); + free( This->device_format ); dinput_device_release_user_format( This );
/* Free action mapping */ @@ -884,7 +884,7 @@ static HRESULT WINAPI dinput_device_EnumObjects( IDirectInputDevice8W *iface,
static HRESULT enum_object_filter_init( struct dinput_device *impl, DIPROPHEADER *filter ) { - DIDATAFORMAT *device_format = impl->data_format.wine_df, *user_format = impl->user_format; + DIDATAFORMAT *device_format = impl->device_format, *user_format = impl->user_format; DIOBJECTDATAFORMAT *device_obj, *user_obj;
if (filter->dwHow > DIPH_BYUSAGE) return DIERR_INVALIDPARAM; @@ -1224,7 +1224,7 @@ static HRESULT WINAPI dinput_device_GetObjectInfo( IDirectInputDevice8W *iface, static HRESULT WINAPI dinput_device_GetDeviceState( IDirectInputDevice8W *iface, DWORD size, void *data ) { struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); - DIDATAFORMAT *device_format = impl->data_format.wine_df, *user_format; + DIDATAFORMAT *device_format = impl->device_format, *user_format; DIOBJECTDATAFORMAT *device_obj, *user_obj; BYTE *user_state = data; DIPROPHEADER filter = @@ -1595,7 +1595,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, break; default: devMask = DIGENRE_ANY; - df = impl->data_format.wine_df; + df = impl->device_format; break; }
@@ -1684,7 +1684,7 @@ static HRESULT WINAPI dinput_device_SetActionMap( IDirectInputDevice8W *iface, D df = &c_dfDIMouse2; break; default: - df = impl->data_format.wine_df; + df = impl->device_format; break; }
@@ -1843,7 +1843,7 @@ HRESULT dinput_device_alloc( SIZE_T size, const struct dinput_device_vtbl *vtbl, This->instance.dwSize = sizeof(DIDEVICEINSTANCEW); This->caps.dwSize = sizeof(DIDEVCAPS); This->caps.dwFlags = DIDC_ATTACHED | DIDC_EMULATED; - This->data_format.wine_df = format; + This->device_format = format; InitializeCriticalSection( &This->crit ); This->dinput = dinput; IDirectInput_AddRef( &dinput->IDirectInput7A_iface ); @@ -1871,7 +1871,7 @@ static const GUID *object_instance_guid( const DIDEVICEOBJECTINSTANCEW *instance static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) { struct dinput_device *impl = impl_from_IDirectInputDevice8W( data ); - DIDATAFORMAT *format = impl->data_format.wine_df; + DIDATAFORMAT *format = impl->device_format; DIOBJECTDATAFORMAT *obj_format;
if (!format->rgodf) @@ -1904,7 +1904,7 @@ static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, HRESULT dinput_device_init( IDirectInputDevice8W *iface ) { struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface ); - DIDATAFORMAT *format = impl->data_format.wine_df; + DIDATAFORMAT *format = impl->device_format; ULONG i, size;
IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL ); diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 190e2c16ffe..e77d0190a48 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -28,11 +28,6 @@ #include "wine/list.h" #include "dinput_private.h"
-typedef struct -{ - LPDIDATAFORMAT wine_df; /* wine internal data format */ -} DataFormat; - typedef struct { unsigned int offset; @@ -88,7 +83,7 @@ struct dinput_device BOOL overflow; /* return DI_BUFFEROVERFLOW in 'GetDeviceData' */ DWORD buffersize; /* size of the queue - set in 'SetProperty' */
- DataFormat data_format; /* user data format and wine to user format converter */ + DIDATAFORMAT *device_format; DIDATAFORMAT *user_format;
/* Action mapping */ diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 13d71a270b6..d7e64af9928 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -1115,7 +1115,7 @@ static HRESULT hid_joystick_read( IDirectInputDevice8W *iface ) }; struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); ULONG i, count, report_len = impl->caps.InputReportByteLength; - DIDATAFORMAT *format = impl->base.data_format.wine_df; + DIDATAFORMAT *format = impl->base.device_format; struct parse_device_state_params params = {{0}}; char *report_buf = impl->input_report_buf; USAGE_AND_PAGE *usages; @@ -2009,7 +2009,7 @@ static BOOL get_parameters_object_id( struct hid_joystick *impl, struct hid_valu static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_value_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data ) { - DIDATAFORMAT *device_format = impl->base.data_format.wine_df, *user_format = impl->base.user_format; + DIDATAFORMAT *device_format = impl->base.device_format, *user_format = impl->base.user_format; DIOBJECTDATAFORMAT *device_obj, *user_obj;
if (!user_format) return DIENUM_CONTINUE;