Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/hhd/controller/physical/evdev.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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():
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/hhd/device/oxp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
8 changes: 6 additions & 2 deletions src/hhd/device/oxp/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -493,13 +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 if conf["vibrate_on_press"].to(bool) else 0,
)

share_reboots = False
Expand Down
7 changes: 7 additions & 0 deletions src/hhd/device/oxp/controllers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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