winebus.sys: Declare multiple HID simple haptics controller collections.

Instead of having the waveforms combined. This better matches what
Windows.Gaming.Input and Windows.Devices.Haptics are exposing, with one
SimpleHapticsController for each motor.

This will also simplify the declaration of left/right trigger motors.

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 2022-03-14 10:29:36 +01:00 committed by Alexandre Julliard
parent 0fb4c0519b
commit e651f56e79
2 changed files with 98 additions and 3 deletions

View File

@ -337,6 +337,11 @@ struct hid_haptics_waveform
BYTE manual_trigger;
BYTE repeat_count;
};
struct hid_haptics_intensity
{
UINT16 rumble_intensity;
UINT16 buzz_intensity;
};
#include "poppack.h"
BOOL hid_device_add_haptics(struct unix_device *iface)
@ -344,7 +349,8 @@ BOOL hid_device_add_haptics(struct unix_device *iface)
struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
const BYTE haptics_features_report = ++desc->next_report_id[HidP_Feature];
const BYTE haptics_waveform_report = ++desc->next_report_id[HidP_Output];
const BYTE haptics_template[] =
const BYTE haptics_intensity_report = ++desc->next_report_id[HidP_Output];
const BYTE waveforms_template[] =
{
USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER),
@ -404,16 +410,75 @@ BOOL hid_device_add_haptics(struct unix_device *iface)
OUTPUT(1, Data|Var|Abs),
END_COLLECTION,
};
const BYTE haptics_template[] =
{
USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER),
COLLECTION(1, Logical),
REPORT_ID(1, haptics_features_report),
USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST),
COLLECTION(1, NamedArray),
USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|3),
REPORT_SIZE(1, 16),
REPORT_COUNT(1, 1),
FEATURE(1, Data|Var|Abs|Null),
END_COLLECTION,
USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST),
COLLECTION(1, NamedArray),
USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|3),
REPORT_SIZE(1, 16),
REPORT_COUNT(1, 1),
FEATURE(1, Data|Var|Abs|Null),
END_COLLECTION,
USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME),
UNIT(2, 0x1001), /* seconds */
UNIT_EXPONENT(1, -3), /* 10^-3 */
LOGICAL_MINIMUM(4, 0x00000000),
LOGICAL_MAXIMUM(4, 0x7fffffff),
REPORT_SIZE(1, 32),
REPORT_COUNT(1, 1),
FEATURE(1, Data|Var|Abs),
/* reset global items */
UNIT(1, 0), /* None */
UNIT_EXPONENT(1, 0),
REPORT_ID(1, haptics_intensity_report),
USAGE(1, HID_USAGE_HAPTICS_INTENSITY),
LOGICAL_MINIMUM(4, 0x00000000),
LOGICAL_MAXIMUM(4, 0x0000ffff),
REPORT_SIZE(1, 16),
REPORT_COUNT(1, 1),
OUTPUT(1, Data|Var|Abs),
END_COLLECTION,
};
iface->hid_haptics.features_report = haptics_features_report;
iface->hid_haptics.waveform_report = haptics_waveform_report;
iface->hid_haptics.intensity_report = haptics_intensity_report;
iface->hid_haptics.features.waveform_list[0] = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE;
iface->hid_haptics.features.waveform_list[1] = HID_USAGE_HAPTICS_WAVEFORM_BUZZ;
iface->hid_haptics.features.duration_list[0] = 0;
iface->hid_haptics.features.duration_list[1] = 0;
iface->hid_haptics.features.waveform_cutoff_time_ms = 1000;
iface->hid_haptics.features.rumble.waveform = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE;
iface->hid_haptics.features.rumble.duration = 0;
iface->hid_haptics.features.rumble.cutoff_time_ms = 1000;
iface->hid_haptics.features.buzz.waveform = HID_USAGE_HAPTICS_WAVEFORM_BUZZ;
iface->hid_haptics.features.buzz.duration = 0;
iface->hid_haptics.features.buzz.cutoff_time_ms = 1000;
return hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template));
if (!hid_report_descriptor_append(desc, waveforms_template, sizeof(waveforms_template)))
return FALSE;
if (!hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template)))
return FALSE;
if (!hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template)))
return FALSE;
return TRUE;
}
#include "pshpack1.h"
@ -1072,7 +1137,23 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC
struct hid_physical *physical = &iface->hid_physical;
struct hid_haptics *haptics = &iface->hid_haptics;
if (packet->reportId == haptics->waveform_report)
if (packet->reportId == haptics->intensity_report)
{
struct hid_haptics_intensity *report = (struct hid_haptics_intensity *)(packet->reportBuffer + 1);
ULONG duration_ms;
io->Information = sizeof(*report) + 1;
assert(packet->reportBufferLen == io->Information);
if (!report->rumble_intensity && !report->buzz_intensity)
io->Status = iface->hid_vtbl->haptics_stop(iface);
else
{
duration_ms = min(haptics->features.rumble.cutoff_time_ms, haptics->features.buzz.cutoff_time_ms);
io->Status = iface->hid_vtbl->haptics_start(iface, duration_ms, report->rumble_intensity, report->buzz_intensity);
}
}
else if (packet->reportId == haptics->waveform_report)
{
struct hid_haptics_waveform *report = (struct hid_haptics_waveform *)(packet->reportBuffer + 1);
UINT16 *rumble_intensity = haptics->waveform_intensity + HAPTICS_WAVEFORM_RUMBLE_ORDINAL;
@ -1307,6 +1388,8 @@ static void hid_device_set_feature_report(struct unix_device *iface, HID_XFER_PA
assert(packet->reportBufferLen == io->Information);
haptics->features.waveform_cutoff_time_ms = features->waveform_cutoff_time_ms;
haptics->features.rumble.cutoff_time_ms = features->rumble.cutoff_time_ms;
haptics->features.buzz.cutoff_time_ms = features->buzz.cutoff_time_ms;
io->Status = STATUS_SUCCESS;
}
else

View File

@ -138,12 +138,23 @@ enum haptics_waveform_ordinal
HAPTICS_WAVEFORM_LAST_ORDINAL = HAPTICS_WAVEFORM_BUZZ_ORDINAL,
};
#include "pshpack1.h"
struct hid_haptics_feature
{
WORD waveform;
WORD duration;
UINT cutoff_time_ms;
};
struct hid_haptics_features
{
WORD waveform_list[HAPTICS_WAVEFORM_LAST_ORDINAL - HAPTICS_WAVEFORM_FIRST_ORDINAL + 1];
WORD duration_list[HAPTICS_WAVEFORM_LAST_ORDINAL - HAPTICS_WAVEFORM_FIRST_ORDINAL + 1];
UINT waveform_cutoff_time_ms;
struct hid_haptics_feature rumble;
struct hid_haptics_feature buzz;
};
#include "poppack.h"
struct hid_haptics
{
@ -151,6 +162,7 @@ struct hid_haptics
UINT16 waveform_intensity[HAPTICS_WAVEFORM_LAST_ORDINAL + 1];
BYTE features_report;
BYTE waveform_report;
BYTE intensity_report;
};
/* must match the order and number of usages in the