mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-08 11:19:14 +02:00
evdev: init axis range warnings for touch devices too
Move the code from the touchpad code into the more generic evdev code Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
cff370fcd0
commit
4bb3da4115
5 changed files with 134 additions and 68 deletions
|
|
@ -279,39 +279,6 @@ tp_get_delta(struct tp_touch *t)
|
||||||
return tp_normalize_delta(t->tp, delta);
|
return tp_normalize_delta(t->tp, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
tp_check_axis_range(struct tp_dispatch *tp,
|
|
||||||
unsigned int code,
|
|
||||||
int value)
|
|
||||||
{
|
|
||||||
int min, max;
|
|
||||||
|
|
||||||
switch(code) {
|
|
||||||
case ABS_X:
|
|
||||||
case ABS_MT_POSITION_X:
|
|
||||||
min = tp->warning_range.min.x;
|
|
||||||
max = tp->warning_range.max.x;
|
|
||||||
break;
|
|
||||||
case ABS_Y:
|
|
||||||
case ABS_MT_POSITION_Y:
|
|
||||||
min = tp->warning_range.min.y;
|
|
||||||
max = tp->warning_range.max.y;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value < min || value > max) {
|
|
||||||
log_info_ratelimit(tp_libinput_context(tp),
|
|
||||||
&tp->warning_range.range_warn_limit,
|
|
||||||
"Axis %#x value %d is outside expected range [%d, %d]\n"
|
|
||||||
"See %s/absolute_coordinate_ranges.html for details\n",
|
|
||||||
code, value, min, max,
|
|
||||||
HTTP_DOC_LINK);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tp_process_absolute(struct tp_dispatch *tp,
|
tp_process_absolute(struct tp_dispatch *tp,
|
||||||
const struct input_event *e,
|
const struct input_event *e,
|
||||||
|
|
@ -321,14 +288,18 @@ tp_process_absolute(struct tp_dispatch *tp,
|
||||||
|
|
||||||
switch(e->code) {
|
switch(e->code) {
|
||||||
case ABS_MT_POSITION_X:
|
case ABS_MT_POSITION_X:
|
||||||
tp_check_axis_range(tp, e->code, e->value);
|
evdev_device_check_abs_axis_range(tp->device,
|
||||||
|
e->code,
|
||||||
|
e->value);
|
||||||
t->point.x = e->value;
|
t->point.x = e->value;
|
||||||
t->millis = time;
|
t->millis = time;
|
||||||
t->dirty = true;
|
t->dirty = true;
|
||||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||||
break;
|
break;
|
||||||
case ABS_MT_POSITION_Y:
|
case ABS_MT_POSITION_Y:
|
||||||
tp_check_axis_range(tp, e->code, e->value);
|
evdev_device_check_abs_axis_range(tp->device,
|
||||||
|
e->code,
|
||||||
|
e->value);
|
||||||
t->point.y = e->value;
|
t->point.y = e->value;
|
||||||
t->millis = time;
|
t->millis = time;
|
||||||
t->dirty = true;
|
t->dirty = true;
|
||||||
|
|
@ -363,14 +334,18 @@ tp_process_absolute_st(struct tp_dispatch *tp,
|
||||||
|
|
||||||
switch(e->code) {
|
switch(e->code) {
|
||||||
case ABS_X:
|
case ABS_X:
|
||||||
tp_check_axis_range(tp, e->code, e->value);
|
evdev_device_check_abs_axis_range(tp->device,
|
||||||
|
e->code,
|
||||||
|
e->value);
|
||||||
t->point.x = e->value;
|
t->point.x = e->value;
|
||||||
t->millis = time;
|
t->millis = time;
|
||||||
t->dirty = true;
|
t->dirty = true;
|
||||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||||
break;
|
break;
|
||||||
case ABS_Y:
|
case ABS_Y:
|
||||||
tp_check_axis_range(tp, e->code, e->value);
|
evdev_device_check_abs_axis_range(tp->device,
|
||||||
|
e->code,
|
||||||
|
e->value);
|
||||||
t->point.y = e->value;
|
t->point.y = e->value;
|
||||||
t->millis = time;
|
t->millis = time;
|
||||||
t->dirty = true;
|
t->dirty = true;
|
||||||
|
|
@ -2241,32 +2216,10 @@ tp_init_hysteresis(struct tp_dispatch *tp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
tp_init_range_warnings(struct tp_dispatch *tp,
|
|
||||||
struct evdev_device *device,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
const struct input_absinfo *x, *y;
|
|
||||||
|
|
||||||
x = device->abs.absinfo_x;
|
|
||||||
y = device->abs.absinfo_y;
|
|
||||||
|
|
||||||
tp->warning_range.min.x = x->minimum - 0.05 * width;
|
|
||||||
tp->warning_range.min.y = y->minimum - 0.05 * height;
|
|
||||||
tp->warning_range.max.x = x->maximum + 0.05 * width;
|
|
||||||
tp->warning_range.max.y = y->maximum + 0.05 * height;
|
|
||||||
|
|
||||||
/* One warning every 5 min is enough */
|
|
||||||
ratelimit_init(&tp->warning_range.range_warn_limit, s2us(3000), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tp_init(struct tp_dispatch *tp,
|
tp_init(struct tp_dispatch *tp,
|
||||||
struct evdev_device *device)
|
struct evdev_device *device)
|
||||||
{
|
{
|
||||||
int width, height;
|
|
||||||
|
|
||||||
tp->base.interface = &tp_interface;
|
tp->base.interface = &tp_interface;
|
||||||
tp->device = device;
|
tp->device = device;
|
||||||
|
|
||||||
|
|
@ -2278,10 +2231,7 @@ tp_init(struct tp_dispatch *tp,
|
||||||
if (!tp_init_slots(tp, device))
|
if (!tp_init_slots(tp, device))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
width = device->abs.dimensions.x;
|
evdev_device_init_abs_range_warnings(device);
|
||||||
height = device->abs.dimensions.y;
|
|
||||||
|
|
||||||
tp_init_range_warnings(tp, device, width, height);
|
|
||||||
|
|
||||||
tp->reports_distance = libevdev_has_event_code(device->evdev,
|
tp->reports_distance = libevdev_has_event_code(device->evdev,
|
||||||
EV_ABS,
|
EV_ABS,
|
||||||
|
|
|
||||||
|
|
@ -247,11 +247,6 @@ struct tp_dispatch {
|
||||||
|
|
||||||
struct device_coords hysteresis_margin;
|
struct device_coords hysteresis_margin;
|
||||||
|
|
||||||
struct {
|
|
||||||
struct device_coords min, max;
|
|
||||||
struct ratelimit range_warn_limit;
|
|
||||||
} warning_range;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
double x_scale_coeff;
|
double x_scale_coeff;
|
||||||
double y_scale_coeff;
|
double y_scale_coeff;
|
||||||
|
|
|
||||||
|
|
@ -852,11 +852,13 @@ fallback_process_touch(struct fallback_dispatch *dispatch,
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_UP;
|
dispatch->pending_event = EVDEV_ABSOLUTE_MT_UP;
|
||||||
break;
|
break;
|
||||||
case ABS_MT_POSITION_X:
|
case ABS_MT_POSITION_X:
|
||||||
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->mt.slots[dispatch->mt.slot].point.x = e->value;
|
dispatch->mt.slots[dispatch->mt.slot].point.x = e->value;
|
||||||
if (dispatch->pending_event == EVDEV_NONE)
|
if (dispatch->pending_event == EVDEV_NONE)
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||||
break;
|
break;
|
||||||
case ABS_MT_POSITION_Y:
|
case ABS_MT_POSITION_Y:
|
||||||
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->mt.slots[dispatch->mt.slot].point.y = e->value;
|
dispatch->mt.slots[dispatch->mt.slot].point.y = e->value;
|
||||||
if (dispatch->pending_event == EVDEV_NONE)
|
if (dispatch->pending_event == EVDEV_NONE)
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||||
|
|
@ -870,11 +872,13 @@ fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
||||||
{
|
{
|
||||||
switch (e->code) {
|
switch (e->code) {
|
||||||
case ABS_X:
|
case ABS_X:
|
||||||
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->abs.point.x = e->value;
|
dispatch->abs.point.x = e->value;
|
||||||
if (dispatch->pending_event == EVDEV_NONE)
|
if (dispatch->pending_event == EVDEV_NONE)
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MOTION;
|
dispatch->pending_event = EVDEV_ABSOLUTE_MOTION;
|
||||||
break;
|
break;
|
||||||
case ABS_Y:
|
case ABS_Y:
|
||||||
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->abs.point.y = e->value;
|
dispatch->abs.point.y = e->value;
|
||||||
if (dispatch->pending_event == EVDEV_NONE)
|
if (dispatch->pending_event == EVDEV_NONE)
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MOTION;
|
dispatch->pending_event = EVDEV_ABSOLUTE_MOTION;
|
||||||
|
|
@ -1716,6 +1720,8 @@ fallback_dispatch_init_abs(struct fallback_dispatch *dispatch,
|
||||||
dispatch->abs.point.x = device->abs.absinfo_x->value;
|
dispatch->abs.point.x = device->abs.absinfo_x->value;
|
||||||
dispatch->abs.point.y = device->abs.absinfo_y->value;
|
dispatch->abs.point.y = device->abs.absinfo_y->value;
|
||||||
dispatch->abs.seat_slot = -1;
|
dispatch->abs.seat_slot = -1;
|
||||||
|
|
||||||
|
evdev_device_init_abs_range_warnings(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct evdev_dispatch *
|
static struct evdev_dispatch *
|
||||||
|
|
|
||||||
65
src/evdev.h
65
src/evdev.h
|
|
@ -162,6 +162,11 @@ struct evdev_device {
|
||||||
struct matrix usermatrix; /* as supplied by the caller */
|
struct matrix usermatrix; /* as supplied by the caller */
|
||||||
|
|
||||||
struct device_coords dimensions;
|
struct device_coords dimensions;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct device_coords min, max;
|
||||||
|
struct ratelimit range_warn_limit;
|
||||||
|
} warning_range;
|
||||||
} abs;
|
} abs;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -298,6 +303,11 @@ struct fallback_dispatch {
|
||||||
struct {
|
struct {
|
||||||
struct device_coords point;
|
struct device_coords point;
|
||||||
int32_t seat_slot;
|
int32_t seat_slot;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct device_coords min, max;
|
||||||
|
struct ratelimit range_warn_limit;
|
||||||
|
} warning_range;
|
||||||
} abs;
|
} abs;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -639,4 +649,59 @@ evdev_device_mm_to_units(const struct evdev_device *device,
|
||||||
|
|
||||||
return units;
|
return units;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
evdev_device_init_abs_range_warnings(struct evdev_device *device)
|
||||||
|
{
|
||||||
|
const struct input_absinfo *x, *y;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
x = device->abs.absinfo_x;
|
||||||
|
y = device->abs.absinfo_y;
|
||||||
|
width = device->abs.dimensions.x;
|
||||||
|
height = device->abs.dimensions.y;
|
||||||
|
|
||||||
|
device->abs.warning_range.min.x = x->minimum - 0.05 * width;
|
||||||
|
device->abs.warning_range.min.y = y->minimum - 0.05 * height;
|
||||||
|
device->abs.warning_range.max.x = x->maximum + 0.05 * width;
|
||||||
|
device->abs.warning_range.max.y = y->maximum + 0.05 * height;
|
||||||
|
|
||||||
|
/* One warning every 5 min is enough */
|
||||||
|
ratelimit_init(&device->abs.warning_range.range_warn_limit,
|
||||||
|
s2us(3000),
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
evdev_device_check_abs_axis_range(struct evdev_device *device,
|
||||||
|
unsigned int code,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
int min, max;
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
case ABS_X:
|
||||||
|
case ABS_MT_POSITION_X:
|
||||||
|
min = device->abs.warning_range.min.x;
|
||||||
|
max = device->abs.warning_range.max.x;
|
||||||
|
break;
|
||||||
|
case ABS_Y:
|
||||||
|
case ABS_MT_POSITION_Y:
|
||||||
|
min = device->abs.warning_range.min.y;
|
||||||
|
max = device->abs.warning_range.max.y;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < min || value > max) {
|
||||||
|
log_info_ratelimit(evdev_libinput_context(device),
|
||||||
|
&device->abs.warning_range.range_warn_limit,
|
||||||
|
"Axis %#x value %d is outside expected range [%d, %d]\n"
|
||||||
|
"See %s/absolute_coordinate_ranges.html for details\n",
|
||||||
|
code, value, min, max,
|
||||||
|
HTTP_DOC_LINK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* EVDEV_H */
|
#endif /* EVDEV_H */
|
||||||
|
|
|
||||||
50
test/log.c
50
test/log.c
|
|
@ -140,11 +140,61 @@ START_TEST(log_priority)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static int axisrange_log_handler_called = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
axisrange_warning_log_handler(struct libinput *libinput,
|
||||||
|
enum libinput_log_priority priority,
|
||||||
|
const char *format,
|
||||||
|
va_list args)
|
||||||
|
{
|
||||||
|
axisrange_log_handler_called++;
|
||||||
|
litest_assert_notnull(format);
|
||||||
|
litest_assert_notnull(strstr(format, "is outside expected range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(log_axisrange_warning)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
const struct input_absinfo *abs;
|
||||||
|
int axis = _i; /* looped test */
|
||||||
|
|
||||||
|
litest_touch_down(dev, 0, 90, 100);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_INFO);
|
||||||
|
libinput_log_set_handler(li, axisrange_warning_log_handler);
|
||||||
|
|
||||||
|
abs = libevdev_get_abs_info(dev->evdev, axis);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
litest_event(dev, EV_ABS,
|
||||||
|
ABS_MT_POSITION_X + axis,
|
||||||
|
abs->maximum * 2 + i);
|
||||||
|
litest_event(dev, EV_ABS, axis, abs->maximum * 2);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expect only one message per 5 min */
|
||||||
|
ck_assert_int_eq(axisrange_log_handler_called, 1);
|
||||||
|
|
||||||
|
litest_restore_log_handler(li);
|
||||||
|
axisrange_log_handler_called = 0;
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
litest_setup_tests_log(void)
|
litest_setup_tests_log(void)
|
||||||
{
|
{
|
||||||
|
struct range axes = { ABS_X, ABS_Y + 1};
|
||||||
|
|
||||||
litest_add_no_device("log:defaults", log_default_priority);
|
litest_add_no_device("log:defaults", log_default_priority);
|
||||||
litest_add_no_device("log:logging", log_handler_invoked);
|
litest_add_no_device("log:logging", log_handler_invoked);
|
||||||
litest_add_no_device("log:logging", log_handler_NULL);
|
litest_add_no_device("log:logging", log_handler_NULL);
|
||||||
litest_add_no_device("log:logging", log_priority);
|
litest_add_no_device("log:logging", log_priority);
|
||||||
|
|
||||||
|
litest_add_ranged("log:warnings", log_axisrange_warning, LITEST_TOUCH, LITEST_ANY, &axes);
|
||||||
|
litest_add_ranged("log:warnings", log_axisrange_warning, LITEST_TOUCHPAD, LITEST_ANY, &axes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue