dinput: Move HID joystick extra caps to struct dinput_device.

As object properties.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-11-18 09:53:12 +01:00 committed by Alexandre Julliard
parent dee684fbca
commit 1ae1744cb2
3 changed files with 66 additions and 67 deletions

View File

@ -740,6 +740,7 @@ void dinput_device_destroy( IDirectInputDevice8W *iface )
TRACE( "iface %p.\n", iface ); TRACE( "iface %p.\n", iface );
free( This->object_properties );
free( This->data_queue ); free( This->data_queue );
/* Free data format */ /* Free data format */
@ -1940,6 +1941,7 @@ HRESULT dinput_device_init( IDirectInputDevice8W *iface )
size = format->dwNumObjs * sizeof(*format->rgodf); size = format->dwNumObjs * sizeof(*format->rgodf);
if (!(format->rgodf = calloc( 1, size ))) return DIERR_OUTOFMEMORY; if (!(format->rgodf = calloc( 1, size ))) return DIERR_OUTOFMEMORY;
format->dwSize = sizeof(*format); format->dwSize = sizeof(*format);
format->dwObjSize = sizeof(*format->rgodf); format->dwObjSize = sizeof(*format->rgodf);
format->dwFlags = DIDF_ABSAXIS; format->dwFlags = DIDF_ABSAXIS;

View File

@ -57,6 +57,17 @@ struct dinput_device_vtbl
#define DEVICE_STATE_MAX_SIZE 1024 #define DEVICE_STATE_MAX_SIZE 1024
struct object_properties
{
LONG bit_size;
LONG logical_min;
LONG logical_max;
LONG range_min;
LONG range_max;
LONG deadzone;
LONG saturation;
};
/* Device implementation */ /* Device implementation */
struct dinput_device struct dinput_device
{ {
@ -100,6 +111,7 @@ struct dinput_device
BOOL autocenter; BOOL autocenter;
LONG device_gain; LONG device_gain;
struct object_properties *object_properties;
}; };
extern HRESULT dinput_device_alloc( SIZE_T size, const struct dinput_device_vtbl *vtbl, const GUID *guid, extern HRESULT dinput_device_alloc( SIZE_T size, const struct dinput_device_vtbl *vtbl, const GUID *guid,

View File

@ -52,17 +52,6 @@ DEFINE_GUID( GUID_DEVINTERFACE_WINEXINPUT,0x6c53d5fd,0x6480,0x440f,0xb6,0x18,0x4
DEFINE_GUID( hid_joystick_guid, 0x9e573edb, 0x7734, 0x11d2, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7 ); DEFINE_GUID( hid_joystick_guid, 0x9e573edb, 0x7734, 0x11d2, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7 );
DEFINE_DEVPROPKEY( DEVPROPKEY_HID_HANDLE, 0xbc62e415, 0xf4fe, 0x405c, 0x8e, 0xda, 0x63, 0x6f, 0xb5, 0x9f, 0x08, 0x98, 2 ); DEFINE_DEVPROPKEY( DEVPROPKEY_HID_HANDLE, 0xbc62e415, 0xf4fe, 0x405c, 0x8e, 0xda, 0x63, 0x6f, 0xb5, 0x9f, 0x08, 0x98, 2 );
struct extra_caps
{
LONG bit_size;
LONG logical_min;
LONG logical_max;
LONG range_min;
LONG range_max;
LONG deadzone;
LONG saturation;
};
struct pid_control_report struct pid_control_report
{ {
BYTE id; BYTE id;
@ -156,8 +145,6 @@ struct hid_joystick
HIDD_ATTRIBUTES attrs; HIDD_ATTRIBUTES attrs;
HIDP_CAPS caps; HIDP_CAPS caps;
struct extra_caps *input_extra_caps;
char *input_report_buf; char *input_report_buf;
char *output_report_buf; char *output_report_buf;
USAGE_AND_PAGE *usages_buf; USAGE_AND_PAGE *usages_buf;
@ -715,7 +702,6 @@ static void hid_joystick_release( IDirectInputDevice8W *iface )
free( impl->usages_buf ); free( impl->usages_buf );
free( impl->output_report_buf ); free( impl->output_report_buf );
free( impl->input_report_buf ); free( impl->input_report_buf );
free( impl->input_extra_caps );
HidD_FreePreparsedData( impl->preparsed ); HidD_FreePreparsedData( impl->preparsed );
CloseHandle( impl->base.read_event ); CloseHandle( impl->base.read_event );
CloseHandle( impl->device ); CloseHandle( impl->device );
@ -727,29 +713,29 @@ static HRESULT hid_joystick_get_property( IDirectInputDevice8W *iface, DWORD pro
DIPROPHEADER *header, DIDEVICEOBJECTINSTANCEW *instance ) DIPROPHEADER *header, DIDEVICEOBJECTINSTANCEW *instance )
{ {
struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
struct extra_caps *extra = NULL; struct object_properties *properties = NULL;
if (instance) extra = impl->input_extra_caps + instance->dwOfs / sizeof(LONG); if (instance) properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG);
switch (property) switch (property)
{ {
case (DWORD_PTR)DIPROP_RANGE: case (DWORD_PTR)DIPROP_RANGE:
{ {
DIPROPRANGE *value = (DIPROPRANGE *)header; DIPROPRANGE *value = (DIPROPRANGE *)header;
value->lMin = extra->range_min; value->lMin = properties->range_min;
value->lMax = extra->range_max; value->lMax = properties->range_max;
return DI_OK; return DI_OK;
} }
case (DWORD_PTR)DIPROP_DEADZONE: case (DWORD_PTR)DIPROP_DEADZONE:
{ {
DIPROPDWORD *value = (DIPROPDWORD *)header; DIPROPDWORD *value = (DIPROPDWORD *)header;
value->dwData = extra->deadzone; value->dwData = properties->deadzone;
return DI_OK; return DI_OK;
} }
case (DWORD_PTR)DIPROP_SATURATION: case (DWORD_PTR)DIPROP_SATURATION:
{ {
DIPROPDWORD *value = (DIPROPDWORD *)header; DIPROPDWORD *value = (DIPROPDWORD *)header;
value->dwData = extra->saturation; value->dwData = properties->saturation;
return DI_OK; return DI_OK;
} }
case (DWORD_PTR)DIPROP_GRANULARITY: case (DWORD_PTR)DIPROP_GRANULARITY:
@ -797,22 +783,22 @@ static HRESULT hid_joystick_get_property( IDirectInputDevice8W *iface, DWORD pro
static void set_extra_caps_range( struct hid_joystick *impl, const DIDEVICEOBJECTINSTANCEW *instance, static void set_extra_caps_range( struct hid_joystick *impl, const DIDEVICEOBJECTINSTANCEW *instance,
LONG min, LONG max ) LONG min, LONG max )
{ {
struct extra_caps *extra = impl->input_extra_caps + instance->dwOfs / sizeof(LONG); struct object_properties *properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG);
LONG tmp; LONG tmp;
extra->range_min = min; properties->range_min = min;
extra->range_max = max; properties->range_max = max;
if (instance->dwType & DIDFT_AXIS) if (instance->dwType & DIDFT_AXIS)
{ {
if (!extra->range_min) tmp = extra->range_max / 2; if (!properties->range_min) tmp = properties->range_max / 2;
else tmp = round( (extra->range_min + extra->range_max) / 2.0 ); else tmp = round( (properties->range_min + properties->range_max) / 2.0 );
*(LONG *)(impl->base.device_state + instance->dwOfs) = tmp; *(LONG *)(impl->base.device_state + instance->dwOfs) = tmp;
} }
else if (instance->dwType & DIDFT_POV) else if (instance->dwType & DIDFT_POV)
{ {
tmp = extra->logical_max - extra->logical_min; tmp = properties->logical_max - properties->logical_min;
if (tmp > 0) extra->range_max -= max / (tmp + 1); if (tmp > 0) properties->range_max -= max / (tmp + 1);
*(LONG *)(impl->base.device_state + instance->dwOfs) = -1; *(LONG *)(impl->base.device_state + instance->dwOfs) = -1;
} }
} }
@ -842,9 +828,9 @@ static HRESULT hid_joystick_set_property( IDirectInputDevice8W *iface, DWORD pro
const DIPROPHEADER *header, const DIDEVICEOBJECTINSTANCEW *instance ) const DIPROPHEADER *header, const DIDEVICEOBJECTINSTANCEW *instance )
{ {
struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
struct extra_caps *extra = NULL; struct object_properties *properties = NULL;
if (instance) extra = impl->input_extra_caps + instance->dwOfs / sizeof(LONG); if (instance) properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG);
switch (property) switch (property)
{ {
@ -857,13 +843,13 @@ static HRESULT hid_joystick_set_property( IDirectInputDevice8W *iface, DWORD pro
case (DWORD_PTR)DIPROP_DEADZONE: case (DWORD_PTR)DIPROP_DEADZONE:
{ {
const DIPROPDWORD *value = (const DIPROPDWORD *)header; const DIPROPDWORD *value = (const DIPROPDWORD *)header;
extra->deadzone = value->dwData; properties->deadzone = value->dwData;
return DI_OK; return DI_OK;
} }
case (DWORD_PTR)DIPROP_SATURATION: case (DWORD_PTR)DIPROP_SATURATION:
{ {
const DIPROPDWORD *value = (const DIPROPDWORD *)header; const DIPROPDWORD *value = (const DIPROPDWORD *)header;
extra->saturation = value->dwData; properties->saturation = value->dwData;
return DI_OK; return DI_OK;
} }
} }
@ -1124,34 +1110,34 @@ static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_val
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
static LONG sign_extend( ULONG value, struct extra_caps *caps ) static LONG sign_extend( ULONG value, struct object_properties *properties )
{ {
UINT sign = 1 << (caps->bit_size - 1); UINT sign = 1 << (properties->bit_size - 1);
if (sign <= 1 || caps->logical_min >= 0) return value; if (sign <= 1 || properties->logical_min >= 0) return value;
return value - ((value & sign) << 1); return value - ((value & sign) << 1);
} }
static LONG scale_value( ULONG value, struct extra_caps *caps ) static LONG scale_value( ULONG value, struct object_properties *properties )
{ {
LONG tmp = sign_extend( value, caps ), log_min, log_max, phy_min, phy_max; LONG tmp = sign_extend( value, properties ), log_min, log_max, phy_min, phy_max;
log_min = caps->logical_min; log_min = properties->logical_min;
log_max = caps->logical_max; log_max = properties->logical_max;
phy_min = caps->range_min; phy_min = properties->range_min;
phy_max = caps->range_max; phy_max = properties->range_max;
if (log_min > tmp || log_max < tmp) return -1; /* invalid / null value */ if (log_min > tmp || log_max < tmp) return -1; /* invalid / null value */
return phy_min + MulDiv( tmp - log_min, phy_max - phy_min, log_max - log_min ); return phy_min + MulDiv( tmp - log_min, phy_max - phy_min, log_max - log_min );
} }
static LONG scale_axis_value( ULONG value, struct extra_caps *caps ) static LONG scale_axis_value( ULONG value, struct object_properties *properties )
{ {
LONG tmp = sign_extend( value, caps ), log_ctr, log_min, log_max, phy_ctr, phy_min, phy_max; LONG tmp = sign_extend( value, properties ), log_ctr, log_min, log_max, phy_ctr, phy_min, phy_max;
ULONG bit_max = (1 << caps->bit_size) - 1; ULONG bit_max = (1 << properties->bit_size) - 1;
log_min = caps->logical_min; log_min = properties->logical_min;
log_max = caps->logical_max; log_max = properties->logical_max;
phy_min = caps->range_min; phy_min = properties->range_min;
phy_max = caps->range_max; phy_max = properties->range_max;
/* xinput HID gamepad have bogus logical value range, let's use the bit range instead */ /* xinput HID gamepad have bogus logical value range, let's use the bit range instead */
if (log_min == 0 && log_max == -1) log_max = bit_max; if (log_min == 0 && log_max == -1) log_max = bit_max;
@ -1163,14 +1149,14 @@ static LONG scale_axis_value( ULONG value, struct extra_caps *caps )
tmp -= log_ctr; tmp -= log_ctr;
if (tmp <= 0) if (tmp <= 0)
{ {
log_max = MulDiv( log_min - log_ctr, caps->deadzone, 10000 ); log_max = MulDiv( log_min - log_ctr, properties->deadzone, 10000 );
log_min = MulDiv( log_min - log_ctr, caps->saturation, 10000 ); log_min = MulDiv( log_min - log_ctr, properties->saturation, 10000 );
phy_max = phy_ctr; phy_max = phy_ctr;
} }
else else
{ {
log_min = MulDiv( log_max - log_ctr, caps->deadzone, 10000 ); log_min = MulDiv( log_max - log_ctr, properties->deadzone, 10000 );
log_max = MulDiv( log_max - log_ctr, caps->saturation, 10000 ); log_max = MulDiv( log_max - log_ctr, properties->saturation, 10000 );
phy_min = phy_ctr; phy_min = phy_ctr;
} }
@ -1182,7 +1168,7 @@ static LONG scale_axis_value( ULONG value, struct extra_caps *caps )
static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value_caps *caps, static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value_caps *caps,
DIDEVICEOBJECTINSTANCEW *instance, void *data ) DIDEVICEOBJECTINSTANCEW *instance, void *data )
{ {
struct extra_caps *extra = impl->input_extra_caps + instance->dwOfs / sizeof(LONG); struct object_properties *properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG);
IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface; IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface;
ULONG logical_value, report_len = impl->caps.InputReportByteLength; ULONG logical_value, report_len = impl->caps.InputReportByteLength;
struct parse_device_state_params *params = data; struct parse_device_state_params *params = data;
@ -1196,8 +1182,8 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value
&logical_value, impl->preparsed, report_buf, report_len ); &logical_value, impl->preparsed, report_buf, report_len );
if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_GetUsageValue %04x:%04x returned %#x\n", if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_GetUsageValue %04x:%04x returned %#x\n",
instance->wUsagePage, instance->wUsage, status ); instance->wUsagePage, instance->wUsage, status );
if (instance->dwType & DIDFT_AXIS) value = scale_axis_value( logical_value, extra ); if (instance->dwType & DIDFT_AXIS) value = scale_axis_value( logical_value, properties );
else value = scale_value( logical_value, extra ); else value = scale_value( logical_value, properties );
old_value = *(LONG *)(params->old_state + instance->dwOfs); old_value = *(LONG *)(params->old_state + instance->dwOfs);
*(LONG *)(impl->base.device_state + instance->dwOfs) = value; *(LONG *)(impl->base.device_state + instance->dwOfs) = value;
@ -1578,16 +1564,16 @@ HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *in
return DI_OK; return DI_OK;
} }
static BOOL init_extra_caps( struct hid_joystick *impl, struct hid_value_caps *caps, static BOOL init_object_properties( struct hid_joystick *impl, struct hid_value_caps *caps,
DIDEVICEOBJECTINSTANCEW *instance, void *data ) DIDEVICEOBJECTINSTANCEW *instance, void *data )
{ {
struct extra_caps *extra = impl->input_extra_caps + instance->dwOfs / sizeof(LONG); struct object_properties *properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG);
LONG range_max = (instance->dwType & DIDFT_AXIS) ? 65535 : 36000; LONG range_max = (instance->dwType & DIDFT_AXIS) ? 65535 : 36000;
extra->bit_size = caps->bit_size; properties->bit_size = caps->bit_size;
extra->logical_min = caps->logical_min; properties->logical_min = caps->logical_min;
extra->logical_max = caps->logical_max; properties->logical_max = caps->logical_max;
set_extra_caps_range( impl, instance, 0, range_max ); set_extra_caps_range( impl, instance, 0, range_max );
extra->saturation = 10000; properties->saturation = 10000;
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
@ -1870,9 +1856,9 @@ HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID *guid,
}, },
}; };
HIDD_ATTRIBUTES attrs = {.Size = sizeof(attrs)}; HIDD_ATTRIBUTES attrs = {.Size = sizeof(attrs)};
struct object_properties *object_properties;
struct hid_preparsed_data *preparsed; struct hid_preparsed_data *preparsed;
struct hid_joystick *impl = NULL; struct hid_joystick *impl = NULL;
struct extra_caps *extra;
USAGE_AND_PAGE *usages; USAGE_AND_PAGE *usages;
char *buffer; char *buffer;
HRESULT hr; HRESULT hr;
@ -1907,11 +1893,10 @@ HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID *guid,
list_init( &impl->effect_list ); list_init( &impl->effect_list );
preparsed = (struct hid_preparsed_data *)impl->preparsed; preparsed = (struct hid_preparsed_data *)impl->preparsed;
size = preparsed->input_caps_count * sizeof(struct object_properties);
size = preparsed->input_caps_count * sizeof(struct extra_caps); if (!(object_properties = calloc( 1, size ))) goto failed;
if (!(extra = calloc( 1, size ))) goto failed; impl->base.object_properties = object_properties;
impl->input_extra_caps = extra; enum_objects( impl, &filter, DIDFT_AXIS | DIDFT_POV, init_object_properties, NULL );
enum_objects( impl, &filter, DIDFT_AXIS | DIDFT_POV, init_extra_caps, NULL );
size = impl->caps.InputReportByteLength; size = impl->caps.InputReportByteLength;
if (!(buffer = malloc( size ))) goto failed; if (!(buffer = malloc( size ))) goto failed;