moused(8): Add support for evdev protocol
The new daemon have following properties as compared with previous
incarnation:
- evdev protocol support for mices and touchpads. Additionally to
relative PS/2 and USB devices it enables console support for I2C/USB
touchpads and bluetooth mices.
- Other aged protocols like COM, raw PS/2 and X10 are dropped with only
exception of sysmouse. For those who still use them there is an
utility called msconvd(8).
- single daemon per system where hotplug is processed via devd socket.
Per device mode still supported too.
- Configuration and quirks files in libinput-compatible format.
Actually, the new moused config parser is taken from libinput.
The moused(8) can work in 2 modes:
1. Evdev support mode. It enables all previously mentioned devices.
It is enabled by deault.
2. Sysmouse support mode. All should work as before.
No new devices supported. To enable it add following lines to
/etc/rc.conf:
moused_port="/dev/psm0"
moused_nondefault_enable="YES"
One may add hw.usb.usbhid.enable=0 to /boot/loader.conf to enable
ums(4) driver which supports sysmouse protocol.
Differential Revision: https://reviews.freebsd.org/D52164
This commit is contained in:
+6
-2
@@ -586,15 +586,19 @@ font8x14="NO" # font 8x14 from /usr/share/{syscons,vt}/fonts/* (or NO).
|
||||
font8x8="NO" # font 8x8 from /usr/share/{syscons,vt}/fonts/* (or NO).
|
||||
blanktime="300" # blank time (in seconds) or "NO" to turn it off.
|
||||
saver="NO" # screen saver: Uses /boot/kernel/${saver}_saver.ko
|
||||
moused_nondefault_enable="YES" # Treat non-default mice as enabled unless
|
||||
moused_nondefault_enable="NO" # Treat non-default mice as enabled unless
|
||||
# specifically overridden in rc.conf(5).
|
||||
moused_enable="NO" # Run the mouse daemon.
|
||||
moused_type="auto" # See man page for rc.conf(5) for available settings.
|
||||
moused_port="/dev/psm0" # Set to your mouse port.
|
||||
moused_port="auto" # Set to your mouse port.
|
||||
moused_flags="" # Any additional flags to moused.
|
||||
mousechar_start="NO" # if 0xd0-0xd3 default range is occupied in your
|
||||
# language code table, specify alternative range
|
||||
# start like mousechar_start=3, see vidcontrol(1)
|
||||
msconvd_enable="NO" # Run the mouse protocol conversion daemon.
|
||||
msconvd_type="auto" # See rc.conf(5) man page for available moused_type-s.
|
||||
msconvd_ports="" # List of msconvd ports.
|
||||
msconvd_flags="" # Any additional flags to msconvd.
|
||||
allscreens_flags="" # Set this vidcontrol mode for all virtual screens
|
||||
allscreens_kbdflags="" # Set this kbdcontrol mode for all virtual screens
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ JAILPACKAGE= jail
|
||||
.if ${MK_LEGACY_CONSOLE} != "no"
|
||||
CONFGROUPS+= CONSOLE
|
||||
CONSOLE+= moused
|
||||
CONSOLE+= msconvd
|
||||
CONSOLE+= syscons
|
||||
CONSOLEPACKAGE= console-tools
|
||||
.endif
|
||||
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
|
||||
# PROVIDE: msconvd
|
||||
# REQUIRE: DAEMON FILESYSTEMS
|
||||
# KEYWORD: nojail shutdown
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="msconvd"
|
||||
desc="Mouse protocol conversion daemon"
|
||||
command="/usr/sbin/${name}"
|
||||
start_cmd="msconvd_start"
|
||||
pidprefix="/var/run/msconvd"
|
||||
load_rc_config $name
|
||||
|
||||
: ${msconvd_enable="NO"}
|
||||
: ${msconvd_type="auto"}
|
||||
|
||||
# doesn't make sense to run in a svcj: nojail keyword
|
||||
# XXX: How does msconvd communiacte with the kernel?
|
||||
# XXX: Does the kernel prevent this communcation in jails?
|
||||
msconvd_svcj="NO"
|
||||
|
||||
# Set the pid file and variable name. The second argument, if it exists, is
|
||||
# expected to be the mouse device.
|
||||
#
|
||||
if [ -n "$2" ]; then
|
||||
eval msconvd_$2_enable=\${msconvd_$2_enable-${msconvd_enable}}
|
||||
rcvar="msconvd_$2_enable"
|
||||
pidfile="${pidprefix}.$2.pid"
|
||||
else
|
||||
for ms in ${msconvd_ports}; do
|
||||
/etc/rc.d/msconvd $1 ${ms}
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msconvd_start()
|
||||
{
|
||||
local ms myflags myport mytype
|
||||
|
||||
# Set the mouse device and get any related variables. If
|
||||
# a msconvd device has been specified on the commandline, then
|
||||
# rc.conf(5) variables defined for that device take precedence
|
||||
# over the generic msconvd_* variables. The only exception is
|
||||
# the msconvd_port variable, which if not defined sets it to
|
||||
# the passed in device name.
|
||||
#
|
||||
ms=$1
|
||||
eval myflags=\${msconvd_${ms}_flags-$msconvd_flags}
|
||||
eval myport=\${msconvd_${ms}_port-/dev/${ms}}
|
||||
eval mytype=\${msconvd_${ms}_type-$msconvd_type}
|
||||
|
||||
startmsg -n "Starting ${ms} ${name}"
|
||||
${command} ${myflags} -p ${myport} -t ${mytype} -I ${pidfile}
|
||||
startmsg '.'
|
||||
}
|
||||
|
||||
run_rc_command $*
|
||||
@@ -3793,11 +3793,14 @@ OLD_FILES+=usr/share/man/man1/host.1.gz
|
||||
.endif
|
||||
|
||||
.if ${MK_LEGACY_CONSOLE} == no
|
||||
OLD_FILES+=etc/moused.conf
|
||||
OLD_FILES+=etc/rc.d/moused
|
||||
OLD_FILES+=etc/rc.d/msconvd
|
||||
OLD_FILES+=etc/rc.d/syscons
|
||||
OLD_FILES+=usr/sbin/kbdcontrol
|
||||
OLD_FILES+=usr/sbin/kbdmap
|
||||
OLD_FILES+=usr/sbin/moused
|
||||
OLD_FILES+=usr/sbin/msconvd
|
||||
OLD_FILES+=usr/sbin/vidcontrol
|
||||
OLD_FILES+=usr/sbin/vidfont
|
||||
OLD_FILES+=usr/share/man/man1/kbdcontrol.1.gz
|
||||
@@ -3806,7 +3809,11 @@ OLD_FILES+=usr/share/man/man1/vidcontrol.1.gz
|
||||
OLD_FILES+=usr/share/man/man1/vidfont.1.gz
|
||||
OLD_FILES+=usr/share/man/man5/kbdmap.5.gz
|
||||
OLD_FILES+=usr/share/man/man5/keymap.5.gz
|
||||
OLD_FILES+=usr/share/man/man5/moused.conf.5.gz
|
||||
OLD_FILES+=usr/share/man/man8/moused.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/msconvd.8.gz
|
||||
OLD_FILES+=usr/share/moused/5-generic-touchpad.quirks
|
||||
OLD_DIRS+=usr/share/moused
|
||||
.endif
|
||||
|
||||
.for LIBCOMPAT libcompat in ${_ALL_LIBCOMPATS_libcompats}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
PACKAGE= console-tools
|
||||
PROG= moused
|
||||
MAN= moused.8
|
||||
SUBDIR+=moused
|
||||
SUBDIR+=msconvd
|
||||
|
||||
LIBADD= m util
|
||||
|
||||
#BINMODE=4555
|
||||
#PRECIOUSPROG=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
lib/libcompiler_rt \
|
||||
lib/libutil \
|
||||
lib/msun \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
||||
@@ -0,0 +1,28 @@
|
||||
PACKAGE= console-tools
|
||||
PROG= moused
|
||||
|
||||
SRCS= moused.c \
|
||||
event-names.h \
|
||||
quirks.c \
|
||||
quirks.h \
|
||||
util.c \
|
||||
util.h \
|
||||
util-evdev.c \
|
||||
util-evdev.h \
|
||||
util-list.c \
|
||||
util-list.h
|
||||
MAN= moused.8 \
|
||||
moused.conf.5
|
||||
CONFS= moused.conf
|
||||
QUIRKS= 5-generic-touchpad.quirks
|
||||
|
||||
CWARNFLAGS.quirks.c+= -Wno-cast-align -Wno-shadow -Wno-cast-qual \
|
||||
-Wno-unused-variable -Wno-unused-parameter
|
||||
CWARNFLAGS.util.c+= -Wno-shadow
|
||||
LIBADD= m util
|
||||
BINDIR= /usr/sbin
|
||||
|
||||
FILES= ${QUIRKS:S|^|quirks/|}
|
||||
FILESDIR= /usr/share/${PROG}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,538 @@
|
||||
.\" SPDX-License-Identifier: BSD-4-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 1996 Mike Pritchard <mpp@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by Mike Pritchard.
|
||||
.\" 4. Neither the name of the author nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd June 14, 2025
|
||||
.Dt MOUSED 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm moused
|
||||
.Nd pass mouse data to the console driver
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dfg
|
||||
.Op Fl I Ar file
|
||||
.Op Fl F Ar rate
|
||||
.Op Fl r Ar resolution
|
||||
.Op Fl VH Op Fl U Ar distance Fl L Ar distance
|
||||
.Op Fl A Ar exp Ns Op , Ns Ar offset
|
||||
.Op Fl a Ar X Ns Op , Ns Ar Y
|
||||
.Op Fl C Ar threshold
|
||||
.Op Fl m Ar N=M
|
||||
.Op Fl w Ar N
|
||||
.Op Fl z Ar target
|
||||
.Op Fl t Ar mousetype
|
||||
.Op Fl l Ar level
|
||||
.Op Fl 3 Op Fl E Ar timeout
|
||||
.Op Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after
|
||||
.Fl p Ar port
|
||||
.Pp
|
||||
.Nm
|
||||
.Op Fl d
|
||||
.Fl p Ar port
|
||||
.Fl i Ar info
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility and the console driver work together to support
|
||||
mouse operation in the text console and user programs.
|
||||
They virtualize the mouse and provide user programs with mouse data
|
||||
in the standard format
|
||||
(see
|
||||
.Xr sysmouse 4 ) .
|
||||
.Pp
|
||||
The mouse daemon listens to the specified port for mouse data,
|
||||
interprets and then passes it via ioctls to the console driver.
|
||||
Supported data interfaces are
|
||||
.Qq input event device
|
||||
AKA evdev and
|
||||
.Xr sysmouse 4
|
||||
level 1.
|
||||
The mouse daemon
|
||||
reports translation movement, button press/release
|
||||
events and movement of the roller or the wheel if available.
|
||||
The roller/wheel movement is reported as
|
||||
.Dq Z
|
||||
axis movement.
|
||||
.Pp
|
||||
The console driver will display the mouse pointer on the screen
|
||||
and provide cut and paste functions if the mouse pointer is enabled
|
||||
in the virtual console via
|
||||
.Xr vidcontrol 1 .
|
||||
If
|
||||
.Xr sysmouse 4
|
||||
is opened by the user program, the console driver also passes the mouse
|
||||
data to the device so that the user program will see it.
|
||||
.Pp
|
||||
If the mouse daemon receives the signal
|
||||
.Dv SIGHUP ,
|
||||
it will reopen the mouse port and reinitialize itself.
|
||||
Useful if
|
||||
the mouse is attached/detached while the system is suspended.
|
||||
.Pp
|
||||
If the mouse daemon receives the signal
|
||||
.Dv SIGUSR1 ,
|
||||
it will stop passing mouse events.
|
||||
Sending the signal
|
||||
.Dv SIGUSR1
|
||||
again will resume passing mouse events.
|
||||
Useful if your typing on a laptop is
|
||||
interrupted by accidentally touching the mouse pad.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl 3
|
||||
Emulate the third (middle) button for 2-button mice.
|
||||
It is emulated
|
||||
by pressing the left and right physical buttons simultaneously.
|
||||
.It Fl C Ar threshold
|
||||
Set double click speed as the maximum interval in msec between button clicks.
|
||||
Without this option, the default value of 500 msec will be assumed.
|
||||
This option will have effect only on the cut and paste operations
|
||||
in the text mode console.
|
||||
The user program which is reading mouse data
|
||||
via
|
||||
.Xr sysmouse 4
|
||||
will not be affected.
|
||||
.It Fl E Ar timeout
|
||||
When the third button emulation is enabled
|
||||
(see above),
|
||||
the
|
||||
.Nm
|
||||
utility waits
|
||||
.Ar timeout
|
||||
msec at most before deciding whether two buttons are being pressed
|
||||
simultaneously.
|
||||
The default timeout is 100 msec.
|
||||
.It Fl F Ar rate
|
||||
Only for
|
||||
.Xr sysmouse 4
|
||||
interface.
|
||||
Set the report rate (reports/sec) of the device if supported.
|
||||
.It Fl L Ar distance
|
||||
When
|
||||
.Dq Virtual Scrolling
|
||||
is enabled, the
|
||||
.Fl L
|
||||
option can be used to set the
|
||||
.Ar distance
|
||||
(in pixels) that the mouse must move before a scroll event
|
||||
is generated. This effectively controls the scrolling speed.
|
||||
The default
|
||||
.Ar distance
|
||||
is 2 pixels.
|
||||
.It Fl H
|
||||
Enable
|
||||
.Dq Horizontal Virtual Scrolling .
|
||||
With this option set, holding the middle mouse
|
||||
button down will cause motion to be interpreted as
|
||||
horizontal scrolling.
|
||||
Use the
|
||||
.Fl U
|
||||
option to set the distance the mouse must move before the scrolling mode is
|
||||
activated and the
|
||||
.Fl L
|
||||
option to set the scrolling speed.
|
||||
This option may be used with or without the
|
||||
.Fl V
|
||||
option.
|
||||
.It Fl I Ar file
|
||||
Write the process id of the
|
||||
.Nm
|
||||
utility in the specified file.
|
||||
Without this option, the process id will be stored in
|
||||
.Pa /var/run/moused.pid .
|
||||
.It Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after
|
||||
Terminate drift.
|
||||
Use this option if mouse pointer slowly wanders when mouse is not moved.
|
||||
Movements up to
|
||||
.Ar distance
|
||||
(for example 4) pixels (X+Y) in
|
||||
.Ar time
|
||||
msec (default 500) are ignored, except during
|
||||
.Ar after
|
||||
msec (default 4000) since last real mouse movement.
|
||||
.It Fl V
|
||||
Enable
|
||||
.Dq Virtual Scrolling .
|
||||
With this option set, holding the middle mouse
|
||||
button down will cause motion to be interpreted as scrolling.
|
||||
Use the
|
||||
.Fl U
|
||||
option to set the distance the mouse must move before the scrolling mode is
|
||||
activated and the
|
||||
.Fl L
|
||||
option to set the scrolling speed.
|
||||
.It Fl U Ar distance
|
||||
When
|
||||
.Dq Virtual Scrolling
|
||||
is enabled, the
|
||||
.Fl U
|
||||
option can be used to set the
|
||||
.Ar distance
|
||||
(in pixels) that the mouse must move before the scrolling
|
||||
mode is activated.
|
||||
The default
|
||||
.Ar distance
|
||||
is 3 pixels.
|
||||
.It Fl A Ar exp Ns Op , Ns Ar offset
|
||||
Apply exponential (dynamic) acceleration to mouse movements:
|
||||
the faster you move the mouse, the more it will be accelerated.
|
||||
That means that small mouse movements are not accelerated,
|
||||
so they are still very accurate, while a faster movement will
|
||||
drive the pointer quickly across the screen.
|
||||
.Pp
|
||||
The
|
||||
.Ar exp
|
||||
value specifies the exponent, which is basically
|
||||
the amount of acceleration. Useful values are in the
|
||||
range 1.1 to 2.0, but it depends on your mouse hardware
|
||||
and your personal preference. A value of 1.0 means no
|
||||
exponential acceleration. A value of 2.0 means squared
|
||||
acceleration (i.e. if you move the mouse twice as fast,
|
||||
the pointer will move four times as fast on the screen).
|
||||
Values beyond 2.0 are possible but not recommended.
|
||||
A good value to start is probably 1.5.
|
||||
.Pp
|
||||
The optional
|
||||
.Ar offset
|
||||
value specifies the distance at which the acceleration
|
||||
begins. The default is 1.0, which means that the
|
||||
acceleration is applied to movements larger than one unit.
|
||||
If you specify a larger value, it takes more speed for
|
||||
the acceleration to kick in, i.e. the speed range for
|
||||
small and accurate movements is wider.
|
||||
Usually the default should be sufficient, but if you're
|
||||
not satisfied with the behaviour, try a value of 2.0.
|
||||
.Pp
|
||||
Note that the
|
||||
.Fl A
|
||||
option interacts badly with the X server's own acceleration,
|
||||
which doesn't work very well anyway. Therefore it is
|
||||
recommended to switch it off if necessary:
|
||||
.Dq xset m 1 .
|
||||
.It Fl a Ar X Ns Op , Ns Ar Y
|
||||
Accelerate or decelerate the mouse input.
|
||||
This is a linear acceleration only.
|
||||
Values less than 1.0 slow down movement, values greater than 1.0 speed it
|
||||
up.
|
||||
Specifying only one value sets the acceleration for both axes.
|
||||
.Pp
|
||||
You can use the
|
||||
.Fl a
|
||||
and
|
||||
.Fl A
|
||||
options at the same time to have the combined effect
|
||||
of linear and exponential acceleration.
|
||||
.It Fl d
|
||||
Enable debugging messages.
|
||||
.It Fl f
|
||||
Do not become a daemon and instead run as a foreground process.
|
||||
Useful for testing and debugging.
|
||||
.It Fl g
|
||||
Only for evdev interface.
|
||||
Become the sole recipient of all incoming input events.
|
||||
This prevents other processes from getting input events on the device.
|
||||
.It Fl i Ar info
|
||||
Print specified information and quit.
|
||||
Available pieces of
|
||||
information are:
|
||||
.Pp
|
||||
.Bl -tag -compact -width modelxxx
|
||||
.It Ar port
|
||||
Port (device file) name, i.e.\&
|
||||
.Pa /dev/input/event0 ,
|
||||
.Pa /dev/ums0
|
||||
and
|
||||
.Pa /dev/psm0 .
|
||||
.It Ar if
|
||||
Interface type:
|
||||
.Dq evdev
|
||||
or
|
||||
.Dq sysmouse .
|
||||
.It Ar type
|
||||
Device type:
|
||||
.Dq mouse
|
||||
or
|
||||
.Dq touchpad .
|
||||
.It Ar model
|
||||
Mouse model.
|
||||
.It Ar all
|
||||
All of the above items.
|
||||
Print port, type and model in this order
|
||||
in one line.
|
||||
.El
|
||||
.Pp
|
||||
If the
|
||||
.Nm
|
||||
utility cannot determine the requested information, it prints
|
||||
.Dq Li unknown
|
||||
or
|
||||
.Dq Li generic .
|
||||
.It Fl l Ar level
|
||||
Ignored.
|
||||
Used for compatibiliy with legacy
|
||||
.Nm .
|
||||
.It Fl m Ar N=M
|
||||
Assign the physical button
|
||||
.Ar M
|
||||
to the logical button
|
||||
.Ar N .
|
||||
You may specify as many instances of this option as you like.
|
||||
More than one physical button may be assigned to a logical button at the
|
||||
same time.
|
||||
In this case the logical button will be down,
|
||||
if either of the assigned physical buttons is held down.
|
||||
Do not put space around
|
||||
.Ql = .
|
||||
.It Fl p Ar port
|
||||
Use
|
||||
.Ar port
|
||||
to communicate with the mouse.
|
||||
.It Fl r Ar resolution
|
||||
Only for
|
||||
.Xr sysmouse 4
|
||||
interface.
|
||||
Set the resolution of the device; in Dots Per Inch, or
|
||||
.Ar low ,
|
||||
.Ar medium-low ,
|
||||
.Ar medium-high
|
||||
or
|
||||
.Ar high .
|
||||
This option may not be supported by all the device.
|
||||
.It Fl t Ar type
|
||||
Ignored.
|
||||
Used for compatibiliy with legacy
|
||||
.Nm .
|
||||
.It Fl q Ar config
|
||||
Path to configuration file.
|
||||
.It Fl Q Ar quirks
|
||||
Path to quirks directory.
|
||||
.It Fl w Ar N
|
||||
Make the physical button
|
||||
.Ar N
|
||||
act as the wheel mode button.
|
||||
While this button is pressed, X and Y axis movement is reported to be zero
|
||||
and the Y axis movement is mapped to Z axis.
|
||||
You may further map the Z axis movement to virtual buttons by the
|
||||
.Fl z
|
||||
option below.
|
||||
.It Fl z Ar target
|
||||
Map Z axis (roller/wheel) movement to another axis or to virtual buttons.
|
||||
Valid
|
||||
.Ar target
|
||||
maybe:
|
||||
.Bl -tag -compact -width x__
|
||||
.It Ar x
|
||||
.It Ar y
|
||||
X or Y axis movement will be reported when the Z axis movement is detected.
|
||||
.It Ar N
|
||||
Report down events for the virtual buttons
|
||||
.Ar N
|
||||
and
|
||||
.Ar N+1
|
||||
respectively when negative and positive Z axis movement
|
||||
is detected.
|
||||
There do not need to be physical buttons
|
||||
.Ar N
|
||||
and
|
||||
.Ar N+1 .
|
||||
Note that mapping to logical buttons is carried out after mapping
|
||||
from the Z axis movement to the virtual buttons is done.
|
||||
.It Ar N1 N2
|
||||
Report down events for the virtual buttons
|
||||
.Ar N1
|
||||
and
|
||||
.Ar N2
|
||||
respectively when negative and positive Z axis movement
|
||||
is detected.
|
||||
.It Ar N1 N2 N3 N4
|
||||
This is useful for the mouse with two wheels of which
|
||||
the second wheel is used to generate horizontal scroll action,
|
||||
and for the mouse which has a knob or a stick which can detect
|
||||
the horizontal force applied by the user.
|
||||
.Pp
|
||||
The motion of the second wheel will be mapped to the buttons
|
||||
.Ar N3 ,
|
||||
for the negative direction, and
|
||||
.Ar N4 ,
|
||||
for the positive direction.
|
||||
If the buttons
|
||||
.Ar N3
|
||||
and
|
||||
.Ar N4
|
||||
actually exist in this mouse, their actions will not be detected.
|
||||
.Pp
|
||||
Note that horizontal movement or second roller/wheel movement may not
|
||||
always be detected,
|
||||
because there appears to be no accepted standard as to how it is encoded.
|
||||
.Pp
|
||||
Note also that some mice think left is the negative horizontal direction;
|
||||
others may think otherwise.
|
||||
Moreover, there are some mice whose two wheels are both mounted vertically,
|
||||
and the direction of the second vertical wheel does not match the
|
||||
first one.
|
||||
.El
|
||||
.Ss Multiple Mice
|
||||
The
|
||||
.Nm
|
||||
utility may operate in 2 different modes depending on the value of
|
||||
.Fl p
|
||||
option.
|
||||
When started with
|
||||
.Fl p Ar auto
|
||||
option specified the
|
||||
.Nm
|
||||
handles all recognized pointing devices in a single instance.
|
||||
Device hotplug is supported through
|
||||
.Xr devd 8 .
|
||||
Only evdev interface is available in this mode.
|
||||
When started with
|
||||
.Fl p Ar <selected_port>
|
||||
option specified the
|
||||
.Nm
|
||||
handles single device located at
|
||||
.Ar <selected_port> .
|
||||
Both evdev and
|
||||
.Xr sysmouse 4
|
||||
level 1 interfaces are available in this mode.
|
||||
Multiple
|
||||
.Nm
|
||||
instances may be run simultaneously.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/run/moused.pid -compact
|
||||
.It Pa /dev/consolectl
|
||||
device to control the console
|
||||
.It Pa /dev/input/event%d
|
||||
Input event device
|
||||
.It Pa /dev/psm%d
|
||||
PS/2 mouse driver
|
||||
.It Pa /dev/sysmouse
|
||||
virtualized mouse driver
|
||||
.It Pa /dev/ums%d
|
||||
USB mouse driver
|
||||
.It Pa /var/run/moused.pid
|
||||
process id of the currently running
|
||||
.Nm
|
||||
utility
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
moused -p auto
|
||||
vidcontrol -m on
|
||||
.Ed
|
||||
.Pp
|
||||
Start
|
||||
.Nm
|
||||
utility to handle all evdev pointing devices automatically with hotplug
|
||||
support.
|
||||
And enable the mouse pointer in the text console after than.
|
||||
The daemon can be started without the
|
||||
.Fl p
|
||||
option as well.
|
||||
.Pp
|
||||
.Dl "moused -f -d -g -p /dev/input/event0"
|
||||
.Ed
|
||||
.Pp
|
||||
Start the mouse daemon on the
|
||||
.Pa /dev/input/event0
|
||||
in the exclusive foreground debug mode.
|
||||
Exclusive mode may disable mouse in Xorg session.
|
||||
.Pp
|
||||
.Dl "moused -p /dev/input/event0 -m 1=3 -m 3=1"
|
||||
.Pp
|
||||
Assign the physical button 3 (right button) to the logical button 1
|
||||
(logical left) and the physical button 1 (left) to the logical
|
||||
button 3 (logical right).
|
||||
This will effectively swap the left and right buttons.
|
||||
.Pp
|
||||
.Dl "moused -p /dev/input/event0 -z 4"
|
||||
.Pp
|
||||
Report negative Z axis movement (i.e., mouse wheel) as the button 4 pressed
|
||||
and positive Z axis movement (i.e., mouse wheel) as the button 5 pressed.
|
||||
.Pp
|
||||
If you add
|
||||
.Pp
|
||||
.Dl "ALL ALL = NOPASSWD: /usr/bin/killall -USR1 moused"
|
||||
.Pp
|
||||
to your
|
||||
.Pa /usr/local/etc/sudoers
|
||||
file, and bind
|
||||
.Pp
|
||||
.Dl "killall -USR1 moused"
|
||||
.Pp
|
||||
to a key in your window manager, you can suspend mouse events on your laptop if
|
||||
you keep brushing over the mouse pad while typing.
|
||||
.Sh SEE ALSO
|
||||
.Xr moused.conf 5 ,
|
||||
.Xr kill 1 ,
|
||||
.Xr vidcontrol 1 ,
|
||||
.Xr xset 1 ,
|
||||
.Xr keyboard 4 ,
|
||||
.Xr psm 4 ,
|
||||
.Xr sysmouse 4 ,
|
||||
.Xr ums 4 ,
|
||||
.Xr devd 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 2.2 .
|
||||
It was rewriten to support multiple input event devices in
|
||||
.Fx 15.0 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
utility was originally written by
|
||||
.An Michael Smith Aq Mt msmith@FreeBSD.org .
|
||||
This manual page was written by
|
||||
.An Mike Pritchard Aq Mt mpp@FreeBSD.org .
|
||||
The command and manual page have since been updated by
|
||||
.An Kazutaka Yokota Aq Mt yokota@FreeBSD.org .
|
||||
Multiple input event devices support was added by
|
||||
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .
|
||||
.Sh CAVEATS
|
||||
Cut and paste functions in the virtual console assume that there
|
||||
are three buttons on the mouse.
|
||||
The logical button 1 (logical left) selects a region of text in the
|
||||
console and copies it to the cut buffer.
|
||||
The logical button 3 (logical right) extends the selected region.
|
||||
The logical button 2 (logical middle) pastes the selected text
|
||||
at the text cursor position.
|
||||
If the mouse has only two buttons, the middle, `paste' button
|
||||
is not available.
|
||||
To obtain the paste function, use the
|
||||
.Fl 3
|
||||
option to emulate the middle button, or use the
|
||||
.Fl m
|
||||
option to assign the physical right button to the logical middle button:
|
||||
.Dq Fl m Li 2=3 .
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
[Default]
|
||||
MatchName=*
|
||||
|
||||
MousedGrabDevice=0 # 1/0
|
||||
MousedIgnoreDevice=0 # 1/0
|
||||
|
||||
MousedClickThreshold=500 # ms
|
||||
MousedEmulateThirdButton=0 # 1/0
|
||||
MousedEmulateThirdButtonTimeout=100 # ms
|
||||
MousedExponentialAccel=1.3 # float
|
||||
MousedExponentialOffset=2.0 # dots
|
||||
MousedLinearAccelX=1.0 # float
|
||||
MousedLinearAccelY=1.0 # float
|
||||
MousedLinearAccelZ=1.0 # float
|
||||
#MousedMapZAxis=0
|
||||
MousedVirtualScrollEnable=0 # 1/0
|
||||
MousedHorVirtualScrollEnable=0 # 1/0
|
||||
MousedVirtualScrollSpeed=2 # dots
|
||||
MousedVirtualScrollThreshold=3 # dots
|
||||
MousedWMode=0 # button num
|
||||
|
||||
[Mouse drift termination]
|
||||
MatchDevType=mouse # mouse/touchpad
|
||||
MousedDriftTerminate=0 # 1/0
|
||||
MousedDriftDistance=4 # dots
|
||||
MousedDriftTime=500 # ms
|
||||
MousedDriftAfter=4000 # ms
|
||||
|
||||
[Default touchpad gesture settings]
|
||||
MatchDevType=touchpad # mouse/touchpad
|
||||
MousedTwoFingerScroll=1 # 1/0
|
||||
MousedNaturalScroll=0 # 1/0
|
||||
MousedThreeFingerDrag=0 # 1/0
|
||||
MousedSoftButton2X=42 # pct
|
||||
MousedSoftButton3X=58 # pct
|
||||
MousedSoftButtonsY=25 # pct
|
||||
MousedTapTimeout=180 # ms
|
||||
#MousedTapPressureThreshold=20
|
||||
MousedTapMaxDelta=1.3 # mm
|
||||
MousedTapholdTimeout=300 # ms
|
||||
MousedVScrollMinDelta=1.25 # mm
|
||||
MousedVScrollHorArea=0.0 # mm
|
||||
MousedVScrollVerArea=-15.0 # mm
|
||||
@@ -0,0 +1,422 @@
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 2025 Vladimir Kondratyev <wulf@FreeBSD.org>
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd May 19, 2025
|
||||
.Dt MOUSED.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm moused.conf
|
||||
.Nd mouse daemon configuration file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
file specifies how the
|
||||
.Xr moused 8
|
||||
(mouse daemon) should operate. It provides ability to adjust certain
|
||||
mice parameters on per-device basis.
|
||||
.Pp
|
||||
Configuration file format is derrived from
|
||||
.Xr libinput 1
|
||||
device quirk files.
|
||||
A file may contain multiple section headers ([some identifier])
|
||||
followed by one or more MatchFoo=Bar directives, followed by at least
|
||||
one of MousedFoo=bar or AttrFoo=bar directive.
|
||||
A configuration file must contain at least one section, each section
|
||||
must have at least one
|
||||
.Sq Match
|
||||
tag and at least one of either
|
||||
.Sq Attr
|
||||
or
|
||||
.Sq Moused .
|
||||
Section names are free-form and may contain spaces.
|
||||
.Ss List of currently available matches.
|
||||
.Bl -tag -width indent
|
||||
.It MatchName, MatchUniq
|
||||
Match on the NAME or UNIQ udev property on this device. These
|
||||
properties are typically derived from the device’s kernel name or uniq.
|
||||
These matches use
|
||||
.Fn fnmatch
|
||||
globs.
|
||||
.It MatchBus
|
||||
A lower-case bus name. Currently supported are usb, bluetooth, ps2,
|
||||
rmi, i2c, and spi.
|
||||
.It MatchVendor, MatchProduct, MatchVersion
|
||||
The hexadecmial 4-digit vendor ID, product ID or driver version as
|
||||
exported, without a 0x prefix.
|
||||
.It MatchDMIModalias, MatchDeviceTree
|
||||
An
|
||||
.Fn fnmatch
|
||||
glob for the DMI modalias or the DeviceTree compatible string.
|
||||
.It MatchDevType
|
||||
One of touchpad, mouse, pointingstick, keyboard, joystick, tablet,
|
||||
tablet-pad.
|
||||
Only touchpad and mouse types are suppported.
|
||||
.El
|
||||
.Ss List of currently available Moused tags.
|
||||
.Bl -tag -width indent
|
||||
.It MousedGrabDevice
|
||||
Only for evdev interface.
|
||||
Become the sole recipient of all incoming input events.
|
||||
This prevents other processes from getting input events on the device.
|
||||
.Pp
|
||||
Use
|
||||
.Fl g
|
||||
option alternatively.
|
||||
.It MousedIgnoreDevice
|
||||
Ignore given device.
|
||||
.It MousedClickThreshold
|
||||
Set double click speed as the maximum interval in msec between button clicks.
|
||||
Without this option, the default value of 500 msec will be assumed.
|
||||
This option will have effect only on the cut and paste operations
|
||||
in the text mode console.
|
||||
The user program which is reading mouse data
|
||||
via
|
||||
.Xr sysmouse 4
|
||||
will not be affected.
|
||||
.Pp
|
||||
Use
|
||||
.Fl C
|
||||
option alternatively.
|
||||
.It MousedEmulateThirdButton
|
||||
Emulate the third (middle) button for 2-button mice.
|
||||
It is emulated
|
||||
by pressing the left and right physical buttons simultaneously.
|
||||
.Pp
|
||||
Use
|
||||
.Fl 3
|
||||
option alternatively.
|
||||
.It MousedEmulateThirdButtonTimeout
|
||||
When the third button emulation is enabled
|
||||
(see above),
|
||||
the
|
||||
.Xr moused 8
|
||||
utility waits
|
||||
.Ar MousedEmulateThirdButtonTimeout
|
||||
msec at most before deciding whether two buttons are being pressed
|
||||
simultaneously.
|
||||
The default timeout is 100 msec.
|
||||
.Pp
|
||||
Use
|
||||
.Fl E
|
||||
option alternatively.
|
||||
.It MousedLinearAccelX
|
||||
.It MousedLinearAccelY
|
||||
.It MousedLinearAccelZ
|
||||
Accelerate or decelerate the mouse input.
|
||||
This is a linear acceleration only.
|
||||
Values less than 1.0 slow down movement, values greater than 1.0 speed it
|
||||
up.
|
||||
.Pp
|
||||
You can use the
|
||||
.Ar MousedLinearAccel
|
||||
and
|
||||
.Ar MousedExponentialAccel
|
||||
options at the same time to have the combined effect
|
||||
of linear and exponential acceleration.
|
||||
.Pp
|
||||
Use
|
||||
.Fl a
|
||||
option alternatively.
|
||||
.It MousedExponentialAccel
|
||||
.It MousedExponentialOffset
|
||||
Apply exponential (dynamic) acceleration to mouse movements:
|
||||
the faster you move the mouse, the more it will be accelerated.
|
||||
That means that small mouse movements are not accelerated,
|
||||
so they are still very accurate, while a faster movement will
|
||||
drive the pointer quickly across the screen.
|
||||
.Pp
|
||||
The
|
||||
.Ar MousedExponentialAccel
|
||||
value specifies the exponent, which is basically
|
||||
the amount of acceleration. Useful values are in the
|
||||
range 1.1 to 2.0, but it depends on your mouse hardware
|
||||
and your personal preference. A value of 1.0 means no
|
||||
exponential acceleration. A value of 2.0 means squared
|
||||
acceleration (i.e. if you move the mouse twice as fast,
|
||||
the pointer will move four times as fast on the screen).
|
||||
Values beyond 2.0 are possible but not recommended.
|
||||
A good value to start is probably 1.5.
|
||||
.Pp
|
||||
The optional
|
||||
.Ar MousedExponentialOffset
|
||||
value specifies the distance at which the acceleration
|
||||
begins. The default is 1.0, which means that the
|
||||
acceleration is applied to movements larger than one unit.
|
||||
If you specify a larger value, it takes more speed for
|
||||
the acceleration to kick in, i.e. the speed range for
|
||||
small and accurate movements is wider.
|
||||
Usually the default should be sufficient, but if you're
|
||||
not satisfied with the behaviour, try a value of 2.0.
|
||||
.Pp
|
||||
Note that the
|
||||
.Fl A
|
||||
option interacts badly with the X server's own acceleration,
|
||||
which doesn't work very well anyway. Therefore it is
|
||||
recommended to switch it off if necessary:
|
||||
.Dq xset m 1 .
|
||||
.Pp
|
||||
Use
|
||||
.Fl A
|
||||
option alternatively.
|
||||
.It MousedMapZAxis
|
||||
Map Z axis (roller/wheel) movement to another axis or to virtual buttons.
|
||||
Does not supported yet.
|
||||
Use
|
||||
.Fl z
|
||||
option instead.
|
||||
.It MousedVirtualScrollEnable
|
||||
Enable
|
||||
.Dq Virtual Scrolling .
|
||||
With this option set, holding the middle mouse
|
||||
button down will cause motion to be interpreted as scrolling.
|
||||
Use the
|
||||
.Ar MousedVirtualScrollThreshold
|
||||
option to set the distance the mouse must move before the scrolling mode is
|
||||
activated and the
|
||||
.Ar MousedVirtualScrollSpeed
|
||||
option to set the scrolling speed.
|
||||
.Pp
|
||||
Use
|
||||
.Fl V
|
||||
option alternatively.
|
||||
.It MousedHorVirtualScrollEnable
|
||||
Enable
|
||||
.Dq Horizontal Virtual Scrolling .
|
||||
With this option set, holding the middle mouse
|
||||
button down will cause motion to be interpreted as
|
||||
horizontal scrolling.
|
||||
Use the
|
||||
.Ar MousedVirtualScrollThreshold
|
||||
option to set the distance the mouse must move before the scrolling mode is
|
||||
activated and the
|
||||
.Ar MousedVirtualScrollSpeed
|
||||
option to set the scrolling speed.
|
||||
This option may be used with or without the
|
||||
.Ar MousedVirtualScrollEnable
|
||||
option.
|
||||
.Pp
|
||||
Use
|
||||
.Fl H
|
||||
option alternatively.
|
||||
.It MousedVirtualScrollSpeed= Ar distance
|
||||
When
|
||||
.Dq Virtual Scrolling
|
||||
is enabled, the
|
||||
.Ar MousedVirtualScrollSpeed
|
||||
option can be used to set the
|
||||
.Ar distance
|
||||
(in pixels) that the mouse must move before a scroll event
|
||||
is generated.
|
||||
This effectively controls the scrolling speed.
|
||||
The default
|
||||
.Ar distance
|
||||
is 2 pixels.
|
||||
.Pp
|
||||
Use
|
||||
.Fl L
|
||||
option alternatively.
|
||||
.It MousedVirtualScrollThreshold= Ar distance
|
||||
When
|
||||
.Dq Virtual Scrolling
|
||||
is enabled, the
|
||||
.Ar MousedVirtualScrollThreshold
|
||||
option can be used to set the
|
||||
.Ar distance
|
||||
(in pixels) that the mouse must move before the scrolling
|
||||
mode is activated.
|
||||
The default
|
||||
.Ar distance
|
||||
is 3 pixels.
|
||||
.Pp
|
||||
Use
|
||||
.Fl U
|
||||
option alternatively.
|
||||
.It MousedWMode= Ar N
|
||||
Make the physical button
|
||||
.Ar N
|
||||
act as the wheel mode button.
|
||||
While this button is pressed, X and Y axis movement is reported to be zero
|
||||
and the Y axis movement is mapped to Z axis.
|
||||
You may further map the Z axis movement to virtual buttons by the
|
||||
.Ar MousedMapZAxis
|
||||
tag.
|
||||
.Pp
|
||||
Use
|
||||
.Fl w
|
||||
option alternatively.
|
||||
.El
|
||||
.Ss List of currently available Moused mice specific tags.
|
||||
.Bl -tag -width indent
|
||||
.It MousedDriftTerminate
|
||||
.It MousedDriftDistance
|
||||
.It MousedDriftTime
|
||||
.It MousedDriftAfter
|
||||
Terminate drift.
|
||||
Use this option if mouse pointer slowly wanders when mouse is not moved.
|
||||
Movements up to
|
||||
.Ar MousedDriftDistance
|
||||
(for example 4) pixels (X+Y) in
|
||||
.Ar MousedDriftTime
|
||||
msec (default 500) are ignored, except during
|
||||
.Ar MousedDriftAfter
|
||||
msec (default 4000) since last real mouse movement.
|
||||
.Pp
|
||||
Use
|
||||
.Fl T
|
||||
option alternatively.
|
||||
.El
|
||||
.Ss List of currently available Moused touchpad specific tags.
|
||||
.Bl -tag -width indent
|
||||
.It MousedTwoFingerScroll
|
||||
Enable two finger scrolling.
|
||||
.It MousedNaturalScroll
|
||||
Enable natural scrolling.
|
||||
.It MousedThreeFingerDrag
|
||||
Enable dragging with three fingers.
|
||||
.It MousedSoftButton2X
|
||||
Horisontal position of 2-nd softbutton left edge in percents.
|
||||
(0-disable)
|
||||
.It MousedSoftButton3X
|
||||
Horisontal position of 3-rd softbutton left edge in percents.
|
||||
(0-disable)
|
||||
.It MousedSoftButtonsY
|
||||
Vertical size of softbuttons area in percents.
|
||||
Use negative values to place softbutton area at top of touchpad.
|
||||
.It MousedTapTimeout
|
||||
Tap timeout in milliseconds
|
||||
.It MousedTapPressureThreshold
|
||||
Pressure threshold to detect tap.
|
||||
.It MousedTapMaxDelta
|
||||
Length of finger movement above which a tap is ignored measured in mm.
|
||||
.It MousedTapholdTimeout
|
||||
Maximum elapsed time between two taps to consider a tap-hold action.
|
||||
.It MousedVScrollMinDelta
|
||||
Minimum movement to consider virtual scrolling.
|
||||
.It MousedVScrollHorArea
|
||||
Area reserved for horizontal virtual scrolling in mm.
|
||||
.It MousedVScrollVerArea
|
||||
Area reserved for vertical virtual scrolling in mm.
|
||||
.El
|
||||
.Ss List of currently available libinput-compatible tags.
|
||||
.Bl -tag -width indent
|
||||
.It AttrSizeHint
|
||||
Hints at the width x height of the device in mm.
|
||||
.It AttrTouchSizeRange
|
||||
Not supported yet.
|
||||
.It AttrPalmSizeThreshold
|
||||
Maximum finger width to detect palm in mm.
|
||||
.It AttrLidSwitchReliability
|
||||
Not supported yet.
|
||||
.It AttrKeyboardIntegration
|
||||
Not supported yet.
|
||||
.It AttrPointingStickIntegration
|
||||
Not supported yet.
|
||||
.It AttrTPKComboLayout
|
||||
Not supported yet.
|
||||
.It AttrPressureRange= Ar N : Ar M
|
||||
Specifies the touch pressure required to trigger a press
|
||||
.Ar N
|
||||
and to trigger a release
|
||||
.Ar M .
|
||||
.It AttrPalmPressureThreshold
|
||||
Maximum pressure to detect palm.
|
||||
.It AttrResolutionHint
|
||||
Hints at the resolution of the x/y axis in units/mm.
|
||||
.It AttrTrackpointMultiplier
|
||||
Not supported yet.
|
||||
.It AttrThumbPressureThreshold
|
||||
Not supported yet.
|
||||
.It AttrUseVelocityAveraging
|
||||
Not supported yet.
|
||||
.It AttrTabletSmoothing
|
||||
Not supported yet.
|
||||
.It AttrThumbSizeThreshold
|
||||
Not supported yet.
|
||||
.It AttrMscTimestamp
|
||||
Not supported yet.
|
||||
.It AttrEventCode
|
||||
Enables or disables the evdev event type/code tuples on the device.
|
||||
The prefix for each entry is either
|
||||
.Sq +
|
||||
(enable) or
|
||||
.Sq -
|
||||
(disable).
|
||||
Entries may be a named event type, or a named event code, or a named
|
||||
event type with a hexadecimal event code, separated by a single colon.
|
||||
.It AttrInputProp
|
||||
Enables or disables the evdev input property on the device.
|
||||
The prefix for each entry is either
|
||||
,Sq +
|
||||
(enable) or
|
||||
.Sq -
|
||||
(disable).
|
||||
Entries may be a named input property or the hexadecimal value of that
|
||||
property.
|
||||
.El
|
||||
.Pp
|
||||
All
|
||||
.Xr libinput 1
|
||||
.Sq Model
|
||||
quirks are currently ignored.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/local/etc/moused.conf -compact
|
||||
.It Pa /usr/local/etc/moused.conf
|
||||
The file
|
||||
.Nm
|
||||
resides in
|
||||
.Pa /usr/local/etc .
|
||||
.It Pa /usr/local/share/moused/*.quirks
|
||||
Predefined quirks processed before
|
||||
.Nm .
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Set touch pressure and palm detection thesholds for PS/2 Synaptics
|
||||
touchpad:
|
||||
.Bd -literal -offset indent
|
||||
[SynPS/2 Synaptics TouchPad]
|
||||
MatchDevType=touchpad
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
AttrPressureRange=35:30
|
||||
AttrPalmPressureThreshold=220
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr moused 8
|
||||
.Pp
|
||||
.Xr libinput 1
|
||||
device quirk format:
|
||||
.Lk https://wayland.freedesktop.org/libinput/doc/latest/device-quirks.html
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
file format first appeared in
|
||||
.Fx 15.0 .
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org
|
||||
based on
|
||||
. Xr moused 8
|
||||
manual page and
|
||||
.Xr libinput 1
|
||||
documentation.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright © 2018 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/**
|
||||
* Handle to the quirks context.
|
||||
*/
|
||||
struct quirks_context;
|
||||
|
||||
/**
|
||||
* Contains all quirks set for a single device.
|
||||
*/
|
||||
struct quirks;
|
||||
|
||||
struct quirk_dimensions {
|
||||
size_t x, y;
|
||||
};
|
||||
|
||||
struct quirk_range {
|
||||
int lower, upper;
|
||||
};
|
||||
|
||||
struct quirk_tuples {
|
||||
struct {
|
||||
int first;
|
||||
int second;
|
||||
int third;
|
||||
} tuples[32];
|
||||
size_t ntuples;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quirks known to libinput. Moused does not support all of them.
|
||||
*/
|
||||
enum quirk {
|
||||
QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD = 100,
|
||||
QUIRK_MODEL_APPLE_TOUCHPAD,
|
||||
QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON,
|
||||
QUIRK_MODEL_BOUNCING_KEYS,
|
||||
QUIRK_MODEL_CHROMEBOOK,
|
||||
QUIRK_MODEL_CLEVO_W740SU,
|
||||
QUIRK_MODEL_DELL_CANVAS_TOTEM,
|
||||
QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_ZBOOK_STUDIO_G3,
|
||||
QUIRK_MODEL_INVERT_HORIZONTAL_SCROLLING,
|
||||
QUIRK_MODEL_LENOVO_SCROLLPOINT,
|
||||
QUIRK_MODEL_LENOVO_T450_TOUCHPAD,
|
||||
QUIRK_MODEL_LENOVO_X1GEN6_TOUCHPAD,
|
||||
QUIRK_MODEL_LENOVO_X230,
|
||||
QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD,
|
||||
QUIRK_MODEL_SYSTEM76_BONOBO,
|
||||
QUIRK_MODEL_SYSTEM76_GALAGO,
|
||||
QUIRK_MODEL_SYSTEM76_KUDU,
|
||||
QUIRK_MODEL_TABLET_MODE_NO_SUSPEND,
|
||||
QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE,
|
||||
QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER,
|
||||
QUIRK_MODEL_TRACKBALL,
|
||||
QUIRK_MODEL_WACOM_TOUCHPAD,
|
||||
QUIRK_MODEL_PRESSURE_PAD,
|
||||
QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS,
|
||||
|
||||
_QUIRK_LAST_MODEL_QUIRK_, /* Guard: do not modify */
|
||||
|
||||
QUIRK_ATTR_SIZE_HINT = 300,
|
||||
QUIRK_ATTR_TOUCH_SIZE_RANGE,
|
||||
QUIRK_ATTR_PALM_SIZE_THRESHOLD,
|
||||
QUIRK_ATTR_LID_SWITCH_RELIABILITY,
|
||||
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
||||
QUIRK_ATTR_TRACKPOINT_INTEGRATION,
|
||||
QUIRK_ATTR_TPKBCOMBO_LAYOUT,
|
||||
QUIRK_ATTR_PRESSURE_RANGE,
|
||||
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
||||
QUIRK_ATTR_RESOLUTION_HINT,
|
||||
QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
|
||||
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
|
||||
QUIRK_ATTR_USE_VELOCITY_AVERAGING,
|
||||
QUIRK_ATTR_TABLET_SMOOTHING,
|
||||
QUIRK_ATTR_THUMB_SIZE_THRESHOLD,
|
||||
QUIRK_ATTR_MSC_TIMESTAMP,
|
||||
QUIRK_ATTR_EVENT_CODE,
|
||||
QUIRK_ATTR_INPUT_PROP,
|
||||
|
||||
_QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */
|
||||
|
||||
|
||||
/* Daemon parameters */
|
||||
MOUSED_GRAB_DEVICE = 1000,
|
||||
MOUSED_IGNORE_DEVICE,
|
||||
|
||||
/* Standard moused parameters */
|
||||
MOUSED_CLICK_THRESHOLD,
|
||||
MOUSED_DRIFT_TERMINATE,
|
||||
MOUSED_DRIFT_DISTANCE,
|
||||
MOUSED_DRIFT_TIME,
|
||||
MOUSED_DRIFT_AFTER,
|
||||
MOUSED_EMULATE_THIRD_BUTTON,
|
||||
MOUSED_EMULATE_THIRD_BUTTON_TIMEOUT,
|
||||
MOUSED_EXPONENTIAL_ACCEL,
|
||||
MOUSED_EXPONENTIAL_OFFSET,
|
||||
MOUSED_LINEAR_ACCEL_X,
|
||||
MOUSED_LINEAR_ACCEL_Y,
|
||||
MOUSED_LINEAR_ACCEL_Z,
|
||||
MOUSED_MAP_Z_AXIS,
|
||||
MOUSED_VIRTUAL_SCROLL_ENABLE,
|
||||
MOUSED_HOR_VIRTUAL_SCROLL_ENABLE,
|
||||
MOUSED_VIRTUAL_SCROLL_SPEED,
|
||||
MOUSED_VIRTUAL_SCROLL_THRESHOLD,
|
||||
MOUSED_WMODE,
|
||||
|
||||
/* Touchpad parameters from psm(4) driver */
|
||||
MOUSED_TWO_FINGER_SCROLL,
|
||||
MOUSED_NATURAL_SCROLL,
|
||||
MOUSED_THREE_FINGER_DRAG,
|
||||
MOUSED_SOFTBUTTON2_X,
|
||||
MOUSED_SOFTBUTTON3_X,
|
||||
MOUSED_SOFTBUTTONS_Y,
|
||||
MOUSED_TAP_TIMEOUT,
|
||||
MOUSED_TAP_PRESSURE_THRESHOLD,
|
||||
MOUSED_TAP_MAX_DELTA,
|
||||
MOUSED_TAPHOLD_TIMEOUT,
|
||||
MOUSED_VSCROLL_MIN_DELTA,
|
||||
MOUSED_VSCROLL_HOR_AREA,
|
||||
MOUSED_VSCROLL_VER_AREA,
|
||||
|
||||
_MOUSED_LAST_OPTION_ /* Guard: do not modify */
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a printable name for the quirk. This name is for developer
|
||||
* tools, not user consumption. Do not display this in a GUI.
|
||||
*/
|
||||
const char*
|
||||
quirk_get_name(enum quirk q);
|
||||
|
||||
/**
|
||||
* Log priorities used if custom logging is enabled.
|
||||
*/
|
||||
enum quirks_log_priorities {
|
||||
QLOG_NOISE = LOG_DEBUG + 1,
|
||||
QLOG_DEBUG = LOG_DEBUG,
|
||||
QLOG_INFO = LOG_INFO,
|
||||
QLOG_ERROR = LOG_ERR,
|
||||
QLOG_PARSER_ERROR = LOG_CRIT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Log type to be used for logging. Use the moused logging to hook up a
|
||||
* moused log handler. This will cause the quirks to reduce the noise and
|
||||
* only provide useful messages.
|
||||
*
|
||||
* QLOG_CUSTOM_LOG_PRIORITIES enables more fine-grained and verbose logging,
|
||||
* allowing debugging tools to be more useful.
|
||||
*/
|
||||
enum quirks_log_type {
|
||||
QLOG_MOUSED_LOGGING,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the quirks subsystem. This function must be called
|
||||
* before anything else.
|
||||
*
|
||||
* If log_type is QLOG_CUSTOM_LOG_PRIORITIES, the log handler is called with
|
||||
* the custom QLOG_* log priorities. Otherwise, the log handler only uses
|
||||
* the moused (syslog) log priorities.
|
||||
*
|
||||
* @param config_file A file path to main configuration file
|
||||
* @param quirks_path The directory containing the various quirk files
|
||||
* @param log_handler The moused log handler called for debugging output
|
||||
*
|
||||
* @return an opaque handle to the context
|
||||
*/
|
||||
struct quirks_context *
|
||||
quirks_init_subsystem(const char *config_file,
|
||||
const char *quirks_path,
|
||||
moused_log_handler log_handler,
|
||||
enum quirks_log_type log_type);
|
||||
|
||||
/**
|
||||
* Clean up after ourselves. This function must be called
|
||||
* as the last call to the quirks subsystem.
|
||||
*
|
||||
* All quirks returned to the caller in quirks_fetch_for_device() must be
|
||||
* unref'd before this call.
|
||||
*
|
||||
* @return Always NULL
|
||||
*/
|
||||
struct quirks_context *
|
||||
quirks_context_unref(struct quirks_context *ctx);
|
||||
|
||||
DEFINE_UNREF_CLEANUP_FUNC(quirks_context);
|
||||
|
||||
struct quirks_context *
|
||||
quirks_context_ref(struct quirks_context *ctx);
|
||||
|
||||
/**
|
||||
* Fetch the quirks for a given device. If no quirks are defined, this
|
||||
* function returns NULL.
|
||||
*
|
||||
* @return A new quirks struct, use quirks_unref() to release
|
||||
*/
|
||||
struct quirks *
|
||||
quirks_fetch_for_device(struct quirks_context *ctx,
|
||||
struct device *device);
|
||||
|
||||
/**
|
||||
* Reduce the refcount by one. When the refcount reaches zero, the
|
||||
* associated struct is released.
|
||||
*
|
||||
* @return Always NULL
|
||||
*/
|
||||
struct quirks *
|
||||
quirks_unref(struct quirks *q);
|
||||
|
||||
DEFINE_UNREF_CLEANUP_FUNC(quirks);
|
||||
|
||||
/**
|
||||
* Returns true if the given quirk applies is in this quirk list.
|
||||
*/
|
||||
bool
|
||||
quirks_has_quirk(struct quirks *q, enum quirk which);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as unsigned integer.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_uint32(struct quirks *q,
|
||||
enum quirk which,
|
||||
uint32_t *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as signed integer.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_int32(struct quirks *q,
|
||||
enum quirk which,
|
||||
int32_t *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as double.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_double(struct quirks *q,
|
||||
enum quirk which,
|
||||
double *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as string.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* val is set to the string, do not modify or free it. The lifetime of the
|
||||
* returned string is bound to the lifetime of the quirk.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_string(struct quirks *q,
|
||||
enum quirk which,
|
||||
char **val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as bool.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_bool(struct quirks *q,
|
||||
enum quirk which,
|
||||
bool *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as dimension.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_dimensions(struct quirks *q,
|
||||
enum quirk which,
|
||||
struct quirk_dimensions *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as range.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_range(struct quirks *q,
|
||||
enum quirk which,
|
||||
struct quirk_range *val);
|
||||
|
||||
/**
|
||||
* Get the tuples of the given quirk.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, tuples is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_tuples(struct quirks *q,
|
||||
enum quirk which,
|
||||
const struct quirk_tuples **tuples);
|
||||
|
||||
/**
|
||||
* Get the uint32 array of the given quirk.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, tuples is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_uint32_array(struct quirks *q,
|
||||
enum quirk which,
|
||||
const uint32_t **array,
|
||||
size_t *nelements);
|
||||
@@ -0,0 +1,9 @@
|
||||
# Do not edit this file, it will be overwritten on update
|
||||
|
||||
[SynPS/2 Synaptics TouchPad]
|
||||
MatchDevType=touchpad
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
AttrPressureRange=35:30
|
||||
MousedTapPressureThreshold=44
|
||||
#AttrThumbPressureThreshold=45
|
||||
AttrPalmPressureThreshold=220
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
||||
* Copyright © 2013 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
|
||||
#include "event-names.h"
|
||||
#include "util-evdev.h"
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof(a) / (sizeof((a)[0])))
|
||||
|
||||
struct name_lookup {
|
||||
const char *name;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
startswith(const char *str, size_t len, const char *prefix, size_t plen)
|
||||
{
|
||||
return len >= plen && !strncmp(str, prefix, plen);
|
||||
}
|
||||
|
||||
static int type_from_prefix(const char *name, ssize_t len)
|
||||
{
|
||||
const char *e;
|
||||
size_t i;
|
||||
ssize_t l;
|
||||
|
||||
/* MAX_ is not allowed, even though EV_MAX exists */
|
||||
if (startswith(name, len, "MAX_", 4))
|
||||
return -1;
|
||||
/* BTN_ is special as there is no EV_BTN type */
|
||||
if (startswith(name, len, "BTN_", 4))
|
||||
return EV_KEY;
|
||||
/* FF_STATUS_ is special as FF_ is a prefix of it, so test it first */
|
||||
if (startswith(name, len, "FF_STATUS_", 10))
|
||||
return EV_FF_STATUS;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(ev_names); ++i) {
|
||||
/* skip EV_ prefix so @e is suffix of [EV_]XYZ */
|
||||
e = &ev_names[i].name[3];
|
||||
l = strlen(e);
|
||||
|
||||
/* compare prefix and test for trailing _ */
|
||||
if (len > l && startswith(name, len, e, l) && name[l] == '_')
|
||||
return ev_names[i].value;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cmp_entry(const void *vlookup, const void *ventry)
|
||||
{
|
||||
const struct name_lookup *lookup = vlookup;
|
||||
const struct name_entry *entry = ventry;
|
||||
int r;
|
||||
|
||||
r = strncmp(lookup->name, entry->name, lookup->len);
|
||||
if (!r) {
|
||||
if (entry->name[lookup->len])
|
||||
r = -1;
|
||||
else
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct name_entry*
|
||||
lookup_name(const struct name_entry *array, size_t asize,
|
||||
struct name_lookup *lookup)
|
||||
{
|
||||
const struct name_entry *entry;
|
||||
|
||||
entry = bsearch(lookup, array, asize, sizeof(*array), cmp_entry);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_event_type_get_max(unsigned int type)
|
||||
{
|
||||
if (type > EV_MAX)
|
||||
return -1;
|
||||
|
||||
return ev_max[type];
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_event_code_from_name(unsigned int type, const char *name)
|
||||
{
|
||||
struct name_lookup lookup;
|
||||
const struct name_entry *entry;
|
||||
int real_type;
|
||||
size_t len = strlen(name);
|
||||
|
||||
real_type = type_from_prefix(name, len);
|
||||
if (real_type < 0 || (unsigned int)real_type != type)
|
||||
return -1;
|
||||
|
||||
lookup.name = name;
|
||||
lookup.len = len;
|
||||
|
||||
entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
|
||||
|
||||
return entry ? (int)entry->value : -1;
|
||||
}
|
||||
|
||||
static int
|
||||
libevdev_event_type_from_name_n(const char *name, size_t len)
|
||||
{
|
||||
struct name_lookup lookup;
|
||||
const struct name_entry *entry;
|
||||
|
||||
lookup.name = name;
|
||||
lookup.len = len;
|
||||
|
||||
entry = lookup_name(ev_names, ARRAY_LENGTH(ev_names), &lookup);
|
||||
|
||||
return entry ? (int)entry->value : -1;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_event_type_from_name(const char *name)
|
||||
{
|
||||
return libevdev_event_type_from_name_n(name, strlen(name));
|
||||
}
|
||||
|
||||
static int
|
||||
libevdev_property_from_name_n(const char *name, size_t len)
|
||||
{
|
||||
struct name_lookup lookup;
|
||||
const struct name_entry *entry;
|
||||
|
||||
lookup.name = name;
|
||||
lookup.len = len;
|
||||
|
||||
entry = lookup_name(prop_names, ARRAY_LENGTH(prop_names), &lookup);
|
||||
|
||||
return entry ? (int)entry->value : -1;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_property_from_name(const char *name)
|
||||
{
|
||||
return libevdev_property_from_name_n(name, strlen(name));
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright © 2013 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UTIL_EVDEV_H
|
||||
#define UTIL_EVDEV_H
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
|
||||
int libevdev_event_code_from_name(unsigned int type, const char *name);
|
||||
int libevdev_event_type_get_max(unsigned int type);
|
||||
int libevdev_event_type_from_name(const char *name);
|
||||
int libevdev_property_from_name(const char *name);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util-list.h"
|
||||
|
||||
void
|
||||
list_init(struct list *list)
|
||||
{
|
||||
list->prev = list;
|
||||
list->next = list;
|
||||
}
|
||||
|
||||
void
|
||||
list_insert(struct list *list, struct list *elm)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
|
||||
!"elm->next|prev is not NULL, list node used twice?");
|
||||
|
||||
elm->prev = list;
|
||||
elm->next = list->next;
|
||||
list->next = elm;
|
||||
elm->next->prev = elm;
|
||||
}
|
||||
|
||||
void
|
||||
list_append(struct list *list, struct list *elm)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
|
||||
!"elm->next|prev is not NULL, list node used twice?");
|
||||
|
||||
elm->next = list;
|
||||
elm->prev = list->prev;
|
||||
list->prev = elm;
|
||||
elm->prev->next = elm;
|
||||
}
|
||||
|
||||
void
|
||||
list_remove(struct list *elm)
|
||||
{
|
||||
assert((elm->next != NULL && elm->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
|
||||
elm->prev->next = elm->next;
|
||||
elm->next->prev = elm->prev;
|
||||
elm->next = NULL;
|
||||
elm->prev = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
list_empty(const struct list *list)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
|
||||
return list->next == list;
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* This list data structure is a verbatim copy from wayland-util.h from the
|
||||
* Wayland project; except that wl_ prefix has been removed.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Doubly linked list implementation. This struct is used for both the list
|
||||
* nodes and the list head. Use like this:
|
||||
*
|
||||
* @code
|
||||
*
|
||||
* struct foo {
|
||||
* struct list list_of_bars; // the list head
|
||||
* };
|
||||
*
|
||||
* struct bar {
|
||||
* struct list link; // links between the bars
|
||||
* };
|
||||
*
|
||||
* struct foo *f = zalloc(sizeof *f);
|
||||
* struct bar *b = make_some_bar();
|
||||
*
|
||||
* list_init(&f->list_of_bars);
|
||||
* list_append(&f->list_of_bars, &b->link);
|
||||
* list_remove(&b->link);
|
||||
* @endcode
|
||||
*/
|
||||
struct list {
|
||||
struct list *prev;
|
||||
struct list *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize a list head. This function *must* be called once for each list
|
||||
* head. This function *must not* be called for a node to be added to a
|
||||
* list.
|
||||
*/
|
||||
void list_init(struct list *list);
|
||||
|
||||
/**
|
||||
* Insert an element at the front of the list
|
||||
*/
|
||||
void list_insert(struct list *list, struct list *elm);
|
||||
/**
|
||||
* Append an element to the back of the list
|
||||
*/
|
||||
void list_append(struct list *list, struct list *elm);
|
||||
|
||||
/**
|
||||
* Remove an element from list.
|
||||
*
|
||||
* Removing a list element is only possible once, the caller must track
|
||||
* whether the list node has already been removed.
|
||||
*
|
||||
*/
|
||||
void list_remove(struct list *elm);
|
||||
/**
|
||||
* Returns true if the given list head is an empty list.
|
||||
*/
|
||||
bool list_empty(const struct list *list);
|
||||
|
||||
/**
|
||||
* Return the 'type' parent container struct of 'ptr' of which
|
||||
* 'member' is our 'ptr' field. For example:
|
||||
*
|
||||
* @code
|
||||
* struct foo { // the parent container struct
|
||||
* uint32_t a;
|
||||
* struct bar bar_member; // the member field
|
||||
* };
|
||||
*
|
||||
* struct foo *f = zalloc(sizeof *f);
|
||||
* struct bar *b = &f->bar_member;
|
||||
* struct foo *f2 = container_of(b, struct foo, bar_member);
|
||||
*
|
||||
* assert(f == f2);
|
||||
* @endcode
|
||||
*/
|
||||
#define container_of(ptr, type, member) \
|
||||
(__typeof__(type) *)((char *)(ptr) - \
|
||||
offsetof(__typeof__(type), member))
|
||||
|
||||
/**
|
||||
* Given a list 'head', return the first entry of type 'pos' that has a
|
||||
* member 'link'.
|
||||
*
|
||||
* The 'pos' argument is solely used to determine the type be returned and
|
||||
* not modified otherwise. It is common to use the same pointer that the
|
||||
* return value of list_first_entry() is assigned to, for example:
|
||||
*
|
||||
* @code
|
||||
* struct foo {
|
||||
* struct list list_of_bars;
|
||||
* };
|
||||
*
|
||||
* struct bar {
|
||||
* struct list link;
|
||||
* }
|
||||
*
|
||||
* struct foo *f = get_a_foo();
|
||||
* struct bar *b = 0; // initialize to avoid static analysis errors
|
||||
* b = list_first_entry(&f->list_of_bars, b, link);
|
||||
* @endcode
|
||||
*/
|
||||
#define list_first_entry(head, pointer_of_type, member) \
|
||||
container_of((head)->next, __typeof__(*pointer_of_type), member)
|
||||
|
||||
/**
|
||||
* Given a list 'head', return the first entry of type 'container_type' that
|
||||
* has a member 'link'.
|
||||
*
|
||||
* @code
|
||||
* struct foo {
|
||||
* struct list list_of_bars;
|
||||
* };
|
||||
*
|
||||
* struct bar {
|
||||
* struct list link;
|
||||
* }
|
||||
*
|
||||
* struct foo *f = get_a_foo();
|
||||
* struct bar *b = list_first_entry(&f->list_of_bars, struct bar, link);
|
||||
* @endcode
|
||||
*/
|
||||
#define list_first_entry_by_type(head, container_type, member) \
|
||||
container_of((head)->next, container_type, member)
|
||||
|
||||
/**
|
||||
* Iterate through the list.
|
||||
*
|
||||
* @code
|
||||
* struct foo *f = get_a_foo();
|
||||
* struct bar *element;
|
||||
* list_for_each(element, &f->list_of_bars, link) {
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* If a list node needs to be removed during iteration, use
|
||||
* list_for_each_safe().
|
||||
*/
|
||||
#define list_for_each(pos, head, member) \
|
||||
for (pos = list_first_entry_by_type(head, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_first_entry_by_type(&pos->member, __typeof__(*pos), member))
|
||||
|
||||
/**
|
||||
* Iterate through the list. Equivalent to list_for_each() but allows
|
||||
* calling list_remove() on the element.
|
||||
*
|
||||
* @code
|
||||
* struct foo *f = get_a_foo();
|
||||
* struct bar *element;
|
||||
* list_for_each(element, tmp, &f->list_of_bars, link) {
|
||||
* list_remove(&element->link);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
#define list_for_each_safe(pos, head, member) \
|
||||
pos = list_first_entry_by_type(head, __typeof__(*pos), member); \
|
||||
for (__typeof__(pos) _tmp = list_first_entry_by_type(&pos->member, __typeof__(*_tmp), member); \
|
||||
&pos->member != (head); \
|
||||
pos = _tmp, \
|
||||
_tmp = list_first_entry_by_type(&pos->member, __typeof__(*_tmp), member))
|
||||
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2013-2019 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dev/evdev/input.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "util-evdev.h"
|
||||
#include "util-list.h"
|
||||
|
||||
/* util-strings.c */
|
||||
|
||||
/**
|
||||
* Return the next word in a string pointed to by state before the first
|
||||
* separator character. Call repeatedly to tokenize a whole string.
|
||||
*
|
||||
* @param state Current state
|
||||
* @param len String length of the word returned
|
||||
* @param separators List of separator characters
|
||||
*
|
||||
* @return The first word in *state, NOT null-terminated
|
||||
*/
|
||||
static const char *
|
||||
next_word(const char **state, size_t *len, const char *separators)
|
||||
{
|
||||
const char *next = *state;
|
||||
size_t l;
|
||||
|
||||
if (!*next)
|
||||
return NULL;
|
||||
|
||||
next += strspn(next, separators);
|
||||
if (!*next) {
|
||||
*state = next;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l = strcspn(next, separators);
|
||||
*state = next + l;
|
||||
*len = l;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a null-terminated string array with the tokens in the input
|
||||
* string, e.g. "one two\tthree" with a separator list of " \t" will return
|
||||
* an array [ "one", "two", "three", NULL ] and num elements 3.
|
||||
*
|
||||
* Use strv_free() to free the array.
|
||||
*
|
||||
* Another example:
|
||||
* result = strv_from_string("+1-2++3--4++-+5-+-", "+-", &nelem)
|
||||
* result == [ "1", "2", "3", "4", "5", NULL ] and nelem == 5
|
||||
*
|
||||
* @param in Input string
|
||||
* @param separators List of separator characters
|
||||
* @param num_elements Number of elements found in the input string
|
||||
*
|
||||
* @return A null-terminated string array or NULL on errors
|
||||
*/
|
||||
char **
|
||||
strv_from_string(const char *in, const char *separators, size_t *num_elements)
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(separators != NULL);
|
||||
assert(num_elements != NULL);
|
||||
|
||||
const char *s = in;
|
||||
size_t l, nelems = 0;
|
||||
while (next_word(&s, &l, separators) != NULL)
|
||||
nelems++;
|
||||
|
||||
if (nelems == 0) {
|
||||
*num_elements = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strv_len = nelems + 1; /* NULL-terminated */
|
||||
char **strv = zalloc(strv_len * sizeof *strv);
|
||||
|
||||
size_t idx = 0;
|
||||
const char *word;
|
||||
s = in;
|
||||
while ((word = next_word(&s, &l, separators)) != NULL) {
|
||||
char *copy = strndup(word, l);
|
||||
if (!copy) {
|
||||
strv_free(strv);
|
||||
*num_elements = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strv[idx++] = copy;
|
||||
}
|
||||
|
||||
*num_elements = nelems;
|
||||
|
||||
return strv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through strv, calling func with each string and its respective index.
|
||||
* Iteration stops successfully after max elements or at the last element,
|
||||
* whichever occurs first.
|
||||
*
|
||||
* If func returns non-zero, iteration stops and strv_for_each returns
|
||||
* that value.
|
||||
*
|
||||
* @return zero on success, otherwise the error returned by the callback
|
||||
*/
|
||||
int strv_for_each_n(const char **strv, size_t max, strv_foreach_callback_t func, void *data)
|
||||
{
|
||||
for (size_t i = 0; i < max && strv && strv[i]; i++) {
|
||||
int ret = func(strv[i], i, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* !util-strings.c */
|
||||
|
||||
/* util-prop-parsers.c */
|
||||
|
||||
/**
|
||||
* Parses a simple dimension string in the form of "10x40". The two
|
||||
* numbers must be positive integers in decimal notation.
|
||||
* On success, the two numbers are stored in w and h. On failure, w and h
|
||||
* are unmodified.
|
||||
*
|
||||
* @param prop The value of the property
|
||||
* @param w Returns the first component of the dimension
|
||||
* @param h Returns the second component of the dimension
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool
|
||||
parse_dimension_property(const char *prop, size_t *w, size_t *h)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if (!prop)
|
||||
return false;
|
||||
|
||||
if (sscanf(prop, "%dx%d", &x, &y) != 2)
|
||||
return false;
|
||||
|
||||
if (x <= 0 || y <= 0)
|
||||
return false;
|
||||
|
||||
*w = (size_t)x;
|
||||
*h = (size_t)y;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string of the format "a:b" where both a and b must be integer
|
||||
* numbers and a > b. Also allowed is the special string value "none" which
|
||||
* amounts to unsetting the property.
|
||||
*
|
||||
* @param prop The value of the property
|
||||
* @param hi Set to the first digit or 0 in case of 'none'
|
||||
* @param lo Set to the second digit or 0 in case of 'none'
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool
|
||||
parse_range_property(const char *prop, int *hi, int *lo)
|
||||
{
|
||||
int first, second;
|
||||
|
||||
if (!prop)
|
||||
return false;
|
||||
|
||||
if (streq(prop, "none")) {
|
||||
*hi = 0;
|
||||
*lo = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sscanf(prop, "%d:%d", &first, &second) != 2)
|
||||
return false;
|
||||
|
||||
if (second >= first)
|
||||
return false;
|
||||
|
||||
*hi = first;
|
||||
*lo = second;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
parse_boolean_property(const char *prop, bool *b)
|
||||
{
|
||||
if (!prop)
|
||||
return false;
|
||||
|
||||
if (streq(prop, "1"))
|
||||
*b = true;
|
||||
else if (streq(prop, "0"))
|
||||
*b = false;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_evcode_string(const char *s, int *type_out, int *code_out)
|
||||
{
|
||||
int type, code;
|
||||
|
||||
if (strstartswith(s, "EV_")) {
|
||||
type = libevdev_event_type_from_name(s);
|
||||
if (type == -1)
|
||||
return false;
|
||||
|
||||
code = EVENT_CODE_UNDEFINED;
|
||||
} else {
|
||||
struct map {
|
||||
const char *str;
|
||||
int type;
|
||||
} map[] = {
|
||||
{ "KEY_", EV_KEY },
|
||||
{ "BTN_", EV_KEY },
|
||||
{ "ABS_", EV_ABS },
|
||||
{ "REL_", EV_REL },
|
||||
{ "SW_", EV_SW },
|
||||
};
|
||||
bool found = false;
|
||||
|
||||
ARRAY_FOR_EACH(map, m) {
|
||||
if (!strstartswith(s, m->str))
|
||||
continue;
|
||||
|
||||
type = m->type;
|
||||
code = libevdev_event_code_from_name(type, s);
|
||||
if (code == -1)
|
||||
return false;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
}
|
||||
|
||||
*type_out = type;
|
||||
*code_out = code;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string of the format "+EV_ABS;+KEY_A;-BTN_TOOL_DOUBLETAP;-ABS_X;"
|
||||
* where each element must be + or - (enable/disable) followed by a named event
|
||||
* type OR a named event code OR a tuple in the form of EV_KEY:0x123, i.e. a
|
||||
* named event type followed by a hex event code.
|
||||
*
|
||||
* events must point to an existing array of size nevents.
|
||||
* nevents specifies the size of the array in events and returns the number
|
||||
* of items, elements exceeding nevents are simply ignored, just make sure
|
||||
* events is large enough for your use-case.
|
||||
*
|
||||
* The results are returned as input events with type and code set, all
|
||||
* other fields undefined. Where only the event type is specified, the code
|
||||
* is set to EVENT_CODE_UNDEFINED.
|
||||
*
|
||||
* On success, events contains nevents events with each event's value set to 1
|
||||
* or 0 depending on the + or - prefix.
|
||||
*/
|
||||
bool
|
||||
parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents)
|
||||
{
|
||||
bool rc = false;
|
||||
/* A randomly chosen max so we avoid crazy quirks */
|
||||
struct input_event evs[32];
|
||||
|
||||
memset(evs, 0, sizeof evs);
|
||||
|
||||
size_t ncodes;
|
||||
char **strv = strv_from_string(prop, ";", &ncodes);
|
||||
if (!strv || ncodes == 0 || ncodes > ARRAY_LENGTH(evs))
|
||||
goto out;
|
||||
|
||||
ncodes = min(*nevents, ncodes);
|
||||
for (size_t idx = 0; strv[idx]; idx++) {
|
||||
char *s = strv[idx];
|
||||
bool enable;
|
||||
|
||||
switch (*s) {
|
||||
case '+': enable = true; break;
|
||||
case '-': enable = false; break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
s++;
|
||||
|
||||
int type, code;
|
||||
|
||||
if (strstr(s, ":") == NULL) {
|
||||
if (!parse_evcode_string(s, &type, &code))
|
||||
goto out;
|
||||
} else {
|
||||
int consumed;
|
||||
char stype[13] = {0}; /* EV_FF_STATUS + '\0' */
|
||||
|
||||
if (sscanf(s, "%12[A-Z_]:%x%n", stype, &code, &consumed) != 2 ||
|
||||
strlen(s) != (size_t)consumed ||
|
||||
(type = libevdev_event_type_from_name(stype)) == -1 ||
|
||||
code < 0 || code > libevdev_event_type_get_max(type))
|
||||
goto out;
|
||||
}
|
||||
|
||||
evs[idx].type = type;
|
||||
evs[idx].code = code;
|
||||
evs[idx].value = enable;
|
||||
}
|
||||
|
||||
memcpy(events, evs, ncodes * sizeof *events);
|
||||
*nevents = ncodes;
|
||||
rc = true;
|
||||
|
||||
out:
|
||||
strv_free(strv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string of the format "+INPUT_PROP_BUTTONPAD;-INPUT_PROP_POINTER;+0x123;"
|
||||
* where each element must be a named input prop OR a hexcode in the form
|
||||
* 0x1234. The prefix for each element must be either '+' (enable) or '-' (disable).
|
||||
*
|
||||
* props must point to an existing array of size nprops.
|
||||
* nprops specifies the size of the array in props and returns the number
|
||||
* of elements, elements exceeding nprops are simply ignored, just make sure
|
||||
* props is large enough for your use-case.
|
||||
*
|
||||
* On success, props contains nprops elements.
|
||||
*/
|
||||
bool
|
||||
parse_input_prop_property(const char *prop, struct input_prop *props_out, size_t *nprops)
|
||||
{
|
||||
bool rc = false;
|
||||
struct input_prop props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */
|
||||
|
||||
size_t count;
|
||||
char **strv = strv_from_string(prop, ";", &count);
|
||||
if (!strv || count == 0 || count > ARRAY_LENGTH(props))
|
||||
goto out;
|
||||
|
||||
count = min(*nprops, count);
|
||||
for (size_t idx = 0; strv[idx]; idx++) {
|
||||
char *s = strv[idx];
|
||||
unsigned int prop;
|
||||
bool enable;
|
||||
|
||||
switch (*s) {
|
||||
case '+': enable = true; break;
|
||||
case '-': enable = false; break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
s++;
|
||||
|
||||
if (safe_atou_base(s, &prop, 16)) {
|
||||
if (prop > INPUT_PROP_MAX)
|
||||
goto out;
|
||||
} else {
|
||||
int val = libevdev_property_from_name(s);
|
||||
if (val == -1)
|
||||
goto out;
|
||||
prop = (unsigned int)val;
|
||||
}
|
||||
props[idx].prop = prop;
|
||||
props[idx].enabled = enable;
|
||||
}
|
||||
|
||||
memcpy(props_out, props, count * sizeof *props);
|
||||
*nprops = count;
|
||||
rc = true;
|
||||
|
||||
out:
|
||||
strv_free(strv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* !util-prop-parsers.c */
|
||||
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mouse.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
#define MOUSED_ATTRIBUTE_PRINTF(_format, _args) \
|
||||
__attribute__ ((format (printf, _format, _args)))
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
/**
|
||||
* Iterate through the array _arr, assigning the variable elem to each
|
||||
* element. elem only exists within the loop.
|
||||
*/
|
||||
#define ARRAY_FOR_EACH(_arr, _elem) \
|
||||
for (__typeof__((_arr)[0]) *_elem = _arr; \
|
||||
_elem < (_arr) + ARRAY_LENGTH(_arr); \
|
||||
_elem++)
|
||||
|
||||
#define versionsort(...) alphasort(__VA_ARGS__)
|
||||
#define bit(x_) (1UL << (x_))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
/* Supported device interfaces */
|
||||
enum device_if {
|
||||
DEVICE_IF_UNKNOWN = -1,
|
||||
DEVICE_IF_EVDEV = 0,
|
||||
DEVICE_IF_SYSMOUSE,
|
||||
};
|
||||
|
||||
/* Recognized device types */
|
||||
enum device_type {
|
||||
DEVICE_TYPE_UNKNOWN = -1,
|
||||
DEVICE_TYPE_MOUSE = 0,
|
||||
DEVICE_TYPE_POINTINGSTICK,
|
||||
DEVICE_TYPE_TOUCHPAD,
|
||||
DEVICE_TYPE_TOUCHSCREEN,
|
||||
DEVICE_TYPE_TABLET,
|
||||
DEVICE_TYPE_TABLET_PAD,
|
||||
DEVICE_TYPE_KEYBOARD,
|
||||
DEVICE_TYPE_JOYSTICK,
|
||||
};
|
||||
|
||||
struct device {
|
||||
char path[80];
|
||||
enum device_if iftype;
|
||||
enum device_type type;
|
||||
char name[80];
|
||||
char uniq[80];
|
||||
struct input_id id;
|
||||
mousemode_t mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
* Log handler type for custom logging.
|
||||
*
|
||||
* @param priority The priority of the current message
|
||||
* @param format Message format in printf-style
|
||||
* @param args Message arguments
|
||||
*/
|
||||
typedef void moused_log_handler(int priority, int errnum,
|
||||
const char *format, va_list args);
|
||||
|
||||
/* util-mem.h */
|
||||
|
||||
/**
|
||||
* Use: _unref_(foo) struct foo *bar;
|
||||
*
|
||||
* This requires foo_unrefp() to be present, use DEFINE_UNREF_CLEANUP_FUNC.
|
||||
*/
|
||||
#define _unref_(_type) __attribute__((cleanup(_type##_unrefp))) struct _type
|
||||
|
||||
/**
|
||||
* Define a cleanup function for the struct type foo with a matching
|
||||
* foo_unref(). Use:
|
||||
* DEFINE_UNREF_CLEANUP_FUNC(foo)
|
||||
* _unref_(foo) struct foo *bar;
|
||||
*/
|
||||
#define DEFINE_UNREF_CLEANUP_FUNC(_type) \
|
||||
static inline void _type##_unrefp(struct _type **_p) { \
|
||||
if (*_p) \
|
||||
_type##_unref(*_p); \
|
||||
} \
|
||||
struct __useless_struct_to_allow_trailing_semicolon__
|
||||
|
||||
static inline void*
|
||||
_steal(void *ptr) {
|
||||
void **original = (void**)ptr;
|
||||
void *swapped = *original;
|
||||
*original = NULL;
|
||||
return swapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the pointer content and resets the data to NULL.
|
||||
* This circumvents _cleanup_ handling for that pointer.
|
||||
* Use:
|
||||
* _cleanup_free_ char *data = malloc();
|
||||
* return steal(&data);
|
||||
*
|
||||
*/
|
||||
#define steal(ptr_) \
|
||||
(typeof(*ptr_))_steal(ptr_)
|
||||
|
||||
/* ! util-mem.h */
|
||||
|
||||
/* util-strings.h */
|
||||
|
||||
static inline bool
|
||||
streq(const char *str1, const char *str2)
|
||||
{
|
||||
/* one NULL, one not NULL is always false */
|
||||
if (str1 && str2)
|
||||
return strcmp(str1, str2) == 0;
|
||||
return str1 == str2;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
strneq(const char *str1, const char *str2, int n)
|
||||
{
|
||||
/* one NULL, one not NULL is always false */
|
||||
if (str1 && str2)
|
||||
return strncmp(str1, str2, n) == 0;
|
||||
return str1 == str2;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
zalloc(size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
/* We never need to alloc anything more than 1,5 MB so we can assume
|
||||
* if we ever get above that something's going wrong */
|
||||
if (size > 1536 * 1024)
|
||||
assert(!"bug: internal malloc size limit exceeded");
|
||||
|
||||
p = calloc(1, size);
|
||||
if (!p)
|
||||
abort();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* strdup guaranteed to succeed. If the input string is NULL, the output
|
||||
* string is NULL. If the input string is a string pointer, we strdup or
|
||||
* abort on failure.
|
||||
*/
|
||||
static inline char*
|
||||
safe_strdup(const char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
s = strdup(str);
|
||||
if (!s)
|
||||
abort();
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper for asprintf that ensures the passed in-pointer is set
|
||||
* to NULL upon error.
|
||||
* The standard asprintf() call does not guarantee the passed in pointer
|
||||
* will be NULL'ed upon failure, whereas this wrapper does.
|
||||
*
|
||||
* @param strp pointer to set to newly allocated string.
|
||||
* This pointer should be passed to free() to release when done.
|
||||
* @param fmt the format string to use for printing.
|
||||
* @return The number of bytes printed (excluding the null byte terminator)
|
||||
* upon success or -1 upon failure. In the case of failure the pointer is set
|
||||
* to NULL.
|
||||
*/
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
static inline int
|
||||
xasprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
int rc = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
rc = vasprintf(strp, fmt, args);
|
||||
va_end(args);
|
||||
if ((rc == -1) && strp)
|
||||
*strp = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atoi_base(const char *str, int *val, int base)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
char *endptr;
|
||||
long v;
|
||||
|
||||
assert(base == 10 || base == 16 || base == 8);
|
||||
|
||||
errno = 0;
|
||||
v = strtol(str, &endptr, base);
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
|
||||
if (v > INT_MAX || v < INT_MIN)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atoi(const char *str, int *val)
|
||||
{
|
||||
assert(str != NULL);
|
||||
return safe_atoi_base(str, val, 10);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atou_base(const char *str, unsigned int *val, int base)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
char *endptr;
|
||||
unsigned long v;
|
||||
|
||||
assert(base == 10 || base == 16 || base == 8);
|
||||
|
||||
errno = 0;
|
||||
v = strtoul(str, &endptr, base);
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
|
||||
if ((long)v < 0)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atou(const char *str, unsigned int *val)
|
||||
{
|
||||
assert(str != NULL);
|
||||
return safe_atou_base(str, val, 10);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atod(const char *str, double *val)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
char *endptr;
|
||||
double v;
|
||||
size_t slen = strlen(str);
|
||||
|
||||
/* We don't have a use-case where we want to accept hex for a double
|
||||
* or any of the other values strtod can parse */
|
||||
for (size_t i = 0; i < slen; i++) {
|
||||
char c = str[i];
|
||||
|
||||
if (isdigit(c))
|
||||
continue;
|
||||
switch(c) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '.':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
/* Create a "C" locale to force strtod to use '.' as separator */
|
||||
locale_t c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||
if (c_locale == (locale_t)0)
|
||||
return false;
|
||||
|
||||
errno = 0;
|
||||
v = strtod_l(str, &endptr, c_locale);
|
||||
freelocale(c_locale);
|
||||
#else
|
||||
/* No locale support in provided libc, assume it already uses '.' */
|
||||
errno = 0;
|
||||
v = strtod(str, &endptr);
|
||||
#endif
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
if (v != 0.0 && !isnormal(v))
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
char **strv_from_string(const char *in, const char *separator, size_t *num_elements);
|
||||
|
||||
typedef int (*strv_foreach_callback_t)(const char *str, size_t index, void *data);
|
||||
int strv_for_each_n(const char **strv, size_t max, strv_foreach_callback_t func, void *data);
|
||||
|
||||
static inline void
|
||||
strv_free(char **strv) {
|
||||
char **s = strv;
|
||||
|
||||
if (!strv)
|
||||
return;
|
||||
|
||||
while (*s != NULL) {
|
||||
free(*s);
|
||||
*s = (char*)0x1; /* detect use-after-free */
|
||||
s++;
|
||||
}
|
||||
|
||||
free (strv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if str ends in suffix, false otherwise. If the suffix is the
|
||||
* empty string, strendswith() always returns false.
|
||||
*/
|
||||
static inline bool
|
||||
strendswith(const char *str, const char *suffix)
|
||||
{
|
||||
if (str == NULL)
|
||||
return false;
|
||||
|
||||
size_t slen = strlen(str);
|
||||
size_t suffixlen = strlen(suffix);
|
||||
size_t offset;
|
||||
|
||||
if (slen == 0 || suffixlen == 0 || suffixlen > slen)
|
||||
return false;
|
||||
|
||||
offset = slen - suffixlen;
|
||||
return strneq(&str[offset], suffix, suffixlen);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
strstartswith(const char *str, const char *prefix)
|
||||
{
|
||||
if (str == NULL)
|
||||
return false;
|
||||
|
||||
size_t prefixlen = strlen(prefix);
|
||||
|
||||
return prefixlen > 0 ? strneq(str, prefix, strlen(prefix)) : false;
|
||||
}
|
||||
|
||||
/* !util-strings.h */
|
||||
|
||||
/* util-prop-parsers.h */
|
||||
|
||||
struct input_prop {
|
||||
unsigned int prop;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
bool parse_dimension_property(const char *prop, size_t *w, size_t *h);
|
||||
bool parse_range_property(const char *prop, int *hi, int *lo);
|
||||
bool parse_boolean_property(const char *prop, bool *b);
|
||||
#define EVENT_CODE_UNDEFINED 0xffff
|
||||
bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents);
|
||||
bool parse_input_prop_property(const char *prop, struct input_prop *props_out, size_t *nprops);
|
||||
|
||||
/* !util-prop-parsers.h */
|
||||
@@ -0,0 +1,8 @@
|
||||
PACKAGE= console-tools
|
||||
PROG= msconvd
|
||||
SRCS= ${PROG}.c
|
||||
LIBADD= util
|
||||
BINDIR= /usr/sbin
|
||||
MAN= ${PROG}.8
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -31,30 +31,21 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd July 7, 2024
|
||||
.Dt MOUSED 8
|
||||
.Dd May 18, 2025
|
||||
.Dt MSCONVD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm moused
|
||||
.Nd pass mouse data to the system video console driver
|
||||
.Nm msconvd
|
||||
.Nd mouse protocol conversion daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl DPRacdfs
|
||||
.Op Fl DPRcdfs
|
||||
.Op Fl I Ar file
|
||||
.Op Fl F Ar rate
|
||||
.Op Fl r Ar resolution
|
||||
.Op Fl S Ar baudrate
|
||||
.Op Fl VH Op Fl U Ar distance Fl L Ar distance
|
||||
.Op Fl A Ar exp Ns Op , Ns Ar offset
|
||||
.Op Fl a Ar X Ns Op , Ns Ar Y
|
||||
.Op Fl C Ar threshold
|
||||
.Op Fl m Ar N=M
|
||||
.Op Fl w Ar N
|
||||
.Op Fl z Ar target
|
||||
.Op Fl t Ar mousetype
|
||||
.Op Fl l Ar level
|
||||
.Op Fl 3 Op Fl E Ar timeout
|
||||
.Op Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after
|
||||
.Fl p Ar port
|
||||
.Pp
|
||||
.Nm
|
||||
@@ -64,38 +55,41 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility and the console driver work together to support
|
||||
mouse operation in the text console and user programs.
|
||||
They virtualize the mouse and provide user programs with mouse data
|
||||
in the standard format
|
||||
(see
|
||||
.Xr sysmouse 4 ) .
|
||||
.Pp
|
||||
The mouse daemon listens to the specified port for mouse data,
|
||||
interprets and then passes it via ioctls to the console driver.
|
||||
The mouse daemon
|
||||
reports translation movement, button press/release
|
||||
utility and the
|
||||
.Xr moused 8
|
||||
driver work together to support legacy devices like COM,
|
||||
.Xr ams 4
|
||||
mices and X10 remotes as well.
|
||||
.Xr psm 4 ,
|
||||
.Xr ums 4
|
||||
and some other devices are supported too but not recomended to use with
|
||||
.Nm
|
||||
unless kernel is compiled without
|
||||
.Dq option EVDEV_SUPPORT .
|
||||
The
|
||||
.Nm
|
||||
listens to the specified port for mouse data, decodes and then passes
|
||||
it via input event device a.k.a evdev to consumer aplications like
|
||||
.Xr moused 8
|
||||
or
|
||||
.Xr libinput 1 .
|
||||
It does not display the mouse pointer on the screen or provide cut and
|
||||
paste functions.
|
||||
The msconv daemon converts translation movement, button press/release
|
||||
events and movement of the roller or the wheel if available.
|
||||
The roller/wheel movement is reported as
|
||||
.Dq Z
|
||||
axis movement.
|
||||
.Pp
|
||||
The console driver will display the mouse pointer on the screen
|
||||
and provide cut and paste functions if the mouse pointer is enabled
|
||||
in the virtual console via
|
||||
.Xr vidcontrol 1 .
|
||||
If
|
||||
.Xr sysmouse 4
|
||||
is opened by the user program, the console driver also passes the mouse
|
||||
data to the device so that the user program will see it.
|
||||
.Pp
|
||||
If the mouse daemon receives the signal
|
||||
If the
|
||||
.Nm
|
||||
receives the signal
|
||||
.Dv SIGHUP ,
|
||||
it will reopen the mouse port and reinitialize itself.
|
||||
Useful if
|
||||
the mouse is attached/detached while the system is suspended.
|
||||
.Pp
|
||||
If the mouse daemon receives the signal
|
||||
If the
|
||||
.Nm
|
||||
receives the signal
|
||||
.Dv SIGUSR1 ,
|
||||
it will stop passing mouse events.
|
||||
Sending the signal
|
||||
@@ -106,19 +100,6 @@ interrupted by accidentally touching the mouse pad.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl 3
|
||||
Emulate the third (middle) button for 2-button mice.
|
||||
It is emulated
|
||||
by pressing the left and right physical buttons simultaneously.
|
||||
.It Fl C Ar threshold
|
||||
Set double click speed as the maximum interval in msec between button clicks.
|
||||
Without this option, the default value of 500 msec will be assumed.
|
||||
This option will have effect only on the cut and paste operations
|
||||
in the text mode console.
|
||||
The user program which is reading mouse data
|
||||
via
|
||||
.Xr sysmouse 4
|
||||
will not be affected.
|
||||
.It Fl D
|
||||
Lower DTR on the serial port.
|
||||
This option is valid only if
|
||||
@@ -128,46 +109,8 @@ The DTR line may need to be dropped for a 3-button mouse
|
||||
to operate in the
|
||||
.Ar mousesystems
|
||||
mode.
|
||||
.It Fl E Ar timeout
|
||||
When the third button emulation is enabled
|
||||
(see above),
|
||||
the
|
||||
.Nm
|
||||
utility waits
|
||||
.Ar timeout
|
||||
msec at most before deciding whether two buttons are being pressed
|
||||
simultaneously.
|
||||
The default timeout is 100 msec.
|
||||
.It Fl F Ar rate
|
||||
Set the report rate (reports/sec) of the device if supported.
|
||||
.It Fl L Ar distance
|
||||
When
|
||||
.Dq Virtual Scrolling
|
||||
is enabled, the
|
||||
.Fl L
|
||||
option can be used to set the
|
||||
.Ar distance
|
||||
(in pixels) that the mouse must move before a scroll event
|
||||
is generated.
|
||||
This effectively controls the scrolling speed.
|
||||
The default
|
||||
.Ar distance
|
||||
is 2 pixels.
|
||||
.It Fl H
|
||||
Enable
|
||||
.Dq Horizontal Virtual Scrolling .
|
||||
With this option set, holding the middle mouse
|
||||
button down will cause motion to be interpreted as
|
||||
horizontal scrolling.
|
||||
Use the
|
||||
.Fl U
|
||||
option to set the distance the mouse must move before the scrolling mode is
|
||||
activated and the
|
||||
.Fl L
|
||||
option to set the scrolling speed.
|
||||
This option may be used with or without the
|
||||
.Fl V
|
||||
option.
|
||||
.It Fl I Ar file
|
||||
Write the process id of the
|
||||
.Nm
|
||||
@@ -199,89 +142,6 @@ mode.
|
||||
.It Fl S Ar baudrate
|
||||
Select the baudrate for the serial port (1200 to 9600).
|
||||
Not all serial mice support this option.
|
||||
.It Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after
|
||||
Terminate drift.
|
||||
Use this option if mouse pointer slowly wanders when mouse is not moved.
|
||||
Movements up to
|
||||
.Ar distance
|
||||
(for example 4) pixels (X+Y) in
|
||||
.Ar time
|
||||
msec (default 500) are ignored, except during
|
||||
.Ar after
|
||||
msec (default 4000) since last real mouse movement.
|
||||
.It Fl V
|
||||
Enable
|
||||
.Dq Virtual Scrolling .
|
||||
With this option set, holding the middle mouse
|
||||
button down will cause motion to be interpreted as scrolling.
|
||||
Use the
|
||||
.Fl U
|
||||
option to set the distance the mouse must move before the scrolling mode is
|
||||
activated and the
|
||||
.Fl L
|
||||
option to set the scrolling speed.
|
||||
.It Fl U Ar distance
|
||||
When
|
||||
.Dq Virtual Scrolling
|
||||
is enabled, the
|
||||
.Fl U
|
||||
option can be used to set the
|
||||
.Ar distance
|
||||
(in pixels) that the mouse must move before the scrolling
|
||||
mode is activated.
|
||||
The default
|
||||
.Ar distance
|
||||
is 3 pixels.
|
||||
.It Fl A Ar exp Ns Op , Ns Ar offset
|
||||
Apply exponential (dynamic) acceleration to mouse movements:
|
||||
the faster you move the mouse, the more it will be accelerated.
|
||||
That means that small mouse movements are not accelerated,
|
||||
so they are still very accurate, while a faster movement will
|
||||
drive the pointer quickly across the screen.
|
||||
.Pp
|
||||
The
|
||||
.Ar exp
|
||||
value specifies the exponent, which is basically
|
||||
the amount of acceleration.
|
||||
Useful values are in the range 1.1 to 2.0, but it depends on
|
||||
your mouse hardware and your personal preference.
|
||||
A value of 1.0 means no exponential acceleration.
|
||||
A value of 2.0 means squared acceleration (i.e. if
|
||||
you move the mouse twice as fast, the pointer will move
|
||||
four times as fast on the screen).
|
||||
Values beyond 2.0 are possible but not recommended.
|
||||
A good value to start is probably 1.5.
|
||||
.Pp
|
||||
The optional
|
||||
.Ar offset
|
||||
value specifies the distance at which the acceleration begins.
|
||||
The default is 1.0, which means that the acceleration is applied
|
||||
to movements larger than one unit.
|
||||
If you specify a larger value, it takes more speed for
|
||||
the acceleration to kick in, i.e. the speed range for
|
||||
small and accurate movements is wider.
|
||||
Usually the default should be sufficient, but if you're
|
||||
not satisfied with the behaviour, try a value of 2.0.
|
||||
.Pp
|
||||
Note that the
|
||||
.Fl A
|
||||
option interacts badly with the X server's own acceleration,
|
||||
which doesn't work very well anyway.
|
||||
Therefore it is recommended to switch it off if necessary:
|
||||
.Dq xset m 1 .
|
||||
.It Fl a Ar X Ns Op , Ns Ar Y
|
||||
Accelerate or decelerate the mouse input.
|
||||
This is a linear acceleration only.
|
||||
Values less than 1.0 slow down movement, values greater than 1.0 speed it
|
||||
up.
|
||||
Specifying only one value sets the acceleration for both axes.
|
||||
.Pp
|
||||
You can use the
|
||||
.Fl a
|
||||
and
|
||||
.Fl A
|
||||
options at the same time to have the combined effect
|
||||
of linear and exponential acceleration.
|
||||
.It Fl c
|
||||
Some mice report middle button down events
|
||||
as if the left and right buttons are being pressed.
|
||||
@@ -339,18 +199,6 @@ Refer to
|
||||
in
|
||||
.Xr psm 4
|
||||
for more information on this.
|
||||
.It Fl m Ar N=M
|
||||
Assign the physical button
|
||||
.Ar M
|
||||
to the logical button
|
||||
.Ar N .
|
||||
You may specify as many instances of this option as you like.
|
||||
More than one physical button may be assigned to a logical button at the
|
||||
same time.
|
||||
In this case the logical button will be down,
|
||||
if either of the assigned physical buttons is held down.
|
||||
Do not put space around
|
||||
.Ql = .
|
||||
.It Fl p Ar port
|
||||
Use
|
||||
.Ar port
|
||||
@@ -382,7 +230,7 @@ you need to use this option only if the
|
||||
.Nm
|
||||
utility is not able to detect the protocol automatically
|
||||
(see
|
||||
.Sx "Configuring Mouse Daemon" ) .
|
||||
.Sx "Configuring Mouse Protocol Conversion Daemon" ) .
|
||||
.Pp
|
||||
Note that if a protocol type is specified with this option, the
|
||||
.Fl P
|
||||
@@ -475,73 +323,9 @@ For the USB mouse,
|
||||
.Ar auto
|
||||
is the only protocol type available for the USB mouse
|
||||
and should be specified for any USB mice, regardless of the brand.
|
||||
.It Fl w Ar N
|
||||
Make the physical button
|
||||
.Ar N
|
||||
act as the wheel mode button.
|
||||
While this button is pressed, X and Y axis movement is reported to be zero
|
||||
and the Y axis movement is mapped to Z axis.
|
||||
You may further map the Z axis movement to virtual buttons by the
|
||||
.Fl z
|
||||
option below.
|
||||
.It Fl z Ar target
|
||||
Map Z axis (roller/wheel) movement to another axis or to virtual buttons.
|
||||
Valid
|
||||
.Ar target
|
||||
maybe:
|
||||
.Bl -tag -compact -width x__
|
||||
.It Ar x
|
||||
.It Ar y
|
||||
X or Y axis movement will be reported when the Z axis movement is detected.
|
||||
.It Ar N
|
||||
Report down events for the virtual buttons
|
||||
.Ar N
|
||||
and
|
||||
.Ar N+1
|
||||
respectively when negative and positive Z axis movement
|
||||
is detected.
|
||||
There do not need to be physical buttons
|
||||
.Ar N
|
||||
and
|
||||
.Ar N+1 .
|
||||
Note that mapping to logical buttons is carried out after mapping
|
||||
from the Z axis movement to the virtual buttons is done.
|
||||
.It Ar N1 N2
|
||||
Report down events for the virtual buttons
|
||||
.Ar N1
|
||||
and
|
||||
.Ar N2
|
||||
respectively when negative and positive Z axis movement
|
||||
is detected.
|
||||
.It Ar N1 N2 N3 N4
|
||||
This is useful for the mouse with two wheels of which
|
||||
the second wheel is used to generate horizontal scroll action,
|
||||
and for the mouse which has a knob or a stick which can detect
|
||||
the horizontal force applied by the user.
|
||||
.Pp
|
||||
The motion of the second wheel will be mapped to the buttons
|
||||
.Ar N3 ,
|
||||
for the negative direction, and
|
||||
.Ar N4 ,
|
||||
for the positive direction.
|
||||
If the buttons
|
||||
.Ar N3
|
||||
and
|
||||
.Ar N4
|
||||
actually exist in this mouse, their actions will not be detected.
|
||||
.Pp
|
||||
Note that horizontal movement or second roller/wheel movement may not
|
||||
always be detected,
|
||||
because there appears to be no accepted standard as to how it is encoded.
|
||||
.Pp
|
||||
Note also that some mice think left is the negative horizontal direction;
|
||||
others may think otherwise.
|
||||
Moreover, there are some mice whose two wheels are both mounted vertically,
|
||||
and the direction of the second vertical wheel does not match the
|
||||
first one.
|
||||
.El
|
||||
.El
|
||||
.Ss Configuring Mouse Daemon
|
||||
.Ss Configuring Mouse Protocol Conversion Daemon
|
||||
The first thing you need to know is the interface type
|
||||
of the mouse you are going to use.
|
||||
It can be determined by looking at the connector of the mouse.
|
||||
@@ -673,13 +457,17 @@ protocol.
|
||||
.El
|
||||
.Pp
|
||||
To test if the selected protocol type is correct for the given mouse,
|
||||
enable the mouse pointer in the current virtual console,
|
||||
ensure the
|
||||
.Xr moused 8
|
||||
is running in auto port mode,
|
||||
.Pp
|
||||
.Dl "vidcontrol -m on"
|
||||
.Dl "moused -p auto"
|
||||
.Pp
|
||||
start the mouse daemon in the foreground mode,
|
||||
start the
|
||||
.Nm
|
||||
in the foreground mode,
|
||||
.Pp
|
||||
.Dl "moused -f -p <selected_port> -t <selected_protocol>"
|
||||
.Dl "msconvd -f -p <selected_port> -t <selected_protocol>"
|
||||
.Pp
|
||||
and see if the mouse pointer travels correctly
|
||||
according to the mouse movement.
|
||||
@@ -688,19 +476,20 @@ clicking the left, right and middle buttons.
|
||||
Type ^C to stop
|
||||
the command.
|
||||
.Ss Multiple Mice
|
||||
As many instances of the mouse daemon as the number of mice attached to
|
||||
the system may be run simultaneously; one
|
||||
instance for each mouse.
|
||||
As many instances of the
|
||||
.Nm
|
||||
as the number of mice attached to the system may be run simultaneously;
|
||||
one instance for each mouse.
|
||||
This is useful if the user wants to use the built-in PS/2 pointing device
|
||||
of a laptop computer while on the road, but wants to use a serial
|
||||
mouse when s/he attaches the system to the docking station in the office.
|
||||
Run two mouse daemons and tell the application program
|
||||
(such as the
|
||||
.Tn "X\ Window System" )
|
||||
to use
|
||||
.Xr sysmouse 4 ,
|
||||
then the application program will always see mouse data from either mouse.
|
||||
When the serial mouse is not attached, the corresponding mouse daemon
|
||||
Run two
|
||||
.Nm
|
||||
and then the application program e.g.
|
||||
.Xr moused 8
|
||||
will always see mouse data from either mouse.
|
||||
When the serial mouse is not attached, the corresponding
|
||||
.Nm
|
||||
will not detect any movement or button state change and the application
|
||||
program will only see mouse data coming from the daemon for the
|
||||
PS/2 mouse.
|
||||
@@ -709,18 +498,18 @@ are moved at the same time in this configuration,
|
||||
the mouse pointer will travel across the screen just as if movement of
|
||||
the mice is combined all together.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/consolectl -compact
|
||||
.It Pa /dev/consolectl
|
||||
device to control the console
|
||||
.Bl -tag -width /dev/input/event%d -compact
|
||||
.It Pa /dev/input/event%d
|
||||
input event device
|
||||
.It Pa /dev/psm%d
|
||||
PS/2 mouse driver
|
||||
.It Pa /dev/sysmouse
|
||||
virtualized mouse driver
|
||||
.It Pa /dev/cuau%d
|
||||
serial port
|
||||
.It Pa /dev/ttyv%d
|
||||
virtual consoles
|
||||
.It Pa /dev/ums%d
|
||||
USB mouse driver
|
||||
.It Pa /var/run/moused.pid
|
||||
.It Pa /var/run/msconvd.pid
|
||||
process id of the currently running
|
||||
.Nm
|
||||
utility
|
||||
@@ -728,7 +517,7 @@ utility
|
||||
UNIX-domain stream socket for X10 MouseRemote events
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Dl "moused -p /dev/cuau0 -i type"
|
||||
.Dl "msconvd -p /dev/cuau0 -i type"
|
||||
.Pp
|
||||
Let the
|
||||
.Nm
|
||||
@@ -737,8 +526,7 @@ utility determine the protocol type of the mouse at the serial port
|
||||
If successful, the command will print the type, otherwise it will say
|
||||
.Dq Li unknown .
|
||||
.Bd -literal -offset indent
|
||||
moused -p /dev/cuau0
|
||||
vidcontrol -m on
|
||||
msconvd -p /dev/cuau0
|
||||
.Ed
|
||||
.Pp
|
||||
If the
|
||||
@@ -746,10 +534,9 @@ If the
|
||||
utility is able to identify the protocol type of the mouse at the specified
|
||||
port automatically, you can start the daemon without the
|
||||
.Fl t
|
||||
option and enable the mouse pointer in the text console as above.
|
||||
option.
|
||||
.Bd -literal -offset indent
|
||||
moused -p /dev/mouse -t microsoft
|
||||
vidcontrol -m on
|
||||
msconvd -p /dev/mouse -t microsoft
|
||||
.Ed
|
||||
.Pp
|
||||
Start the mouse daemon on the serial port
|
||||
@@ -760,39 +547,26 @@ is explicitly specified by the
|
||||
.Fl t
|
||||
option.
|
||||
.Pp
|
||||
.Dl "moused -p /dev/mouse -m 1=3 -m 3=1"
|
||||
.Pp
|
||||
Assign the physical button 3 (right button) to the logical button 1
|
||||
(logical left) and the physical button 1 (left) to the logical
|
||||
button 3 (logical right).
|
||||
This will effectively swap the left and right buttons.
|
||||
.Pp
|
||||
.Dl "moused -p /dev/mouse -t intellimouse -z 4"
|
||||
.Pp
|
||||
Report negative Z axis movement (i.e., mouse wheel) as the button 4 pressed
|
||||
and positive Z axis movement (i.e., mouse wheel) as the button 5 pressed.
|
||||
.Pp
|
||||
If you add
|
||||
.Pp
|
||||
.Dl "ALL ALL = NOPASSWD: /usr/bin/killall -USR1 moused"
|
||||
.Dl "ALL ALL = NOPASSWD: /usr/bin/killall -USR1 msconvd"
|
||||
.Pp
|
||||
to your
|
||||
.Pa /usr/local/etc/sudoers
|
||||
file, and bind
|
||||
.Pp
|
||||
.Dl "killall -USR1 moused"
|
||||
.Dl "killall -USR1 msconvd"
|
||||
.Pp
|
||||
to a key in your window manager, you can suspend mouse events on your laptop if
|
||||
you keep brushing over the mouse pad while typing.
|
||||
.Sh SEE ALSO
|
||||
.Xr moused 8 ,
|
||||
.Xr kill 1 ,
|
||||
.Xr vidcontrol 1 ,
|
||||
.Xr xset 1 ,
|
||||
.Xr keyboard 4 ,
|
||||
.Xr psm 4 ,
|
||||
.Xr screen 4 ,
|
||||
.Xr sysmouse 4 ,
|
||||
.Xr ums 4
|
||||
.Xr uart 4
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
@@ -809,14 +583,23 @@ for the given serial mouse.
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 15.0 .
|
||||
It is a cropped-down version of
|
||||
.Fx 14.0
|
||||
.Xr moused 8
|
||||
utility originated back in
|
||||
.Fx 2.2 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
utility is based on
|
||||
.Xr moused 8
|
||||
written by
|
||||
.An Michael Smith Aq Mt msmith@FreeBSD.org .
|
||||
This manual page was written by
|
||||
This manual page is extracted from
|
||||
.Xr moused 8
|
||||
page written by
|
||||
.An Mike Pritchard Aq Mt mpp@FreeBSD.org .
|
||||
The command and manual page have since been updated by
|
||||
.An Kazutaka Yokota Aq Mt yokota@FreeBSD.org .
|
||||
@@ -830,21 +613,7 @@ treat the tapping action
|
||||
as fourth button events.
|
||||
Use the option
|
||||
.Dq Fl m Li 1=4
|
||||
of
|
||||
.Xr moused 8
|
||||
for these models
|
||||
to obtain the same effect as the other pad devices.
|
||||
.Pp
|
||||
Cut and paste functions in the virtual console assume that there
|
||||
are three buttons on the mouse.
|
||||
The logical button 1 (logical left) selects a region of text in the
|
||||
console and copies it to the cut buffer.
|
||||
The logical button 3 (logical right) extends the selected region.
|
||||
The logical button 2 (logical middle) pastes the selected text
|
||||
at the text cursor position.
|
||||
If the mouse has only two buttons, the middle, `paste' button
|
||||
is not available.
|
||||
To obtain the paste function, use the
|
||||
.Fl 3
|
||||
option to emulate the middle button, or use the
|
||||
.Fl m
|
||||
option to assign the physical right button to the logical middle button:
|
||||
.Dq Fl m Li 2=3 .
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user