mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-20 06:50:06 +01:00
tools: add a tool to change kernel devices
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
def17850d1
commit
3bf7d50230
4 changed files with 321 additions and 1 deletions
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
libevdev-events
|
||||
touchpad-edge-detector
|
||||
mouse-dpi-tool
|
||||
libevdev-tweak-device
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
noinst_PROGRAMS = libevdev-events
|
||||
bin_PROGRAMS = \
|
||||
touchpad-edge-detector \
|
||||
mouse-dpi-tool
|
||||
mouse-dpi-tool \
|
||||
libevdev-tweak-device
|
||||
|
||||
AM_CPPFLAGS = $(GCC_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/libevdev
|
||||
libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
|
||||
|
|
@ -14,3 +15,7 @@ touchpad_edge_detector_LDADD = $(libevdev_ldadd)
|
|||
|
||||
mouse_dpi_tool_SOURCES = mouse-dpi-tool.c
|
||||
mouse_dpi_tool_LDADD = $(libevdev_ldadd)
|
||||
|
||||
libevdev_tweak_device_SOURCES = libevdev-tweak-device.c
|
||||
libevdev_tweak_device_LDADD = $(libevdev_ldadd)
|
||||
libevdev_tweak_device_MANS = libevdev-tweak-device.1
|
||||
|
|
|
|||
59
tools/libevdev-tweak-device.1
Normal file
59
tools/libevdev-tweak-device.1
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
.TH LIBEVDEV-TWEAK-DEVICE "1"
|
||||
.SH NAME
|
||||
libevdev-tweak-device \- modify an evdev kernel device
|
||||
.SH SYNOPSIS
|
||||
.B libevdev-tweak-device
|
||||
--abs ABS_X [--min a] [--max b] [--res c] [--fuzz d] [--flat e]
|
||||
/dev/input/eventX
|
||||
.PP
|
||||
.B libevdev-tweak-device
|
||||
--led LED_NUML --on|--off /dev/input/eventX
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The
|
||||
.I libevdev-tweak-device
|
||||
tool changes the properties of the evdev kernel device at
|
||||
.I /dev/input/eventX.
|
||||
Currently this may be used to force an LED on or off, or to change the
|
||||
properties of an absolute axis (e.g. its minimum/maximum range or
|
||||
resolution). Changes are permanent until the device is removed.
|
||||
.SH OPTIONS
|
||||
.SS Changing absolute axes
|
||||
.TP 8
|
||||
.B --abs axis
|
||||
Change the given named ABS_ kernel axis, e.g. ABS_X. For a full list, see linux/input.h.
|
||||
Each of the options
|
||||
.B min, max, res, fuzz, flat
|
||||
may be given.
|
||||
.TP 8
|
||||
.B --min v
|
||||
Set the absinfo minimum to the value v
|
||||
.TP 8
|
||||
.B --max v
|
||||
Set the absinfo maximum to the value v
|
||||
.TP 8
|
||||
.B --res v
|
||||
Set the absinfo resolution to the value v
|
||||
.TP 8
|
||||
.B --fuzz v
|
||||
Set the absinfo fuzz to the value v
|
||||
.TP 8
|
||||
.B --flat v
|
||||
Set the absinfo flat to the value v
|
||||
.PP
|
||||
.SS Toggling LEDs
|
||||
.TP 8
|
||||
.B --led led
|
||||
Change the given LED, e.g. LED_NUML. For a full list, see linux/input.h.
|
||||
.TP 8
|
||||
.B --on
|
||||
Change the LED state to on
|
||||
.TP 8
|
||||
.B --off
|
||||
Change the LED state to off
|
||||
.SH NOTES
|
||||
.PP
|
||||
The kernel does not notify processes about absinfo property changes. Any
|
||||
process that has previously obtained the absinfo from the device will remain
|
||||
on the old information. This makes using this tool potentially racy, use
|
||||
with caution.
|
||||
255
tools/libevdev-tweak-device.c
Normal file
255
tools/libevdev-tweak-device.c
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright © 2014 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <config.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
|
||||
static unsigned int changes; /* bitmask of changes */
|
||||
static struct input_absinfo absinfo;
|
||||
static int axis;
|
||||
static int led;
|
||||
static int led_state = -1;
|
||||
const char *path;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("%s --abs <axis> [--min min] [--max max] [--res res] [--fuzz fuzz] [--flat flat] /dev/input/eventXYZ\n"
|
||||
"\tChange the absinfo struct for the named axis\n"
|
||||
"%s --led <led> --on|--off /dev/input/eventXYZ\n"
|
||||
"\tEnable or disable the named LED\n",
|
||||
program_invocation_short_name, program_invocation_short_name);
|
||||
}
|
||||
|
||||
enum opts {
|
||||
OPT_ABS = 1 << 0,
|
||||
OPT_MIN = 1 << 1,
|
||||
OPT_MAX = 1 << 2,
|
||||
OPT_FUZZ = 1 << 3,
|
||||
OPT_FLAT = 1 << 4,
|
||||
OPT_RES = 1 << 5,
|
||||
OPT_LED = 1 << 6,
|
||||
OPT_ON = 1 << 7,
|
||||
OPT_OFF = 1 << 8,
|
||||
OPT_HELP = 1 << 9,
|
||||
};
|
||||
|
||||
static int
|
||||
parse_options(int argc, char **argv)
|
||||
{
|
||||
int rc = 1;
|
||||
int c;
|
||||
int option_index = 0;
|
||||
static struct option opts[] = {
|
||||
{ "abs", 1, 0, OPT_ABS },
|
||||
{ "min", 1, 0, OPT_MIN },
|
||||
{ "max", 1, 0, OPT_MAX },
|
||||
{ "fuzz", 1, 0, OPT_FUZZ },
|
||||
{ "flat", 1, 0, OPT_FLAT },
|
||||
{ "res", 1, 0, OPT_RES },
|
||||
{ "led", 1, 0, OPT_LED },
|
||||
{ "on", 0, 0, OPT_ON },
|
||||
{ "off", 0, 0, OPT_OFF },
|
||||
{ "help", 0, 0, OPT_HELP },
|
||||
{ NULL, 0, 0, 0 },
|
||||
};
|
||||
|
||||
if (argc < 2)
|
||||
goto error;
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "h", opts, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
case OPT_HELP:
|
||||
goto error;
|
||||
case OPT_ABS:
|
||||
if (changes & OPT_LED)
|
||||
goto error;
|
||||
|
||||
axis = libevdev_event_code_from_name(EV_ABS,
|
||||
optarg);
|
||||
if (axis == -1)
|
||||
goto error;
|
||||
break;
|
||||
case OPT_LED:
|
||||
if (changes & OPT_ABS)
|
||||
goto error;
|
||||
|
||||
led = libevdev_event_code_from_name(EV_LED,
|
||||
optarg);
|
||||
if (led == -1)
|
||||
goto error;
|
||||
break;
|
||||
case OPT_MIN:
|
||||
absinfo.minimum = atoi(optarg);
|
||||
break;
|
||||
case OPT_MAX:
|
||||
absinfo.maximum = atoi(optarg);
|
||||
break;
|
||||
case OPT_FUZZ:
|
||||
absinfo.fuzz = atoi(optarg);
|
||||
break;
|
||||
case OPT_FLAT:
|
||||
absinfo.flat = atoi(optarg);
|
||||
break;
|
||||
case OPT_RES:
|
||||
absinfo.resolution = atoi(optarg);
|
||||
break;
|
||||
case OPT_ON:
|
||||
if (led_state != -1)
|
||||
goto error;
|
||||
led_state = 1;
|
||||
break;
|
||||
case OPT_OFF:
|
||||
if (led_state != -1)
|
||||
goto error;
|
||||
led_state = 0;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
changes |= c;
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
goto error;
|
||||
path = argv[optind];
|
||||
|
||||
rc = 0;
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
set_abs(struct libevdev *dev)
|
||||
{
|
||||
int rc;
|
||||
struct input_absinfo abs;
|
||||
const struct input_absinfo *a;
|
||||
|
||||
if ((a = libevdev_get_abs_info(dev, axis)) == NULL) {
|
||||
fprintf(stderr,
|
||||
"Device '%s' doesn't have axis %s\n",
|
||||
libevdev_get_name(dev),
|
||||
libevdev_event_code_get_name(EV_ABS, axis));
|
||||
return;
|
||||
}
|
||||
|
||||
abs = *a;
|
||||
if (changes & OPT_MIN)
|
||||
abs.minimum = absinfo.minimum;
|
||||
if (changes & OPT_MAX)
|
||||
abs.maximum = absinfo.maximum;
|
||||
if (changes & OPT_FUZZ)
|
||||
abs.fuzz = absinfo.fuzz;
|
||||
if (changes & OPT_FLAT)
|
||||
abs.flat = absinfo.flat;
|
||||
if (changes & OPT_RES)
|
||||
abs.resolution = absinfo.resolution;
|
||||
|
||||
rc = libevdev_kernel_set_abs_info(dev, axis, &abs);
|
||||
if (rc != 0)
|
||||
fprintf(stderr,
|
||||
"Failed to set absinfo %s: %s",
|
||||
libevdev_event_code_get_name(EV_ABS, axis),
|
||||
strerror(-rc));
|
||||
}
|
||||
|
||||
static void
|
||||
set_led(struct libevdev *dev)
|
||||
{
|
||||
int rc;
|
||||
enum libevdev_led_value state =
|
||||
led_state ? LIBEVDEV_LED_ON : LIBEVDEV_LED_OFF;
|
||||
|
||||
if (!libevdev_has_event_code(dev, EV_LED, led)) {
|
||||
fprintf(stderr,
|
||||
"Device '%s' doesn't have %s\n",
|
||||
libevdev_get_name(dev),
|
||||
libevdev_event_code_get_name(EV_LED, axis));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
rc = libevdev_kernel_set_led_value(dev, led, state);
|
||||
if (rc != 0)
|
||||
fprintf(stderr,
|
||||
"Failed to set LED %s: %s",
|
||||
libevdev_event_code_get_name(EV_LED, led),
|
||||
strerror(-rc));
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct libevdev *dev = NULL;
|
||||
int fd;
|
||||
int rc = 1;
|
||||
|
||||
rc = parse_options(argc, argv);
|
||||
if (rc != 0 || !path) {
|
||||
usage();
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open device");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = libevdev_new_from_fd(fd, &dev);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (changes & OPT_ABS)
|
||||
set_abs(dev);
|
||||
else if (changes & OPT_LED)
|
||||
set_led(dev);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"++?????++ Out of Cheese Error. Redo From Start.\n");
|
||||
|
||||
out:
|
||||
libevdev_free(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue