From 45c6265b4504396f625105cf52b2e97b3e843777 Mon Sep 17 00:00:00 2001 From: Vitalii Popov Date: Wed, 14 Oct 2026 22:58:53 +0300 Subject: [PATCH] add ability to work with constant-only driver --- src/fbd-dev-vibra.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/fbd-dev-vibra.c b/src/fbd-dev-vibra.c index f764a6c..c43b0a5 100644 --- a/src/fbd-dev-vibra.c +++ b/src/fbd-dev-vibra.c @@ -48,6 +48,9 @@ typedef struct _FbdDevVibra { GUdevDevice *device; gint fd; gint id; /* currently used id */ + /* The driver advertises rumble or periodic effects but rejects them (Qualcomm qti-haptics) */ + gboolean constant_only; + gboolean has_constant; FbdDevVibraFeatureFlags features; } FbdDevVibra; @@ -142,6 +145,8 @@ initable_init (GInitable *initable, return FALSE; } + self->has_constant = HAS_FEATURE (FF_CONSTANT, features); + /* Set gain to 75% if supported */ if (HAS_FEATURE(FF_GAIN, features)) { self->features |= FBD_DEV_VIBRA_FEATURE_GAIN; @@ -232,6 +237,30 @@ fbd_dev_vibra_new (GUdevDevice *device, GError **error) NULL)); } +static gboolean +upload_effect (FbdDevVibra *self, struct ff_effect *effect, double magnitude) +{ + struct ff_effect constant = { 0 }; + + if (!self->constant_only) { + if (ioctl (self->fd, EVIOCSFF, effect) != -1) + return TRUE; + if (errno != EINVAL || !self->has_constant) + return FALSE; + g_debug ("Effect type %u rejected, using constant effects", effect->type); + self->constant_only = TRUE; + } + + constant.type = FF_CONSTANT; + constant.id = -1; + constant.u.constant.level = 0x7FFF * magnitude; + constant.replay = effect->replay; + if (ioctl (self->fd, EVIOCSFF, &constant) == -1) + return FALSE; + effect->id = constant.id; + return TRUE; +} + gboolean fbd_dev_vibra_rumble (FbdDevVibra *self, double magnitude, guint duration, gboolean upload) { @@ -250,7 +279,7 @@ fbd_dev_vibra_rumble (FbdDevVibra *self, double magnitude, guint duration, gbool if (upload) { g_debug("Uploading rumbling vibra effect (%d)", self->fd); - if (ioctl(self->fd, EVIOCSFF, &effect) == -1) { + if (!upload_effect (self, &effect, magnitude)) { g_warning ("Failed to upload rumbling vibra effect: %s", g_strerror (errno)); return FALSE; } @@ -301,7 +330,7 @@ fbd_dev_vibra_periodic (FbdDevVibra *self, effect.replay.delay = 200; g_debug("Uploading periodic effect (%d)", self->fd); - if (ioctl(self->fd, EVIOCSFF, &effect) == -1) { + if (!upload_effect (self, &effect, magnitude)) { g_warning ("Failed to upload periodic vibra effect: %s", g_strerror (errno)); return FALSE; }