[PATCH 3/6] dinput: Introduce new direct_input_device_init helper.
Rémi Bernon
rbernon at codeweavers.com
Fri Oct 15 04:57:41 CDT 2021
To initialize the device data format by enumerating its objects.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/device.c | 93 ++++++++++++++++++++++++++++++++++++
dlls/dinput/device_private.h | 6 +++
dlls/dinput/joystick_hid.c | 89 +++++-----------------------------
3 files changed, 112 insertions(+), 76 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index e2d2e551d02..03c10c7360f 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -35,6 +35,7 @@
#include "winerror.h"
#include "dinput.h"
#include "dinputd.h"
+#include "hidusage.h"
#include "initguid.h"
#include "device_private.h"
@@ -1821,3 +1822,95 @@ HRESULT direct_input_device_alloc( SIZE_T size, const IDirectInputDevice8WVtbl *
*out = This;
return DI_OK;
}
+
+static const GUID *object_instance_guid( const DIDEVICEOBJECTINSTANCEW *instance )
+{
+ switch (instance->wUsagePage)
+ {
+ case HID_USAGE_PAGE_BUTTON: return &GUID_Button;
+ case HID_USAGE_PAGE_GENERIC:
+ switch (instance->wUsage)
+ {
+ case HID_USAGE_GENERIC_X: return &GUID_XAxis;
+ case HID_USAGE_GENERIC_Y: return &GUID_YAxis;
+ case HID_USAGE_GENERIC_Z: return &GUID_ZAxis;
+ case HID_USAGE_GENERIC_WHEEL: return &GUID_ZAxis;
+ case HID_USAGE_GENERIC_RX: return &GUID_RxAxis;
+ case HID_USAGE_GENERIC_RY: return &GUID_RyAxis;
+ case HID_USAGE_GENERIC_RZ: return &GUID_RzAxis;
+ case HID_USAGE_GENERIC_SLIDER: return &GUID_Slider;
+ case HID_USAGE_GENERIC_HATSWITCH: return &GUID_POV;
+ }
+ break;
+ }
+
+ if (IsEqualGUID( &instance->guidType, &GUID_XAxis )) return &GUID_XAxis;
+ if (IsEqualGUID( &instance->guidType, &GUID_YAxis )) return &GUID_YAxis;
+ if (IsEqualGUID( &instance->guidType, &GUID_ZAxis )) return &GUID_ZAxis;
+ if (IsEqualGUID( &instance->guidType, &GUID_RxAxis )) return &GUID_RxAxis;
+ if (IsEqualGUID( &instance->guidType, &GUID_RyAxis )) return &GUID_RyAxis;
+ if (IsEqualGUID( &instance->guidType, &GUID_RzAxis )) return &GUID_RzAxis;
+ if (IsEqualGUID( &instance->guidType, &GUID_Slider )) return &GUID_Slider;
+ if (IsEqualGUID( &instance->guidType, &GUID_Button )) return &GUID_Button;
+ if (IsEqualGUID( &instance->guidType, &GUID_Key )) return &GUID_Key;
+ if (IsEqualGUID( &instance->guidType, &GUID_POV )) return &GUID_POV;
+
+ return &GUID_Unknown;
+}
+
+static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, void *data )
+{
+ IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( data );
+ DIDATAFORMAT *format = impl->data_format.wine_df;
+ DIOBJECTDATAFORMAT *obj_format;
+
+ if (!format->rgodf)
+ {
+ format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) );
+ if (instance->dwType & DIDFT_BUTTON) impl->caps.dwButtons++;
+ if (instance->dwType & DIDFT_AXIS) impl->caps.dwAxes++;
+ if (instance->dwType & DIDFT_POV) impl->caps.dwPOVs++;
+ if (instance->dwType & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV))
+ {
+ if (!impl->device_state_report_id)
+ impl->device_state_report_id = instance->wReportId;
+ else if (impl->device_state_report_id != instance->wReportId)
+ FIXME( "multiple device state reports found!\n" );
+ }
+ }
+ else
+ {
+ obj_format = format->rgodf + format->dwNumObjs;
+ obj_format->pguid = object_instance_guid( instance );
+ obj_format->dwOfs = instance->dwOfs;
+ obj_format->dwType = instance->dwType;
+ obj_format->dwFlags = instance->dwFlags;
+ }
+
+ format->dwNumObjs++;
+ return DIENUM_CONTINUE;
+}
+
+HRESULT direct_input_device_init( IDirectInputDevice8W *iface )
+{
+ IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( iface );
+ DIDATAFORMAT *format = impl->data_format.wine_df;
+ ULONG size;
+
+ IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL );
+ if (format->dwDataSize > DEVICE_STATE_MAX_SIZE)
+ {
+ FIXME( "unable to create device, state is too large\n" );
+ return DIERR_OUTOFMEMORY;
+ }
+
+ size = format->dwNumObjs * sizeof(*format->rgodf);
+ if (!(format->rgodf = calloc( 1, size ))) return DIERR_OUTOFMEMORY;
+ format->dwSize = sizeof(*format);
+ format->dwObjSize = sizeof(*format->rgodf);
+ format->dwFlags = DIDF_ABSAXIS;
+ format->dwNumObjs = 0;
+ IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL );
+
+ return DI_OK;
+}
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 7ae040744cb..43629abdb15 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -62,6 +62,8 @@ struct dinput_device_vtbl
HRESULT (*unacquire)(IDirectInputDevice8W *);
};
+#define DEVICE_STATE_MAX_SIZE 1024
+
/* Device implementation */
typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
struct IDirectInputDeviceImpl
@@ -99,10 +101,14 @@ struct IDirectInputDeviceImpl
/* internal device callbacks */
HANDLE read_event;
const struct dinput_device_vtbl *vtbl;
+
+ BYTE device_state_report_id;
+ BYTE device_state[DEVICE_STATE_MAX_SIZE];
};
extern HRESULT direct_input_device_alloc( SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const struct dinput_device_vtbl *internal_vtbl,
const GUID *guid, IDirectInputImpl *dinput, void **out ) DECLSPEC_HIDDEN;
+extern HRESULT direct_input_device_init( IDirectInputDevice8W *iface );
extern const IDirectInputDevice8AVtbl dinput_device_a_vtbl DECLSPEC_HIDDEN;
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 03005964c67..b6eeb772fcf 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -150,8 +150,6 @@ struct pid_set_ramp_force
struct hid_value_caps *end_caps;
};
-#define DEVICE_STATE_MAX_SIZE 1024
-
struct hid_joystick
{
IDirectInputDeviceImpl base;
@@ -172,9 +170,6 @@ struct hid_joystick
USAGE_AND_PAGE *usages_buf;
ULONG usages_count;
- BYTE device_state_report_id;
- BYTE device_state[DEVICE_STATE_MAX_SIZE];
-
BYTE effect_inuse[255];
struct list effect_list;
struct pid_control_report pid_device_control;
@@ -856,13 +851,13 @@ static BOOL set_property_prop_range( struct hid_joystick *impl, struct hid_value
{
if (!caps->physical_min) tmp = caps->physical_max / 2;
else tmp = round( (caps->physical_min + caps->physical_max) / 2.0 );
- *(LONG *)(impl->device_state + instance->dwOfs) = tmp;
+ *(LONG *)(impl->base.device_state + instance->dwOfs) = tmp;
}
else if (instance->dwType & DIDFT_POV)
{
tmp = caps->logical_max - caps->logical_min;
if (tmp > 0) caps->physical_max -= value->lMax / (tmp + 1);
- *(LONG *)(impl->device_state + instance->dwOfs) = -1;
+ *(LONG *)(impl->base.device_state + instance->dwOfs) = -1;
}
return DIENUM_CONTINUE;
}
@@ -1009,7 +1004,7 @@ static HRESULT WINAPI hid_joystick_GetDeviceState( IDirectInputDevice8W *iface,
EnterCriticalSection( &impl->base.crit );
if (!impl->base.acquired) hr = DIERR_NOTACQUIRED;
- else fill_DataFormat( ptr, len, impl->device_state, &impl->base.data_format );
+ else fill_DataFormat( ptr, len, impl->base.device_state, &impl->base.data_format );
LeaveCriticalSection( &impl->base.crit );
return hr;
@@ -1445,11 +1440,11 @@ static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_val
struct parse_device_state_params *params = data;
BYTE old_value, value;
- if (instance->wReportId != impl->device_state_report_id) return DIENUM_CONTINUE;
+ if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
value = params->buttons[instance->wUsage - 1];
old_value = params->old_state[instance->dwOfs];
- impl->device_state[instance->dwOfs] = value;
+ impl->base.device_state[instance->dwOfs] = value;
if (old_value != value)
queue_event( iface, instance->dwType, value, params->time, params->seq );
@@ -1518,7 +1513,7 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value
LONG old_value, value;
NTSTATUS status;
- if (instance->wReportId != impl->device_state_report_id) return DIENUM_CONTINUE;
+ if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
extra = impl->input_extra_caps + (caps - HID_INPUT_VALUE_CAPS( preparsed ));
status = HidP_GetUsageValue( HidP_Input, instance->wUsagePage, 0, instance->wUsage,
@@ -1529,7 +1524,7 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value
else value = scale_value( logical_value, caps, caps->physical_min, caps->physical_max );
old_value = *(LONG *)(params->old_state + instance->dwOfs);
- *(LONG *)(impl->device_state + instance->dwOfs) = value;
+ *(LONG *)(impl->base.device_state + instance->dwOfs) = value;
if (old_value != value)
queue_event( iface, instance->dwType, value, params->time, params->seq );
@@ -1579,12 +1574,12 @@ static HRESULT hid_joystick_internal_read( IDirectInputDevice8W *iface )
impl->preparsed, report_buf, report_len );
if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_GetUsagesEx returned %#x\n", status );
- if (report_buf[0] == impl->device_state_report_id)
+ if (report_buf[0] == impl->base.device_state_report_id)
{
params.time = GetCurrentTime();
params.seq = impl->base.dinput->evsequence++;
- memcpy( params.old_state, impl->device_state, format->dwDataSize );
- memset( impl->device_state, 0, format->dwDataSize );
+ memcpy( params.old_state, impl->base.device_state, format->dwDataSize );
+ memset( impl->base.device_state, 0, format->dwDataSize );
while (count--)
{
@@ -1599,7 +1594,7 @@ static HRESULT hid_joystick_internal_read( IDirectInputDevice8W *iface )
enum_objects( impl, &filter, DIDFT_AXIS | DIDFT_POV, read_device_state_value, ¶ms );
enum_objects( impl, &filter, DIDFT_BUTTON, check_device_state_button, ¶ms );
- if (impl->base.hEvent && memcmp( ¶ms.old_state, impl->device_state, format->dwDataSize ))
+ if (impl->base.hEvent && memcmp( ¶ms.old_state, impl->base.device_state, format->dwDataSize ))
SetEvent( impl->base.hEvent );
}
@@ -1884,47 +1879,6 @@ static HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTAN
return DI_OK;
}
-static BOOL init_objects( struct hid_joystick *impl, struct hid_value_caps *caps,
- DIDEVICEOBJECTINSTANCEW *instance, void *data )
-{
- DIDATAFORMAT *format = impl->base.data_format.wine_df;
-
- format->dwNumObjs++;
- format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) );
- if (instance->dwType & DIDFT_BUTTON) impl->base.caps.dwButtons++;
- if (instance->dwType & DIDFT_AXIS) impl->base.caps.dwAxes++;
- if (instance->dwType & DIDFT_POV) impl->base.caps.dwPOVs++;
-
- if (instance->dwType & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV) &&
- (instance->wUsagePage == HID_USAGE_PAGE_GENERIC ||
- instance->wUsagePage == HID_USAGE_PAGE_BUTTON))
- {
- if (!impl->device_state_report_id)
- impl->device_state_report_id = instance->wReportId;
- else if (impl->device_state_report_id != instance->wReportId)
- FIXME( "multiple device state reports found!\n" );
- }
-
- return DIENUM_CONTINUE;
-}
-
-static BOOL init_data_format( struct hid_joystick *impl, struct hid_value_caps *caps,
- DIDEVICEOBJECTINSTANCEW *instance, void *data )
-{
- DIDATAFORMAT *format = impl->base.data_format.wine_df;
- DIOBJECTDATAFORMAT *obj_format;
- DWORD *index = data;
-
- obj_format = format->rgodf + *index;
- obj_format->pguid = object_usage_to_guid( instance->wUsagePage, instance->wUsage );
- obj_format->dwOfs = instance->dwOfs;
- obj_format->dwType = instance->dwType;
- obj_format->dwFlags = instance->dwFlags;
- (*index)++;
-
- return DIENUM_CONTINUE;
-}
-
static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *caps,
DIDEVICEOBJECTINSTANCEW *instance, void *data )
{
@@ -2203,11 +2157,10 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
struct hid_preparsed_data *preparsed;
struct hid_joystick *impl = NULL;
struct extra_caps *extra;
- DIDATAFORMAT *format = NULL;
USAGE_AND_PAGE *usages;
- DWORD size, index;
char *buffer;
HRESULT hr;
+ DWORD size;
TRACE( "dinput %p, guid %s, out %p\n", dinput, debugstr_guid( guid ), out );
@@ -2255,7 +2208,6 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
if (!(usages = malloc( size ))) goto failed;
impl->usages_buf = usages;
- enum_objects( impl, &filter, DIDFT_ALL, init_objects, NULL );
enum_objects( impl, &filter, DIDFT_COLLECTION, init_pid_reports, NULL );
enum_objects( impl, &filter, DIDFT_NODATA, init_pid_caps, NULL );
@@ -2296,23 +2248,8 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
impl->base.caps.dwFFDriverVersion = 1;
}
- format = impl->base.data_format.wine_df;
- if (format->dwDataSize > DEVICE_STATE_MAX_SIZE)
- {
- FIXME( "unable to create device, state is too large\n" );
+ if (FAILED(hr = direct_input_device_init( &impl->base.IDirectInputDevice8W_iface )))
goto failed;
- }
-
- size = format->dwNumObjs * sizeof(*format->rgodf);
- if (!(format->rgodf = calloc( 1, size ))) goto failed;
- format->dwSize = sizeof(*format);
- format->dwObjSize = sizeof(*format->rgodf);
- format->dwFlags = DIDF_ABSAXIS;
-
- index = 0;
- enum_objects( impl, &filter, DIDFT_ALL, init_data_format, &index );
-
- _dump_DIDATAFORMAT( impl->base.data_format.wine_df );
range.lMax = 65535;
enum_objects( impl, &range.diph, DIDFT_AXIS, set_property_prop_range, &range );
--
2.33.0
More information about the wine-devel
mailing list