[PATCH 06/11] winebus.sys: Add a PID set condition output report.

Rémi Bernon rbernon at codeweavers.com
Fri Oct 8 02:50:24 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winebus.sys/bus_sdl.c      | 30 ++++++++++-
 dlls/winebus.sys/bus_udev.c     | 23 ++++++++-
 dlls/winebus.sys/hid.c          | 91 +++++++++++++++++++++++++++++++++
 dlls/winebus.sys/unix_private.h | 13 +++++
 4 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 78de600fda6..36efd5cc850 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -208,6 +208,10 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
         if (impl->effect_support & SDL_HAPTIC_TRIANGLE) usages[count++] = PID_USAGE_ET_TRIANGLE;
         if (impl->effect_support & SDL_HAPTIC_SAWTOOTHUP) usages[count++] = PID_USAGE_ET_SAWTOOTH_UP;
         if (impl->effect_support & SDL_HAPTIC_SAWTOOTHDOWN) usages[count++] = PID_USAGE_ET_SAWTOOTH_DOWN;
+        if (impl->effect_support & SDL_HAPTIC_SPRING) usages[count++] = PID_USAGE_ET_SPRING;
+        if (impl->effect_support & SDL_HAPTIC_DAMPER) usages[count++] = PID_USAGE_ET_DAMPER;
+        if (impl->effect_support & SDL_HAPTIC_INERTIA) usages[count++] = PID_USAGE_ET_INERTIA;
+        if (impl->effect_support & SDL_HAPTIC_FRICTION) usages[count++] = PID_USAGE_ET_FRICTION;
 
         if (!hid_device_add_physical(&impl->unix_device, usages, count))
             return FALSE;
@@ -562,7 +566,31 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT
     case PID_USAGE_ET_DAMPER:
     case PID_USAGE_ET_INERTIA:
     case PID_USAGE_ET_FRICTION:
-        FIXME("not implemented!");
+        effect.condition.length = params->duration;
+        effect.condition.delay = params->start_delay;
+        effect.condition.button = params->trigger_button;
+        effect.condition.interval = params->trigger_repeat_interval;
+        effect.condition.direction.type = SDL_HAPTIC_SPHERICAL;
+        effect.condition.direction.dir[0] = params->direction[0] * 36000 / 256;
+        effect.condition.direction.dir[1] = params->direction[1] * 36000 / 256;
+        if (params->condition_count >= 1)
+        {
+            effect.condition.right_sat[0] = params->condition[0].positive_saturation;
+            effect.condition.left_sat[0] = params->condition[0].negative_saturation;
+            effect.condition.right_coeff[0] = params->condition[0].positive_coefficient;
+            effect.condition.left_coeff[0] = params->condition[0].negative_coefficient;
+            effect.condition.deadband[0] = params->condition[0].dead_band;
+            effect.condition.center[0] = params->condition[0].center_point_offset;
+        }
+        if (params->condition_count >= 2)
+        {
+            effect.condition.right_sat[1] = params->condition[1].positive_saturation;
+            effect.condition.left_sat[1] = params->condition[1].negative_saturation;
+            effect.condition.right_coeff[1] = params->condition[1].positive_coefficient;
+            effect.condition.left_coeff[1] = params->condition[1].negative_coefficient;
+            effect.condition.deadband[1] = params->condition[1].dead_band;
+            effect.condition.center[1] = params->condition[1].center_point_offset;
+        }
         break;
 
     case PID_USAGE_ET_CONSTANT_FORCE:
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 8a47b232148..251c74574af 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -672,6 +672,10 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
         if (test_bit(ffbits, FF_TRIANGLE)) usages[count++] = PID_USAGE_ET_TRIANGLE;
         if (test_bit(ffbits, FF_SAW_UP)) usages[count++] = PID_USAGE_ET_SAWTOOTH_UP;
         if (test_bit(ffbits, FF_SAW_DOWN)) usages[count++] = PID_USAGE_ET_SAWTOOTH_DOWN;
+        if (test_bit(ffbits, FF_SPRING)) usages[count++] = PID_USAGE_ET_SPRING;
+        if (test_bit(ffbits, FF_DAMPER)) usages[count++] = PID_USAGE_ET_DAMPER;
+        if (test_bit(ffbits, FF_INERTIA)) usages[count++] = PID_USAGE_ET_INERTIA;
+        if (test_bit(ffbits, FF_FRICTION)) usages[count++] = PID_USAGE_ET_FRICTION;
 
         if (!hid_device_add_physical(iface, usages, count))
             return STATUS_NO_MEMORY;
@@ -1014,7 +1018,24 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B
     case PID_USAGE_ET_DAMPER:
     case PID_USAGE_ET_INERTIA:
     case PID_USAGE_ET_FRICTION:
-        FIXME("not implemented!");
+        if (params->condition_count >= 1)
+        {
+            effect.u.condition[0].right_saturation = params->condition[0].positive_saturation;
+            effect.u.condition[0].left_saturation = params->condition[0].negative_saturation;
+            effect.u.condition[0].right_coeff = params->condition[0].positive_coefficient;
+            effect.u.condition[0].left_coeff = params->condition[0].negative_coefficient;
+            effect.u.condition[0].deadband = params->condition[0].dead_band;
+            effect.u.condition[0].center = params->condition[0].center_point_offset;
+        }
+        if (params->condition_count >= 2)
+        {
+            effect.u.condition[1].right_saturation = params->condition[1].positive_saturation;
+            effect.u.condition[1].left_saturation = params->condition[1].negative_saturation;
+            effect.u.condition[1].right_coeff = params->condition[1].positive_coefficient;
+            effect.u.condition[1].left_coeff = params->condition[1].negative_coefficient;
+            effect.u.condition[1].deadband = params->condition[1].dead_band;
+            effect.u.condition[1].center = params->condition[1].center_point_offset;
+        }
         break;
 
     case PID_USAGE_ET_CONSTANT_FORCE:
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index c25558a5ac4..1cd9cf82d68 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -458,6 +458,18 @@ struct pid_set_envelope
     UINT16 attack_time;
     UINT16 fade_time;
 };
+
+struct pid_set_condition
+{
+    BYTE index;
+    BYTE condition_index;
+    BYTE center_point_offset;
+    BYTE positive_coefficient;
+    BYTE negative_coefficient;
+    BYTE positive_saturation;
+    BYTE negative_saturation;
+    BYTE dead_band;
+};
 #include "poppack.h"
 
 static BOOL hid_descriptor_add_set_periodic(struct unix_device *iface)
@@ -577,6 +589,52 @@ static BOOL hid_descriptor_add_set_envelope(struct unix_device *iface)
     return hid_report_descriptor_append(desc, template, sizeof(template));
 }
 
+static BOOL hid_descriptor_add_set_condition(struct unix_device *iface)
+{
+    struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
+    const BYTE report_id = ++desc->next_report_id[HidP_Output];
+    const BYTE template[] =
+    {
+        /* Condition Report Definition */
+        USAGE(1, PID_USAGE_SET_CONDITION_REPORT),
+        COLLECTION(1, Logical),
+            REPORT_ID(1, report_id),
+
+            USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
+            LOGICAL_MAXIMUM(1, 0x7f),
+            LOGICAL_MINIMUM(1, 0x00),
+            REPORT_SIZE(1, 8),
+            REPORT_COUNT(1, 1),
+            OUTPUT(1, Data|Var|Abs),
+
+            USAGE(1, PID_USAGE_CP_OFFSET),
+            USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT),
+            USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT),
+            LOGICAL_MINIMUM(1, -128),
+            LOGICAL_MAXIMUM(1, +127),
+            PHYSICAL_MINIMUM(2, -10000),
+            PHYSICAL_MAXIMUM(2, +10000),
+            REPORT_SIZE(1, 8),
+            REPORT_COUNT(1, 3),
+            OUTPUT(1, Data|Var|Abs),
+
+            USAGE(1, PID_USAGE_POSITIVE_SATURATION),
+            USAGE(1, PID_USAGE_NEGATIVE_SATURATION),
+            USAGE(1, PID_USAGE_DEAD_BAND),
+            LOGICAL_MINIMUM(1, 0),
+            LOGICAL_MAXIMUM(2, 0x00ff),
+            PHYSICAL_MINIMUM(1, 0),
+            PHYSICAL_MAXIMUM(2, +10000),
+            REPORT_SIZE(1, 8),
+            REPORT_COUNT(1, 3),
+            OUTPUT(1, Data|Var|Abs),
+        END_COLLECTION,
+    };
+
+    iface->hid_physical.set_condition_report = report_id;
+    return hid_report_descriptor_append(desc, template, sizeof(template));
+}
+
 BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT count)
 {
     struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
@@ -729,6 +787,7 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co
     };
     BOOL periodic = FALSE;
     BOOL envelope = FALSE;
+    BOOL condition = FALSE;
     ULONG i;
 
     if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header)))
@@ -769,12 +828,19 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co
             usages[i] == PID_USAGE_ET_SAWTOOTH_UP ||
             usages[i] == PID_USAGE_ET_SAWTOOTH_DOWN)
             periodic = envelope = TRUE;
+        if (usages[i] == PID_USAGE_ET_SPRING ||
+            usages[i] == PID_USAGE_ET_DAMPER ||
+            usages[i] == PID_USAGE_ET_INERTIA ||
+            usages[i] == PID_USAGE_ET_FRICTION)
+            condition = TRUE;
     }
 
     if (periodic && !hid_descriptor_add_set_periodic(iface))
         return FALSE;
     if (envelope && !hid_descriptor_add_set_envelope(iface))
         return FALSE;
+    if (condition && !hid_descriptor_add_set_condition(iface))
+        return FALSE;
 
     /* HID nary collection indexes start at 1 */
     memcpy(iface->hid_physical.effect_types + 1, usages, count * sizeof(*usages));
@@ -901,6 +967,8 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC
             params->direction[1] = report->direction[1];
 
             io->Status = iface->hid_vtbl->physical_effect_update(iface, report->index, params);
+
+            params->condition_count = 0;
         }
     }
     else if (packet->reportId == physical->set_periodic_report)
@@ -935,6 +1003,29 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC
             params->envelope.fade_time = report->fade_time;
         }
     }
+    else if (packet->reportId == physical->set_condition_report)
+    {
+        struct pid_set_condition *report = (struct pid_set_condition *)(packet->reportBuffer + 1);
+        struct effect_params *params = iface->hid_physical.effect_params + report->index;
+        struct effect_condition *condition;
+        UINT index;
+
+        io->Information = sizeof(*report) + 1;
+        if (packet->reportBufferLen < io->Information)
+            io->Status = STATUS_BUFFER_TOO_SMALL;
+        else if ((index = params->condition_count++) >= ARRAY_SIZE(params->condition))
+            io->Status = STATUS_INVALID_PARAMETER;
+        else
+        {
+            condition = params->condition + index;
+            condition->center_point_offset = report->center_point_offset;
+            condition->positive_coefficient = report->positive_coefficient;
+            condition->negative_coefficient = report->negative_coefficient;
+            condition->positive_saturation = report->positive_saturation;
+            condition->negative_saturation = report->negative_saturation;
+            condition->dead_band = report->dead_band;
+        }
+    }
     else
     {
         io->Information = 0;
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index 71e6716c7fa..f8c27a73b73 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -45,6 +45,16 @@ struct effect_envelope
     UINT16 fade_time;
 };
 
+struct effect_condition
+{
+    BYTE center_point_offset;
+    BYTE positive_coefficient;
+    BYTE negative_coefficient;
+    BYTE positive_saturation;
+    BYTE negative_saturation;
+    BYTE dead_band;
+};
+
 struct effect_params
 {
     USAGE effect_type;
@@ -57,11 +67,13 @@ struct effect_params
     BOOL axis_enabled[2];
     BOOL direction_enabled;
     BYTE direction[2];
+    BYTE condition_count;
     /* only for periodic, constant or ramp forces */
     struct effect_envelope envelope;
     union
     {
         struct effect_periodic periodic;
+        struct effect_condition condition[2];
     };
 };
 
@@ -136,6 +148,7 @@ struct hid_physical
     BYTE effect_update_report;
     BYTE set_periodic_report;
     BYTE set_envelope_report;
+    BYTE set_condition_report;
 };
 
 struct hid_device_state
-- 
2.33.0




More information about the wine-devel mailing list