Rémi Bernon : winebus.sys: Add haptics rumble support for UDEV lnxev devices.

Alexandre Julliard julliard at winehq.org
Fri Sep 24 15:31:59 CDT 2021


Module: wine
Branch: master
Commit: a27708dc9b4cf9c6529aa0bc5b391ed43b1cb5a7
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a27708dc9b4cf9c6529aa0bc5b391ed43b1cb5a7

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Sep 24 11:51:57 2021 +0200

winebus.sys: Add haptics rumble support for UDEV lnxev devices.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winebus.sys/bus_udev.c | 62 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 8bc9b4bf64d..88db78360e2 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -126,6 +126,8 @@ struct lnxev_device
     BYTE rel_map[HID_REL_MAX];
     BYTE hat_map[8];
     BYTE button_map[KEY_MAX];
+
+    int haptic_effect_id;
 };
 
 static inline struct base_device *impl_from_unix_device(struct unix_device *iface)
@@ -372,6 +374,8 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
     struct input_absinfo abs_info[HID_ABS_MAX];
     BYTE absbits[(ABS_MAX+7)/8];
     BYTE relbits[(REL_MAX+7)/8];
+    BYTE ffbits[(FF_MAX+7)/8];
+    struct ff_effect effect;
     USAGE_AND_PAGE usage;
     INT i, button_count, abs_count, rel_count, hat_count;
     const BYTE *device_usage = what_am_I(dev);
@@ -387,6 +391,11 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
         WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno, strerror(errno));
         memset(absbits, 0, sizeof(absbits));
     }
+    if (ioctl(impl->base.device_fd, EVIOCGBIT(EV_FF, sizeof(ffbits)), ffbits) == -1)
+    {
+        WARN("ioctl(EVIOCGBIT, EV_FF) failed: %d %s\n", errno, strerror(errno));
+        memset(ffbits, 0, sizeof(ffbits));
+    }
 
     if (!hid_device_begin_report_descriptor(iface, device_usage[0], device_usage[1]))
         return STATUS_NO_MEMORY;
@@ -443,6 +452,23 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
     if (!hid_device_end_input_report(iface))
         return STATUS_NO_MEMORY;
 
+    impl->haptic_effect_id = -1;
+    if (test_bit(ffbits, FF_RUMBLE))
+    {
+        effect.id = -1;
+        effect.type = FF_RUMBLE;
+        effect.replay.length = 0;
+        effect.u.rumble.strong_magnitude = 0;
+        effect.u.rumble.weak_magnitude = 0;
+
+        if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) == -1)
+            WARN("couldn't allocate rumble effect for haptics: %d %s\n", errno, strerror(errno));
+        else if (!hid_device_add_haptics(iface))
+            return FALSE;
+        else
+            impl->haptic_effect_id = effect.id;
+    }
+
     if (!hid_device_end_report_descriptor(iface))
         return STATUS_NO_MEMORY;
 
@@ -737,10 +763,42 @@ static void lnxev_device_read_report(struct unix_device *iface)
 static NTSTATUS lnxev_device_haptics_start(struct unix_device *iface, DWORD duration_ms,
                                            USHORT rumble_intensity, USHORT buzz_intensity)
 {
-    FIXME("iface %p, duration_ms %u, rumble_intensity %u, buzz_intensity %u stub!\n", iface,
+    struct lnxev_device *impl = lnxev_impl_from_unix_device(iface);
+    struct ff_effect effect =
+    {
+        .id = impl->haptic_effect_id,
+        .type = FF_RUMBLE,
+    };
+    struct input_event event;
+
+    TRACE("iface %p, duration_ms %u, rumble_intensity %u, buzz_intensity %u stub!\n", iface,
           duration_ms, rumble_intensity, buzz_intensity);
 
-    return STATUS_NOT_IMPLEMENTED;
+    effect.replay.length = duration_ms;
+    effect.u.rumble.strong_magnitude = rumble_intensity;
+    effect.u.rumble.weak_magnitude = buzz_intensity;
+
+    if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) == -1)
+    {
+        effect.id = -1;
+        if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) == 1)
+        {
+            WARN("couldn't re-allocate rumble effect for haptics: %d %s\n", errno, strerror(errno));
+            return STATUS_UNSUCCESSFUL;
+        }
+        impl->haptic_effect_id = effect.id;
+    }
+
+    event.type = EV_FF;
+    event.code = effect.id;
+    event.value = 1;
+    if (write(impl->base.device_fd, &event, sizeof(event)) == -1)
+    {
+        WARN("couldn't start haptics rumble effect: %d %s\n", errno, strerror(errno));
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    return STATUS_SUCCESS;
 }
 
 static const struct hid_device_vtbl lnxev_device_vtbl =




More information about the wine-cvs mailing list