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:
Vladimir Kondratyev
2025-09-05 00:07:25 +03:00
parent d4bfebf917
commit aef807876c
24 changed files with 10007 additions and 1339 deletions
+6 -2
View File
@@ -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
+1
View File
@@ -273,6 +273,7 @@ JAILPACKAGE= jail
.if ${MK_LEGACY_CONSOLE} != "no"
CONFGROUPS+= CONSOLE
CONSOLE+= moused
CONSOLE+= msconvd
CONSOLE+= syscons
CONSOLEPACKAGE= console-tools
.endif
+61
View File
@@ -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 $*
+7
View File
@@ -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}
+3 -9
View File
@@ -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>
-17
View File
@@ -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
+28
View File
@@ -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
+538
View File
@@ -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
+43
View File
@@ -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
+422
View File
@@ -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 devices 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
+369
View File
@@ -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
+173
View File
@@ -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));
}
+35
View File
@@ -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
+86
View File
@@ -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;
}
+194
View File
@@ -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))
+423
View File
@@ -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 */
+413
View File
@@ -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 */
+8
View File
@@ -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