xenocara/driver/xf86-input-synaptics/test/eventcomm-test.c
shadchin ffcddaf4c2 Update to xf86-input-synaptics 1.7.1.
ok mpi@ jcs@ matthieu@
2013-06-02 18:17:24 +00:00

327 lines
8.5 KiB
C

/*
* Copyright © 2011 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 Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied
* warranty.
*
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL THE AUTHORS 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.
*
* Authors:
* Peter Hutterer
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <assert.h>
#include "synapticsstr.h"
#include "eventcomm.h"
#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
int fd_read, fd_write;
/* A syn event, always handy to have */
struct input_event syn = { {0, 0}, EV_SYN, SYN_REPORT, 0 };
static void
create_pipe_fd(void)
{
int pipefd[2];
assert(pipe(pipefd) != -1);
fd_read = pipefd[0];
fd_write = pipefd[1];
}
static void
reset_data(struct SynapticsHwState **hw, struct CommData *comm,
SynapticsPrivate * priv)
{
SynapticsHwStateFree(&comm->hwState);
memset(comm, 0, sizeof(struct CommData));
SynapticsHwStateFree(hw);
*hw = SynapticsHwStateAlloc(priv);
comm->hwState = SynapticsHwStateAlloc(priv);
}
/**
* Write n input events to fd, followed by the syn event.
*/
static void
write_event(int fd, struct input_event *ev, int n)
{
write(fd, ev, sizeof(struct input_event) * n);
write(fd, &syn, sizeof(syn));
}
static void
test_buttons(int fd, InputInfoPtr pInfo, struct CommData *comm)
{
SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
struct SynapticsHwState *hw = NULL;
struct input_event ev = { {0, 0}, EV_KEY, 0, 0 };
reset_data(&hw, comm, priv);
#define _test_press_release(_code, field) \
ev.code = (_code); \
ev.value = 1; \
write_event(fd, &ev, 1); \
EventReadHwState(pInfo, comm, hw); \
assert(hw->field == 1); \
ev.value = 0; /* button release */ \
write_event(fd_write, &ev, 1); \
EventReadHwState(pInfo, comm, hw); \
assert(hw->field == 0);
_test_press_release(BTN_LEFT, left);
_test_press_release(BTN_RIGHT, right);
_test_press_release(BTN_MIDDLE, middle);
_test_press_release(BTN_FORWARD, up);
_test_press_release(BTN_BACK, down);
_test_press_release(BTN_0, multi[0]);
_test_press_release(BTN_1, multi[1]);
_test_press_release(BTN_2, multi[2]);
_test_press_release(BTN_3, multi[3]);
_test_press_release(BTN_4, multi[4]);
_test_press_release(BTN_5, multi[5]);
_test_press_release(BTN_6, multi[6]);
_test_press_release(BTN_7, multi[7]);
SynapticsHwStateFree(&hw);
}
/**
* This test checks that the recognised event fields set the right hardware
* state. It's a fairly limited test and does not check whether any of the
* others change the HW state at all.
*/
static void
test_read_hw_state(void)
{
InputInfoRec info = { 0 };
SynapticsPrivate private;
struct SynapticsHwState *hw = NULL;
struct CommData comm = { 0 };
struct input_event ev[] = {
{{0, 0}, EV_KEY, BTN_TOOL_FINGER, 1},
{{0, 0}, EV_KEY, BTN_TOOL_DOUBLETAP, 1},
{{0, 0}, EV_KEY, BTN_TOOL_TRIPLETAP, 1},
{{0, 0}, EV_ABS, ABS_X, 42},
{{0, 0}, EV_ABS, ABS_Y, 21},
{{0, 0}, EV_ABS, ABS_PRESSURE, 56},
{{0, 0}, EV_ABS, ABS_TOOL_WIDTH, 204},
};
memset(&private, 0, sizeof(private));
info.private = &private;
info.fd = fd_read;
private.proto_data = EventProtoDataAlloc();
/* just the syn event */
reset_data(&hw, &comm, &private);
write(fd_write, &syn, sizeof(syn));
EventReadHwState(&info, &comm, hw);
assert(hw->numFingers == 0);
/* one finger */
reset_data(&hw, &comm, &private);
write_event(fd_write, &ev[0], 1);
EventReadHwState(&info, &comm, hw);
assert(hw->numFingers == 1);
/* two fingers */
reset_data(&hw, &comm, &private);
write_event(fd_write, &ev[1], 1);
EventReadHwState(&info, &comm, hw);
assert(hw->numFingers == 2);
/* three fingers */
reset_data(&hw, &comm, &private);
write_event(fd_write, &ev[2], 1);
EventReadHwState(&info, &comm, hw);
assert(hw->numFingers == 3);
/* x/y data */
reset_data(&hw, &comm, &private);
write_event(fd_write, &ev[3], 2);
EventReadHwState(&info, &comm, hw);
assert(hw->x == ev[3].value);
assert(hw->y == ev[4].value);
/* pressure */
reset_data(&hw, &comm, &private);
write_event(fd_write, &ev[5], 1);
EventReadHwState(&info, &comm, hw);
assert(hw->z == ev[5].value);
/* finger width */
reset_data(&hw, &comm, &private);
write_event(fd_write, &ev[6], 1);
EventReadHwState(&info, &comm, hw);
assert(hw->fingerWidth == ev[6].value);
/* the various buttons */
test_buttons(fd_write, &info, &comm);
free(private.proto_data);
SynapticsHwStateFree(&hw);
SynapticsHwStateFree(&comm.hwState);
}
static Bool
compare_hw_state(const struct SynapticsHwState *a,
const struct SynapticsHwState *b)
{
#define COMPARE(x) \
if (a->x != b->x) return a->x - b->x
COMPARE(millis);
COMPARE(x);
COMPARE(y);
COMPARE(z);
COMPARE(numFingers);
COMPARE(fingerWidth);
COMPARE(left);
COMPARE(right);
COMPARE(up);
COMPARE(down);
if (memcmp(a->multi, b->multi, sizeof(a->multi)))
return memcmp(a->multi, b->multi, sizeof(a->multi));
COMPARE(middle);
#undef COMPARE
return 0;
}
/**
* Make sure that axes/keys unknown to the driver don't change the hardware
* state.
*/
static void
test_ignore_hw_state(void)
{
int i;
InputInfoRec info = { 0 };
SynapticsPrivate private;
struct SynapticsHwState *hw = NULL;
struct SynapticsHwState *hw_zero = NULL;
struct CommData comm = { 0 };
int known_abs[] = {
ABS_X,
ABS_Y,
ABS_PRESSURE,
ABS_TOOL_WIDTH,
};
int known_keys[] = {
BTN_LEFT,
BTN_RIGHT,
BTN_MIDDLE,
BTN_FORWARD,
BTN_BACK,
BTN_0,
BTN_1,
BTN_2,
BTN_3,
BTN_4,
BTN_5,
BTN_6,
BTN_7,
BTN_TOOL_FINGER,
BTN_TOOL_DOUBLETAP,
BTN_TOOL_TRIPLETAP,
BTN_TOUCH
};
struct input_event ev = { {0, 0}, 0, 0, 1 };
memset(&private, 0, sizeof(private));
info.private = &private;
info.fd = fd_read;
private.proto_data = EventProtoDataAlloc();
reset_data(&hw_zero, &comm, &private);
#define _assert_no_change(_type, _code) \
reset_data(&hw, &comm, &private); \
ev.type = _type; \
ev.code = _code; \
ev.value = 1; \
write_event(fd_write, &ev, 1); \
EventReadHwState(&info, &comm, hw); \
assert(compare_hw_state(hw, hw_zero) == 0);
for (i = ABS_X; i < ABS_MAX; i++) {
int j, skip = 0;
for (j = 0; j < ArrayLength(known_abs); j++) {
if (i == known_abs[j]) {
skip = 1;
break;
}
}
if (skip)
continue;
_assert_no_change(EV_ABS, i);
}
for (i = KEY_RESERVED; i < KEY_MAX; i++) {
int j, skip = 0;
for (j = 0; j < ArrayLength(known_keys); j++) {
if (i == known_keys[j]) {
skip = 1;
break;
}
}
if (skip)
continue;
_assert_no_change(EV_KEY, i);
}
free(private.proto_data);
SynapticsHwStateFree(&hw);
SynapticsHwStateFree(&hw_zero);
SynapticsHwStateFree(&comm.hwState);
}
int
main(int argc, char **argv)
{
create_pipe_fd();
test_read_hw_state();
test_ignore_hw_state();
return 0;
}