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 --- dlls/winebus.sys/hid.c | 89 +++++++++++++++++++++++++++++++-- dlls/winebus.sys/unix_private.h | 12 +++++ 2 files changed, 98 insertions(+), 3 deletions(-)
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 3e83a05cdf6..46336716a70 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -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 diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 553631e40fb..081e57dc53d 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -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