From 543cfcd19acaf7572502d99daf2184fd3d86d33f Mon Sep 17 00:00:00 2001 From: Joshua Tam <297250+joshuatam@users.noreply.github.com> Date: Wed, 9 Apr 2025 01:25:41 +0900 Subject: [PATCH 1/2] add touch keyboard vibration --- src/hhd/controller/physical/evdev.py | 44 ++++++++++++++++++++++++++++ src/hhd/device/oxp/base.py | 1 + 2 files changed, 45 insertions(+) diff --git a/src/hhd/controller/physical/evdev.py b/src/hhd/controller/physical/evdev.py index ed13de7b..3c738145 100644 --- a/src/hhd/controller/physical/evdev.py +++ b/src/hhd/controller/physical/evdev.py @@ -245,6 +245,7 @@ def __init__( msc_delay: float = 0.1, postprocess: dict[str, dict] = AXIS_CALIBRATION, requires_start: bool = False, + vibrate_on_press: float = 0 ) -> None: self.vid = vid self.pid = pid @@ -268,6 +269,7 @@ def __init__( self.start_pressed = None self.start_held = False self.requires_start = requires_start + self.vibrate_on_press = vibrate_on_press def open(self) -> Sequence[int]: for d, info in list_evs(filter_valid=True).items(): @@ -325,6 +327,7 @@ def open(self) -> Sequence[int]: self.fd = self.dev.fd self.started = True self.effect_id = -1 + self.effect_on_press_id = -1 self.queue = [] except Exception as e: # Prevent leftover rules in case of error @@ -395,6 +398,38 @@ def consume(self, events: Sequence[Event]): self.effect_id = self.dev.upload_effect(effect) self.dev.write(getattr(ecodes, "EV_FF"), self.effect_id, 1) + case "vibrate_on_press": + if not self.supports_vibration: + continue + + # Erase old effect + if self.effect_on_press_id != -1: + self.dev.erase_effect(self.effect_on_press_id) + self.effect_on_press_id = -1 + + if ev["magnitude"] > 0: + magnitude = min( + int(ev["magnitude"] * 0xFFFF), 0xFFFF + ) + + rumble = ff.Rumble( + strong_magnitude=magnitude, + weak_magnitude=magnitude, + ) + + duration_ms = 80 + + effect = ff.Effect( + getattr(ecodes, "FF_RUMBLE"), + -1, + 0, + ff.Trigger(0, 0), + ff.Replay(duration_ms, 0), + ff.EffectType(ff_rumble_effect=rumble), + ) + self.effect_on_press_id = self.dev.upload_effect(effect) + self.dev.write(getattr(ecodes, "EV_FF"), self.effect_on_press_id, 1) + def produce(self, fds: Sequence[int]) -> Sequence[Event]: out: list[Event] = [] curr = time.time() @@ -428,6 +463,15 @@ def produce(self, fds: Sequence[int]) -> Sequence[Event]: while can_read(self.fd): for e in self.dev.read(): + if self.vibrate_on_press > 0: + out.append( + { + "type": "vibrate_on_press", + "code": "main", + "magnitude": self.vibrate_on_press, + } + ) + if e.type == B("EV_KEY"): if e.code == B("KEY_LEFTMETA"): self.start_held = e.value != 0 diff --git a/src/hhd/device/oxp/base.py b/src/hhd/device/oxp/base.py index 6fb135ee..690d78cf 100644 --- a/src/hhd/device/oxp/base.py +++ b/src/hhd/device/oxp/base.py @@ -500,6 +500,7 @@ def controller_loop( btn_map=BTN_MAPPINGS, capabilities={EC("EV_KEY"): [EC("KEY_D")]}, requires_start=True, + vibrate_on_press=0.008, ) share_reboots = False From 76d222c10fc1dd37f21e6193018c17d934ca2ee1 Mon Sep 17 00:00:00 2001 From: Joshua Tam <297250+joshuatam@users.noreply.github.com> Date: Thu, 10 Apr 2025 21:51:34 +0800 Subject: [PATCH 2/2] add oxp controller setting for g1 touch keyboard vibration --- src/hhd/device/oxp/__init__.py | 3 +++ src/hhd/device/oxp/base.py | 9 ++++++--- src/hhd/device/oxp/controllers.yml | 7 +++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/hhd/device/oxp/__init__.py b/src/hhd/device/oxp/__init__.py index 795ab0b2..903e06f7 100644 --- a/src/hhd/device/oxp/__init__.py +++ b/src/hhd/device/oxp/__init__.py @@ -110,6 +110,9 @@ def settings(self) -> HHDSettings: # Maybe it is helpful for OneXFly users # del base["controllers"]["oxp"]["children"]["swap_face"] + if not self.dconf.get("g1", False): + del base["controllers"]["oxp"]["children"]["vibrate_on_press"] + if not self.turbo: del base["controllers"]["oxp"]["children"]["extra_buttons"] del base["controllers"]["oxp"]["children"]["turbo_reboots"] diff --git a/src/hhd/device/oxp/base.py b/src/hhd/device/oxp/base.py index 690d78cf..d0a248cc 100644 --- a/src/hhd/device/oxp/base.py +++ b/src/hhd/device/oxp/base.py @@ -39,6 +39,9 @@ X1_MINI_PAGE = 0xFF00 X1_MINI_USAGE = 0x0001 +G1_KEYBOARD_VID = 0x6080 +G1_KEYBOARD_PID = 0x8060 + XFLY_VID = 0x1A2C XFLY_PID = 0xB001 XFLY_PAGE = 0xFF01 @@ -493,14 +496,14 @@ def controller_loop( ) # Touchpad keyboard d_kbd_2 = GenericGamepadEvdev( - vid=[0x6080], - pid=[0x8060], + vid=[G1_KEYBOARD_VID], + pid=[G1_KEYBOARD_PID], required=True, grab=False, btn_map=BTN_MAPPINGS, capabilities={EC("EV_KEY"): [EC("KEY_D")]}, requires_start=True, - vibrate_on_press=0.008, + vibrate_on_press=0.008 if conf["vibrate_on_press"].to(bool) else 0, ) share_reboots = False diff --git a/src/hhd/device/oxp/controllers.yml b/src/hhd/device/oxp/controllers.yml index f270cead..36135f4b 100644 --- a/src/hhd/device/oxp/controllers.yml +++ b/src/hhd/device/oxp/controllers.yml @@ -71,3 +71,10 @@ children: hint: >- Swaps A with B and X with Y. default: False + + vibrate_on_press: + type: bool + tags: [ non-essential ] + title: Vibrate on Press (Touch keyboard) + hint: "Vibrate when typing on touch keyboard." + default: True \ No newline at end of file