mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 02:10:07 +01:00
tools: add a measure touchpad-size tool
Replacement for the touchpad-edge-detector tool with a slightly more expressive design, hopefully cutting down on some of the bug reports. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
101cbe16c3
commit
4a9d3e8796
5 changed files with 446 additions and 38 deletions
|
|
@ -33,59 +33,83 @@ Measuring and fixing touchpad ranges
|
|||
To fix the touchpad you need to:
|
||||
|
||||
#. measure the physical size of your touchpad in mm
|
||||
#. run touchpad-edge-detector
|
||||
#. trim the udev match rule to something sensible
|
||||
#. replace the resolution with the calculated resolution based on physical settings
|
||||
#. run the ``libinput measure touchpad-size`` tool
|
||||
#. verify the hwdb entry provided by this tool
|
||||
#. test locally
|
||||
#. send a patch to the systemd project
|
||||
#. send a patch to the `systemd project <https://github.com/systemd/systemd>`_.
|
||||
|
||||
Detailed explanations are below.
|
||||
|
||||
`libevdev <http://freedesktop.org/wiki/Software/libevdev/>`_ provides a tool
|
||||
called **touchpad-edge-detector** that allows measuring the touchpad's input
|
||||
ranges. Run the tool as root against the device node of your touchpad device
|
||||
and repeatedly move a finger around the whole outside area of the
|
||||
touchpad. Then control+c the process and note the output.
|
||||
An example output is below:
|
||||
.. note:: ``libinput measure touchpad-size`` was introduced in libinput
|
||||
1.16. For earlier versions, use `libevdev <http://freedesktop.org/wiki/Software/libevdev/>`_'s
|
||||
``touchpad-edge-detector`` tool.
|
||||
|
||||
|
||||
The ``libinput measure touchpad-size`` tool is an interactive tool. It must
|
||||
be called with the physical dimensions of the touchpad in mm. In the example
|
||||
below, we use 100mm wide and 55mm high. The tool will find the touchpad device
|
||||
automatically.
|
||||
|
||||
::
|
||||
|
||||
$> sudo touchpad-edge-detector /dev/input/event4
|
||||
Touchpad SynPS/2 Synaptics TouchPad on /dev/input/event4
|
||||
Move one finger around the touchpad to detect the actual edges
|
||||
Kernel says: x [1024..3112], y [2024..4832]
|
||||
Touchpad sends: x [2445..4252], y [3464..4071]
|
||||
$> sudo libinput measure touchpad-size 100x55
|
||||
Using "Touchpad SynPS/2 Synaptics TouchPad": /dev/input/event4
|
||||
|
||||
Touchpad size as listed by the kernel: 49x66mm
|
||||
Calculate resolution as:
|
||||
x axis: 2088/<width in mm>
|
||||
y axis: 2808/<height in mm>
|
||||
Kernel specified touchpad size: 99.7x75.9mm
|
||||
User specified touchpad size: 100.0x55.0mm
|
||||
|
||||
Suggested udev rule:
|
||||
# <Laptop model description goes here>
|
||||
evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvnLENOVO:bvrGJET72WW(2.22):bd02/21/2014:svnLENOVO:pn20ARS25701:pvrThinkPadT440s:rvnLENOVO:rn20ARS25701:rvrSDK0E50512STD:cvnLENOVO:ct10:cvrNotAvailable:*
|
||||
EVDEV_ABS_00=2445:4252:<x resolution>
|
||||
EVDEV_ABS_01=3464:4071:<y resolution>
|
||||
EVDEV_ABS_35=2445:4252:<x resolution>
|
||||
EVDEV_ABS_36=3464:4071:<y resolution>
|
||||
Kernel axis range: x [1024..5112], y [2024..4832]
|
||||
Detected axis range: x [ 0.. 0], y [ 0.. 0]
|
||||
|
||||
Move one finger along all edges of the touchpad
|
||||
until the detected axis range stops changing.
|
||||
|
||||
...
|
||||
|
||||
Move the finger around until the detected axis range matches the data sent
|
||||
by the device. ``Ctrl+C`` terminates the tool and prints a
|
||||
suggested hwdb entry. ::
|
||||
|
||||
...
|
||||
Kernel axis range: x [1024..5112], y [2024..4832]
|
||||
^C
|
||||
Detected axis range: x [2072..4880], y [2159..4832]
|
||||
Resolutions calculated based on user-specified size: x 28, y 49 units/mm
|
||||
|
||||
Suggested hwdb entry:
|
||||
Note: the dmi modalias match is a guess based on your machine's modalias:
|
||||
dmi:bvnLENOVO:bvrGJET72WW(2.22):bd02/21/2014:svnLENOVO:pn20ARS25701:pvrThinkPadT440s:rvnLENOVO:rn20ARS25701:rvrSDK0E50512STD:cvnLENOVO:ct10:cvrNotAvailable:
|
||||
Please verify that this is the most sensible match and adjust if necessary.
|
||||
-8<--------------------------
|
||||
# Laptop model description (e.g. Lenovo X1 Carbon 5th)
|
||||
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadT440s*
|
||||
EVDEV_ABS_00=2072:4880:28
|
||||
EVDEV_ABS_01=2159:4832:49
|
||||
EVDEV_ABS_35=2072:4880:28
|
||||
EVDEV_ABS_36=2159:4832:49
|
||||
-8<--------------------------
|
||||
Instructions on what to do with this snippet are in /usr/lib/udev/hwdb.d/60-evdev.hwdb
|
||||
|
||||
|
||||
|
||||
Note the discrepancy between the coordinate range the kernels advertises vs.
|
||||
what the touchpad sends.
|
||||
To fix the advertised ranges, the udev rule should be taken and trimmed
|
||||
before being sent to the `systemd project <https://github.com/systemd/systemd>`_.
|
||||
If there are discrepancies between the coordinate range the kernels
|
||||
advertises and what what the touchpad sends, the hwdb entry should be added to the
|
||||
``60-evdev.hwdb`` file provided by the `systemd project <https://github.com/systemd/systemd>`_.
|
||||
An example commit can be found
|
||||
`here <https://github.com/systemd/systemd/commit/26f667eac1c5e89b689aa0a1daef6a80f473e045>`_.
|
||||
|
||||
In most cases the match can and should be trimmed to the system vendor (svn)
|
||||
and the product version (pvr), with everything else replaced by a wildcard
|
||||
(*). In this case, a Lenovo T440s, a suitable match string would be:
|
||||
The ``libinput measure touchpad-size`` tool attempts to provide the correct
|
||||
dmi match but it does require user verification.
|
||||
|
||||
In most cases the dmi match can and should be trimmed to the system vendor (``svn``)
|
||||
and the product version (``pvr``) or product name (``pn``), with everything else
|
||||
replaced by a wildcard (``*``). In the above case, the match string is:
|
||||
|
||||
::
|
||||
|
||||
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadT440s*
|
||||
|
||||
As a general rule: for Lenovo devices use ``pvr`` and for all others use
|
||||
``pn``.
|
||||
|
||||
.. note:: hwdb match strings only allow for alphanumeric ascii characters. Use a
|
||||
wildcard (* or ?, whichever appropriate) for special characters.
|
||||
|
|
@ -95,19 +119,19 @@ The actual axis overrides are in the form:
|
|||
::
|
||||
|
||||
# axis number=min:max:resolution
|
||||
EVDEV_ABS_00=2445:4252:42
|
||||
EVDEV_ABS_00=2072:4880:28
|
||||
|
||||
or, if the range is correct but the resolution is wrong
|
||||
|
||||
::
|
||||
|
||||
# axis number=::resolution
|
||||
EVDEV_ABS_00=::42
|
||||
EVDEV_ABS_00=::28
|
||||
|
||||
|
||||
Note the leading single space. The axis numbers are in hex and can be found
|
||||
in *linux/input-event-codes.h*. For touchpads ABS_X, ABS_Y,
|
||||
ABS_MT_POSITION_X and ABS_MT_POSITION_Y are required.
|
||||
in ``linux/input-event-codes.h``. For touchpads ``ABS_X``, ``ABS_Y``,
|
||||
``ABS_MT_POSITION_X`` and ``ABS_MT_POSITION_Y`` are required.
|
||||
|
||||
.. note:: The touchpad's ranges and/or resolution should only be fixed when
|
||||
there is a significant discrepancy. A few units do not make a
|
||||
|
|
|
|||
|
|
@ -595,6 +595,7 @@ configure_file(input : 'tools/libinput-analyze.man',
|
|||
src_python_tools = files(
|
||||
'tools/libinput-analyze-per-slot-delta.py',
|
||||
'tools/libinput-measure-fuzz.py',
|
||||
'tools/libinput-measure-touchpad-size.py',
|
||||
'tools/libinput-measure-touchpad-tap.py',
|
||||
'tools/libinput-measure-touchpad-pressure.py',
|
||||
'tools/libinput-measure-touch-size.py',
|
||||
|
|
@ -617,6 +618,7 @@ endforeach
|
|||
|
||||
src_man = files(
|
||||
'tools/libinput-measure-fuzz.man',
|
||||
'tools/libinput-measure-touchpad-size.man',
|
||||
'tools/libinput-measure-touchpad-tap.man',
|
||||
'tools/libinput-measure-touchpad-pressure.man',
|
||||
'tools/libinput-measure-touch-size.man',
|
||||
|
|
|
|||
39
tools/libinput-measure-touchpad-size.man
Normal file
39
tools/libinput-measure-touchpad-size.man
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
.TH libinput-measure-touchpad-size "1"
|
||||
.SH NAME
|
||||
libinput\-measure\-touchpad\-size \- measure the size of a touchpad
|
||||
.SH SYNOPSIS
|
||||
.B libinput measure touchpad\-size [\-\-help] WxH [\fI/dev/input/event0\fI]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The
|
||||
.B "libinput measure touchpad\-size"
|
||||
tool measures the size of a touchpad. This is an interactive tool. When
|
||||
executed, the tool will prompt the user to interact with the touchpad. The
|
||||
tool records the axis ranges and calculates the size and resolution based on
|
||||
those. On termination, the tool prints a hwdb entry that can be added to the
|
||||
.B 60-evdev.hwdb
|
||||
file provided by system.
|
||||
.PP
|
||||
For details see the online documentation here:
|
||||
.I https://wayland.freedesktop.org/libinput/doc/latest/absolute-coordinate-ranges.html
|
||||
.PP
|
||||
This is a debugging tool only, its output may change at any time. Do not
|
||||
rely on the output.
|
||||
.PP
|
||||
This tool usually needs to be run as root to have access to the
|
||||
/dev/input/eventX nodes.
|
||||
.SH OPTIONS
|
||||
This tool must be provided the physical dimensions of the device in mm.
|
||||
For example, if your touchpad is 100mm wide and 55mm heigh, run this tool as
|
||||
.B libinput measure touchpad-size 100x55
|
||||
.PP
|
||||
If a device node is given, this tool opens that device node. Otherwise, this
|
||||
tool searches for the first node that looks like a touchpad and uses that
|
||||
node.
|
||||
.TP 8
|
||||
.B \-\-help
|
||||
Print help
|
||||
.SH LIBINPUT
|
||||
Part of the
|
||||
.B libinput(1)
|
||||
suite
|
||||
340
tools/libinput-measure-touchpad-size.py
Executable file
340
tools/libinput-measure-touchpad-size.py
Executable file
|
|
@ -0,0 +1,340 @@
|
|||
#!/usr/bin/env python3
|
||||
# vim: set expandtab shiftwidth=4:
|
||||
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
|
||||
#
|
||||
# Copyright © 2020 Red Hat, Inc.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
try:
|
||||
import libevdev
|
||||
import pyudev
|
||||
except ModuleNotFoundError as e:
|
||||
print('Error: {}'.format(str(e)), file=sys.stderr)
|
||||
print('One or more python modules are missing. Please install those '
|
||||
'modules and re-run this tool.')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class DeviceError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Point:
|
||||
def __init__(self, x=None, y=None):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
|
||||
class Touchpad(object):
|
||||
def __init__(self, evdev):
|
||||
x = evdev.absinfo[libevdev.EV_ABS.ABS_X]
|
||||
y = evdev.absinfo[libevdev.EV_ABS.ABS_Y]
|
||||
if not x or not y:
|
||||
raise DeviceError('Device does not have an x or axis')
|
||||
|
||||
if not x.resolution or not y.resolution:
|
||||
print('Device does not have resolutions.', file=sys.stderr)
|
||||
x.resolution = 1
|
||||
y.resolution = 1
|
||||
|
||||
self.xrange = (x.maximum - x.minimum)
|
||||
self.yrange = (y.maximum - y.minimum)
|
||||
self.width = self.xrange / x.resolution
|
||||
self.height = self.yrange / y.resolution
|
||||
|
||||
self._x = x
|
||||
self._y = y
|
||||
|
||||
# We try to make the touchpad at least look proportional. The
|
||||
# terminal character space is (guesswork) ca 2.3 times as high as
|
||||
# wide.
|
||||
self.columns = 30
|
||||
self.rows = int(self.columns * (self.yrange // y.resolution) // (self.xrange // x.resolution) / 2.3)
|
||||
self.pos = Point(0, 0)
|
||||
self.min = Point()
|
||||
self.max = Point()
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self._x
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self._y
|
||||
|
||||
@x.setter
|
||||
def x(self, x):
|
||||
self._x.minimum = min(self.x.minimum, x)
|
||||
self._x.maximum = max(self.x.maximum, x)
|
||||
self.min.x = min(x, self.min.x or 0xffffffff)
|
||||
self.max.x = max(x, self.max.x or -0xffffffff)
|
||||
# we calculate the position based on the original range.
|
||||
# this means on devices with a narrower range than advertised, not
|
||||
# all corners may be reachable in the touchpad drawing.
|
||||
self.pos.x = min(0.99, (x - self._x.minimum) / self.xrange)
|
||||
|
||||
@y.setter
|
||||
def y(self, y):
|
||||
self._y.minimum = min(self.y.minimum, y)
|
||||
self._y.maximum = max(self.y.maximum, y)
|
||||
self.min.y = min(y, self.min.y or 0xffffffff)
|
||||
self.max.y = max(y, self.max.y or -0xffffffff)
|
||||
# we calculate the position based on the original range.
|
||||
# this means on devices with a narrower range than advertised, not
|
||||
# all corners may be reachable in the touchpad drawing.
|
||||
self.pos.y = min(0.99, (y - self._y.minimum) / self.yrange)
|
||||
|
||||
def update_from_data(self):
|
||||
if None in [self.min.x, self.min.y, self.max.x, self.max.y]:
|
||||
raise DeviceError('Insufficient data to continue')
|
||||
self._x.minimum = self.min.x
|
||||
self._x.maximum = self.max.x
|
||||
self._y.minimum = self.min.y
|
||||
self._y.maximum = self.max.y
|
||||
|
||||
def draw(self):
|
||||
print('Detected axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]'.format(
|
||||
self.min.x if self.min.x is not None else 0,
|
||||
self.max.x if self.max.x is not None else 0,
|
||||
self.min.y if self.min.y is not None else 0,
|
||||
self.max.y if self.max.y is not None else 0))
|
||||
|
||||
print()
|
||||
print('Move one finger along all edges of the touchpad'.center(self.columns))
|
||||
print('until the detected axis range stops changing.'.center(self.columns))
|
||||
|
||||
top = int(self.pos.y * self.rows)
|
||||
|
||||
print('+{}+'.format(''.ljust(self.columns, '-')))
|
||||
for row in range(0, top):
|
||||
print('|{}|'.format(''.ljust(self.columns)))
|
||||
|
||||
left = int(self.pos.x * self.columns)
|
||||
right = max(0, self.columns - 1 - left)
|
||||
print('|{}{}{}|'.format(
|
||||
''.ljust(left),
|
||||
'O',
|
||||
''.ljust(right)))
|
||||
|
||||
for row in range(top + 1, self.rows):
|
||||
print('|{}|'.format(''.ljust(self.columns)))
|
||||
|
||||
print('+{}+'.format(''.ljust(self.columns, '-')))
|
||||
|
||||
print('Press Ctrl+C to stop'.center(self.columns))
|
||||
|
||||
print('\033[{}A'.format(self.rows + 8), flush=True)
|
||||
|
||||
self.rows_printed = self.rows + 8
|
||||
|
||||
def erase(self):
|
||||
# Erase all previous lines so we're not left with rubbish
|
||||
for row in range(self.rows_printed):
|
||||
print('\033[K')
|
||||
print('\033[{}A'.format(self.rows_printed))
|
||||
|
||||
|
||||
def dimension(string):
|
||||
try:
|
||||
ts = string.split('x')
|
||||
t = tuple([int(x) for x in ts])
|
||||
if len(t) == 2:
|
||||
return t
|
||||
except: # noqa
|
||||
pass
|
||||
|
||||
msg = "{} is not in format WxH".format(string)
|
||||
raise argparse.ArgumentTypeError(msg)
|
||||
|
||||
|
||||
def between(v1, v2, deviation):
|
||||
return v1 - deviation < v2 < v1 + deviation
|
||||
|
||||
|
||||
def dmi_modalias_match(modalias):
|
||||
modalias = modalias.split(':')
|
||||
dmi = {'svn': None, 'pvr': None, 'pn': None}
|
||||
for m in modalias:
|
||||
for key in dmi:
|
||||
if m.startswith(key):
|
||||
dmi[key] = m[len(key):]
|
||||
|
||||
# Based on the current 60-evdev.hwdb, Lenovo uses pvr and everyone else
|
||||
# uses pn to provide a human-identifiable match
|
||||
if dmi['svn'] == 'LENOVO':
|
||||
return 'dmi:*svn{}:*pvr{}*'.format(dmi['svn'], dmi['pvr'])
|
||||
else:
|
||||
return 'dmi:*svn{}:*pn{}*'.format(dmi['svn'], dmi['pn'])
|
||||
|
||||
|
||||
def main(args):
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Measure the touchpad size"
|
||||
)
|
||||
parser.add_argument(
|
||||
'size', metavar='WxH', type=dimension,
|
||||
help='Touchpad size (width by height) in mm',
|
||||
)
|
||||
parser.add_argument(
|
||||
'path', metavar='/dev/input/event0', nargs='?', type=str,
|
||||
help='Path to device (optional)'
|
||||
)
|
||||
context = pyudev.Context()
|
||||
|
||||
args = parser.parse_args()
|
||||
if not args.path:
|
||||
for device in context.list_devices(subsystem='input'):
|
||||
if (device.get('ID_INPUT_TOUCHPAD', 0) and
|
||||
(device.device_node or '').startswith('/dev/input/event')):
|
||||
args.path = device.device_node
|
||||
name = 'unknown'
|
||||
parent = device
|
||||
while parent is not None:
|
||||
n = parent.get('NAME', None)
|
||||
if n:
|
||||
name = n
|
||||
break
|
||||
parent = parent.parent
|
||||
|
||||
print('Using {}: {}'.format(name, device.device_node))
|
||||
break
|
||||
else:
|
||||
print('Unable to find a touchpad device.', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
dev = pyudev.Devices.from_device_file(context, args.path)
|
||||
overrides = [p for p in dev.properties if p.startswith('EVDEV_ABS')]
|
||||
if overrides:
|
||||
print()
|
||||
print('********************************************************************')
|
||||
print('WARNING: axis overrides already in place for this device:')
|
||||
for prop in overrides:
|
||||
print(' {}={}'.format(prop, dev.properties[prop]))
|
||||
print('The systemd hwdb already overrides the axis ranges and/or resolution.')
|
||||
print('This tool is not needed unless you want to verify the axis overrides.')
|
||||
print('********************************************************************')
|
||||
print()
|
||||
|
||||
try:
|
||||
fd = open(args.path, 'rb')
|
||||
evdev = libevdev.Device(fd)
|
||||
touchpad = Touchpad(evdev)
|
||||
print('Kernel specified touchpad size: {:.1f}x{:.1f}mm'.format(touchpad.width, touchpad.height))
|
||||
print('User specified touchpad size: {:.1f}x{:.1f}mm'.format(*args.size))
|
||||
|
||||
print()
|
||||
print('Kernel axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]'.format(
|
||||
touchpad.x.minimum, touchpad.x.maximum,
|
||||
touchpad.y.minimum, touchpad.y.maximum))
|
||||
|
||||
print('Put your finger on the touchpad to start\033[1A')
|
||||
|
||||
try:
|
||||
touchpad.draw()
|
||||
while True:
|
||||
for event in evdev.events():
|
||||
if event.matches(libevdev.EV_ABS.ABS_X):
|
||||
touchpad.x = event.value
|
||||
elif event.matches(libevdev.EV_ABS.ABS_Y):
|
||||
touchpad.y = event.value
|
||||
elif event.matches(libevdev.EV_SYN.SYN_REPORT):
|
||||
touchpad.draw()
|
||||
except KeyboardInterrupt:
|
||||
touchpad.erase()
|
||||
touchpad.update_from_data()
|
||||
|
||||
print('Detected axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]'.format(
|
||||
touchpad.x.minimum, touchpad.x.maximum,
|
||||
touchpad.y.minimum, touchpad.y.maximum))
|
||||
|
||||
touchpad.x.resolution = round((touchpad.x.maximum - touchpad.x.minimum) / args.size[0])
|
||||
touchpad.y.resolution = round((touchpad.y.maximum - touchpad.y.minimum) / args.size[1])
|
||||
|
||||
print('Resolutions calculated based on user-specified size: x {}, y {} units/mm'.format(
|
||||
touchpad.x.resolution, touchpad.y.resolution))
|
||||
|
||||
# If both x/y are within some acceptable deviation, we skip the axis
|
||||
# overrides and only override the resolution
|
||||
xorig = evdev.absinfo[libevdev.EV_ABS.ABS_X]
|
||||
yorig = evdev.absinfo[libevdev.EV_ABS.ABS_Y]
|
||||
deviation = 1.5 * touchpad.x.resolution # 1.5 mm rounding on each side
|
||||
skip = between(xorig.minimum, touchpad.x.minimum, deviation)
|
||||
skip = skip and between(xorig.maximum, touchpad.x.maximum, deviation)
|
||||
deviation = 1.5 * touchpad.y.resolution # 1.5 mm rounding on each side
|
||||
skip = skip and between(yorig.minimum, touchpad.y.minimum, deviation)
|
||||
skip = skip and between(yorig.maximum, touchpad.y.maximum, deviation)
|
||||
|
||||
if skip:
|
||||
print()
|
||||
print('Note: Axis ranges within acceptable deviation, skipping min/max override')
|
||||
print()
|
||||
|
||||
print()
|
||||
print('Suggested hwdb entry:')
|
||||
|
||||
use_dmi = evdev.id['bustype'] not in [0x03, 0x05] # USB, Bluetooth
|
||||
if use_dmi:
|
||||
modalias = open('/sys/class/dmi/id/modalias').read().strip()
|
||||
print('Note: the dmi modalias match is a guess based on your machine\'s modalias:')
|
||||
print(' ', modalias)
|
||||
print('Please verify that this is the most sensible match and adjust if necessary.')
|
||||
|
||||
print('-8<--------------------------')
|
||||
print('# Laptop model description (e.g. Lenovo X1 Carbon 5th)')
|
||||
if use_dmi:
|
||||
print('evdev:name:{}:{}*'.format(evdev.name, dmi_modalias_match(modalias)))
|
||||
else:
|
||||
print('evdev:input:b{:04X}v{:04X}p{:04X}*'.format(
|
||||
evdev.id['bustype'], evdev.id['vendor'], evdev.id['product']))
|
||||
print(' EVDEV_ABS_00={}:{}:{}'.format(
|
||||
touchpad.x.minimum if not skip else '',
|
||||
touchpad.x.maximum if not skip else '',
|
||||
touchpad.x.resolution))
|
||||
print(' EVDEV_ABS_01={}:{}:{}'.format(
|
||||
touchpad.y.minimum if not skip else '',
|
||||
touchpad.y.maximum if not skip else '',
|
||||
touchpad.y.resolution))
|
||||
if evdev.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_X]:
|
||||
print(' EVDEV_ABS_35={}:{}:{}'.format(
|
||||
touchpad.x.minimum if not skip else '',
|
||||
touchpad.x.maximum if not skip else '',
|
||||
touchpad.x.resolution))
|
||||
print(' EVDEV_ABS_36={}:{}:{}'.format(
|
||||
touchpad.y.minimum if not skip else '',
|
||||
touchpad.y.maximum if not skip else '',
|
||||
touchpad.y.resolution))
|
||||
print('-8<--------------------------')
|
||||
print('Instructions on what to do with this snippet are in /usr/lib/udev/hwdb.d/60-evdev.hwdb')
|
||||
except DeviceError as e:
|
||||
print('Error: {}'.format(e), file=sys.stderr)
|
||||
return 1
|
||||
except PermissionError:
|
||||
print('Unable to open device. Please run me as root', file=sys.stderr)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
|
|
@ -28,6 +28,9 @@ Measure touch fuzz to avoid pointer jitter
|
|||
.B libinput\-measure\-touch\-size(1)
|
||||
Measure touch size and orientation
|
||||
.TP 8
|
||||
.B libinput\-measure\-touchpad\-size(1)
|
||||
Measure the size of a touchpad
|
||||
.TP 8
|
||||
.B libinput\-measure\-touchpad\-tap(1)
|
||||
Measure tap-to-click time
|
||||
.TP 8
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue