Skip to content
Merged
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ hhd = "hhd.__main__:main"
[project.entry-points."hhd.plugins"]
legion_go = "hhd.device.legion_go:autodetect"
rog_ally = "hhd.device.rog_ally:autodetect"
# gpd_win = "hhd.device.gpd.win:autodetect"
gpd_win = "hhd.device.gpd.win:autodetect"
powerbuttond = "hhd.plugins.powerbutton:autodetect"
# display = "hhd.plugins.display:autodetect"

Expand Down
4 changes: 2 additions & 2 deletions src/hhd/controller/physical/imu.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DeviceInfo(NamedTuple):

ACCEL_NAMES = ["accel_3d"]
GYRO_NAMES = ["gyro_3d"]
IMU_NAMES = ["bmi323-imu"]
IMU_NAMES = ["bmi323-imu", "BMI0160"]

ACCEL_MAPPINGS: dict[str, tuple[Axis, str | None, float, float | None]] = {
"accel_x": ("accel_z", "accel", 1, 3),
Expand Down Expand Up @@ -74,7 +74,7 @@ def find_sensor(sensors: Sequence[str]):
with open(name_fn, "r") as f:
name = f.read().strip()

if name in sensors:
if any(sensor in name for sensor in sensors):
logger.info(f"Found device '{name}' at\n{sensor_dir}")
return sensor_dir, name

Expand Down
9 changes: 8 additions & 1 deletion src/hhd/device/gpd/win/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
HHDPlugin,
load_relative_yaml,
get_outputs_config,
get_touchpad_config,
)
from hhd.plugins.settings import HHDSettings

Expand Down Expand Up @@ -41,6 +42,12 @@ def settings(self) -> HHDSettings:
base["controllers"]["gpd_win"]["children"]["controller_mode"].update(
get_outputs_config(can_disable=False)
)

if self.dmi == "G1617-01":
base["controllers"]["gpd_win"]["children"]["touchpad"] = get_touchpad_config()
else:
del base["controllers"]["gpd_win"]["children"]["touchpad"]

return base

def update(self, conf: Config):
Expand Down Expand Up @@ -93,4 +100,4 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
if not name:
return []

return [GpdWinControllersPlugin(name, dmi)]
return [GpdWinControllersPlugin(dmi, name)]
72 changes: 65 additions & 7 deletions src/hhd/device/gpd/win/base.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import logging
import re
import select
import time
from threading import Event as TEvent
from typing import Sequence

from hhd.controller import Event, Multiplexer, can_read
from hhd.controller.base import Event
from hhd.controller import Axis, Event, Multiplexer, can_read
from hhd.controller.base import Event, TouchpadAction
from hhd.controller.physical.evdev import B as EC
from hhd.controller.physical.hidraw import GenericGamepadHidraw
from hhd.controller.physical.evdev import GenericGamepadEvdev
from hhd.controller.physical.imu import CombinedImu
from hhd.plugins import Config, Context, Emitter, get_outputs

from .const import (
GPD_TOUCHPAD_AXIS_MAP,
GPD_TOUCHPAD_BUTTON_MAP,
)

ERROR_DELAY = 1
SELECT_TIMEOUT = 1

Expand All @@ -20,6 +27,18 @@
GPD_WIN_4_PID = 0x0135
GAMEPAD_VID = 0x045E
GAMEPAD_PID = 0x028E
TOUCHPAD_PID = 0x0255
TOUCHPAD_VID = 0x093A

GPD_WIN_MAPPINGS: dict[str, tuple[Axis, str | None, float, float | None]] = {
"accel_x": ("accel_z", "accel", 1, 3),
"accel_y": ("accel_x", "accel", 1, 3),
"accel_z": ("accel_y", "accel", 1, 3),
"anglvel_x": ("gyro_x", "anglvel", 1, None),
"anglvel_y": ("gyro_z", "anglvel", -1, None),
"anglvel_z": ("gyro_y", "anglvel", -1, None),
"timestamp": ("gyro_ts", None, 1, None),
}

BACK_BUTTON_DELAY = 0.1

Expand Down Expand Up @@ -150,9 +169,15 @@ def plugin_run(

def controller_loop(conf: Config, should_exit: TEvent, updated: TEvent):
debug = conf.get("debug", False)
has_touchpad = "touchpad" in conf

# Output
d_producers, d_outs, d_params = get_outputs(conf["controller_mode"], None, False)
d_producers, d_outs, d_params = get_outputs(
conf["controller_mode"], conf["touchpad"] if has_touchpad else None, conf["imu"].to(bool)
)

# Imu
d_imu = CombinedImu(conf["imu_hz"].to(int), GPD_WIN_MAPPINGS, gyro_scale="0.000266")

# Inputs
d_xinput = GenericGamepadEvdev(
Expand All @@ -164,6 +189,18 @@ def controller_loop(conf: Config, should_exit: TEvent, updated: TEvent):
hide=True,
)

if has_touchpad:
d_touch = GenericGamepadEvdev(
vid=[TOUCHPAD_VID],
pid=[TOUCHPAD_PID],
name=[re.compile(".+Touchpad")], # "PNP0C50:00 093A:0255 Touchpad"
capabilities={EC("EV_KEY"): [EC("BTN_MOUSE")]},
btn_map=GPD_TOUCHPAD_BUTTON_MAP,
axis_map=GPD_TOUCHPAD_AXIS_MAP,
aspect_ratio=1.333,
required=False,
)

# Vendor
d_vend = GpdWin4Hidraw(
vid=[GPD_WIN_4_VID],
Expand All @@ -182,14 +219,31 @@ def controller_loop(conf: Config, should_exit: TEvent, updated: TEvent):
# btn_map={EC("KEY_SYSRQ"): "extra_l1", EC("KEY_PAUSE"): "extra_r1"},
)

multiplexer = Multiplexer(
trigger="analog_to_discrete",
dpad="analog_to_discrete",
)
if has_touchpad:
touch_actions = (
conf["touchpad.controller"]
if conf["touchpad.mode"].to(TouchpadAction) == "controller"
else conf["touchpad.emulation"]
)

multiplexer = Multiplexer(
trigger="analog_to_discrete",
dpad="analog_to_discrete",
touchpad_short=touch_actions["short"].to(TouchpadAction),
touchpad_right=touch_actions["hold"].to(TouchpadAction),
)
else:
multiplexer = Multiplexer(
trigger="analog_to_discrete",
dpad="analog_to_discrete",
)

REPORT_FREQ_MIN = 25
REPORT_FREQ_MAX = 400

if conf["imu"].to(bool):
REPORT_FREQ_MAX = max(REPORT_FREQ_MAX, conf["imu_hz"].to(float))

REPORT_DELAY_MAX = 1 / REPORT_FREQ_MIN
REPORT_DELAY_MIN = 1 / REPORT_FREQ_MAX

Expand All @@ -207,6 +261,10 @@ def prepare(m):
try:
d_vend.open()
prepare(d_xinput)
if conf.get("imu", False):
prepare(d_imu)
if has_touchpad and d_params["uses_touch"]:
prepare(d_touch)
prepare(d_kbd_1)
for d in d_producers:
prepare(d)
Expand Down
16 changes: 16 additions & 0 deletions src/hhd/device/gpd/win/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from hhd.controller import Axis, Button, Configuration
from hhd.controller.physical.evdev import B, to_map

GPD_TOUCHPAD_BUTTON_MAP: dict[int, Button] = to_map(
{
"touchpad_touch": [B("BTN_TOOL_FINGER")], # also BTN_TOUCH
"touchpad_right": [B("BTN_TOOL_DOUBLETAP")],
}
)

GPD_TOUCHPAD_AXIS_MAP: dict[int, Axis] = to_map(
{
"touchpad_x": [B("ABS_X")], # also ABS_MT_POSITION_X
"touchpad_y": [B("ABS_Y")], # also ABS_MT_POSITION_Y
}
)
17 changes: 17 additions & 0 deletions src/hhd/device/gpd/win/controllers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ children:
#
# Common settings
#
imu:
type: bool
title: Motion Support
hint: >-
Enable gyroscope/accelerometer (IMU) support (.3% background CPU use)
default: True

imu_hz:
type: discrete
title: Motion Hz
hint: >-
Sets the sampling frequency for the IMU.
Check `/sys/bus/iio/devices/iio:device0/in_anglvel_sampling_frequency_available`.
options: [50, 100, 200, 400, 800, 1600]
default: 400

touchpad:

debug:
type: bool
Expand Down