1/*
2 * Copyright © 2011 Red Hat, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of Red Hat
9 * not be used in advertising or publicity pertaining to distribution
10 * of the software without specific, written prior permission.  Red
11 * Hat makes no representations about the suitability of this software
12 * for any purpose.  It is provided "as is" without express or implied
13 * warranty.
14 *
15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authors:
24 *      Peter Hutterer
25 */
26
27#if HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include <stdio.h>
32#include <assert.h>
33
34#include "synapticsstr.h"
35#include "eventcomm.h"
36
37#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
38
39int fd_read, fd_write;
40
41/* A syn event, always handy to have */
42struct input_event syn = { {0, 0}, EV_SYN, SYN_REPORT, 0 };
43
44static void
45create_pipe_fd(void)
46{
47    int pipefd[2];
48
49    assert(pipe(pipefd) != -1);
50
51    fd_read = pipefd[0];
52    fd_write = pipefd[1];
53}
54
55static void
56reset_data(struct SynapticsHwState **hw, struct CommData *comm,
57           SynapticsPrivate * priv)
58{
59    SynapticsHwStateFree(&comm->hwState);
60    memset(comm, 0, sizeof(struct CommData));
61    SynapticsHwStateFree(hw);
62    *hw = SynapticsHwStateAlloc(priv);
63    comm->hwState = SynapticsHwStateAlloc(priv);
64}
65
66/**
67 * Write n input events to fd, followed by the syn event.
68 */
69static void
70write_event(int fd, struct input_event *ev, int n)
71{
72    write(fd, ev, sizeof(struct input_event) * n);
73    write(fd, &syn, sizeof(syn));
74}
75
76static void
77test_buttons(int fd, InputInfoPtr pInfo, struct CommData *comm)
78{
79    SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
80    struct SynapticsHwState *hw = NULL;
81    struct input_event ev = { {0, 0}, EV_KEY, 0, 0 };
82
83    reset_data(&hw, comm, priv);
84
85#define _test_press_release(_code, field)       \
86        ev.code = (_code);                      \
87        ev.value = 1;                           \
88        write_event(fd, &ev, 1);                \
89        EventReadHwState(pInfo, comm, hw);      \
90        assert(hw->field == 1);                 \
91        ev.value = 0; /* button release */      \
92        write_event(fd_write, &ev, 1);          \
93        EventReadHwState(pInfo, comm, hw);      \
94        assert(hw->field == 0);
95
96    _test_press_release(BTN_LEFT, left);
97    _test_press_release(BTN_RIGHT, right);
98    _test_press_release(BTN_MIDDLE, middle);
99    _test_press_release(BTN_FORWARD, up);
100    _test_press_release(BTN_BACK, down);
101    _test_press_release(BTN_0, multi[0]);
102    _test_press_release(BTN_1, multi[1]);
103    _test_press_release(BTN_2, multi[2]);
104    _test_press_release(BTN_3, multi[3]);
105    _test_press_release(BTN_4, multi[4]);
106    _test_press_release(BTN_5, multi[5]);
107    _test_press_release(BTN_6, multi[6]);
108    _test_press_release(BTN_7, multi[7]);
109
110    SynapticsHwStateFree(&hw);
111}
112
113/**
114 * This test checks that the recognised event fields set the right hardware
115 * state. It's a fairly limited test and does not check whether any of the
116 * others change the HW state at all.
117 */
118static void
119test_read_hw_state(void)
120{
121    InputInfoRec info = { 0 };
122    SynapticsPrivate private;
123    struct SynapticsHwState *hw = NULL;
124    struct CommData comm = { 0 };
125
126    struct input_event ev[] = {
127        {{0, 0}, EV_KEY, BTN_TOOL_FINGER, 1},
128        {{0, 0}, EV_KEY, BTN_TOOL_DOUBLETAP, 1},
129        {{0, 0}, EV_KEY, BTN_TOOL_TRIPLETAP, 1},
130        {{0, 0}, EV_ABS, ABS_X, 42},
131        {{0, 0}, EV_ABS, ABS_Y, 21},
132        {{0, 0}, EV_ABS, ABS_PRESSURE, 56},
133        {{0, 0}, EV_ABS, ABS_TOOL_WIDTH, 204},
134    };
135
136    memset(&private, 0, sizeof(private));
137
138    info.private = &private;
139    info.fd = fd_read;
140
141    private.proto_data = EventProtoDataAlloc();
142
143    /* just the syn event */
144    reset_data(&hw, &comm, &private);
145    write(fd_write, &syn, sizeof(syn));
146    EventReadHwState(&info, &comm, hw);
147    assert(hw->numFingers == 0);
148
149    /* one finger */
150    reset_data(&hw, &comm, &private);
151    write_event(fd_write, &ev[0], 1);
152    EventReadHwState(&info, &comm, hw);
153    assert(hw->numFingers == 1);
154
155    /* two fingers */
156    reset_data(&hw, &comm, &private);
157    write_event(fd_write, &ev[1], 1);
158    EventReadHwState(&info, &comm, hw);
159    assert(hw->numFingers == 2);
160
161    /* three fingers */
162    reset_data(&hw, &comm, &private);
163    write_event(fd_write, &ev[2], 1);
164    EventReadHwState(&info, &comm, hw);
165    assert(hw->numFingers == 3);
166
167    /* x/y data */
168    reset_data(&hw, &comm, &private);
169    write_event(fd_write, &ev[3], 2);
170    EventReadHwState(&info, &comm, hw);
171    assert(hw->x == ev[3].value);
172    assert(hw->y == ev[4].value);
173
174    /* pressure */
175    reset_data(&hw, &comm, &private);
176    write_event(fd_write, &ev[5], 1);
177    EventReadHwState(&info, &comm, hw);
178    assert(hw->z == ev[5].value);
179
180    /* finger width */
181    reset_data(&hw, &comm, &private);
182    write_event(fd_write, &ev[6], 1);
183    EventReadHwState(&info, &comm, hw);
184    assert(hw->fingerWidth == ev[6].value);
185
186    /* the various buttons */
187    test_buttons(fd_write, &info, &comm);
188
189    free(private.proto_data);
190    SynapticsHwStateFree(&hw);
191    SynapticsHwStateFree(&comm.hwState);
192}
193
194static Bool
195compare_hw_state(const struct SynapticsHwState *a,
196                 const struct SynapticsHwState *b)
197{
198#define COMPARE(x) \
199        if (a->x != b->x) return a->x - b->x
200
201    COMPARE(millis);
202    COMPARE(x);
203    COMPARE(y);
204    COMPARE(z);
205    COMPARE(numFingers);
206    COMPARE(fingerWidth);
207    COMPARE(left);
208    COMPARE(right);
209    COMPARE(up);
210    COMPARE(down);
211    if (memcmp(a->multi, b->multi, sizeof(a->multi)))
212        return memcmp(a->multi, b->multi, sizeof(a->multi));
213    COMPARE(middle);
214
215#undef COMPARE
216
217    return 0;
218}
219
220/**
221 * Make sure that axes/keys unknown to the driver don't change the hardware
222 * state.
223 */
224static void
225test_ignore_hw_state(void)
226{
227    int i;
228    InputInfoRec info = { 0 };
229    SynapticsPrivate private;
230    struct SynapticsHwState *hw = NULL;
231    struct SynapticsHwState *hw_zero = NULL;
232    struct CommData comm = { 0 };
233
234    int known_abs[] = {
235        ABS_X,
236        ABS_Y,
237        ABS_PRESSURE,
238        ABS_TOOL_WIDTH,
239    };
240
241    int known_keys[] = {
242        BTN_LEFT,
243        BTN_RIGHT,
244        BTN_MIDDLE,
245        BTN_FORWARD,
246        BTN_BACK,
247        BTN_0,
248        BTN_1,
249        BTN_2,
250        BTN_3,
251        BTN_4,
252        BTN_5,
253        BTN_6,
254        BTN_7,
255        BTN_TOOL_FINGER,
256        BTN_TOOL_DOUBLETAP,
257        BTN_TOOL_TRIPLETAP,
258        BTN_TOUCH
259    };
260
261    struct input_event ev = { {0, 0}, 0, 0, 1 };
262
263    memset(&private, 0, sizeof(private));
264    info.private = &private;
265    info.fd = fd_read;
266
267    private.proto_data = EventProtoDataAlloc();
268
269    reset_data(&hw_zero, &comm, &private);
270
271#define _assert_no_change(_type, _code) \
272        reset_data(&hw, &comm, &private);               \
273        ev.type = _type;                                \
274        ev.code = _code;                                \
275        ev.value = 1;                                   \
276        write_event(fd_write, &ev, 1);                  \
277        EventReadHwState(&info, &comm, hw);            \
278        assert(compare_hw_state(hw, hw_zero) == 0);
279
280    for (i = ABS_X; i < ABS_MAX; i++) {
281        int j, skip = 0;
282
283        for (j = 0; j < ArrayLength(known_abs); j++) {
284            if (i == known_abs[j]) {
285                skip = 1;
286                break;
287            }
288        }
289
290        if (skip)
291            continue;
292
293        _assert_no_change(EV_ABS, i);
294    }
295
296    for (i = KEY_RESERVED; i < KEY_MAX; i++) {
297        int j, skip = 0;
298
299        for (j = 0; j < ArrayLength(known_keys); j++) {
300            if (i == known_keys[j]) {
301                skip = 1;
302                break;
303            }
304        }
305
306        if (skip)
307            continue;
308
309        _assert_no_change(EV_KEY, i);
310    }
311
312    free(private.proto_data);
313    SynapticsHwStateFree(&hw);
314    SynapticsHwStateFree(&hw_zero);
315    SynapticsHwStateFree(&comm.hwState);
316}
317
318int
319main(int argc, char **argv)
320{
321    create_pipe_fd();
322
323    test_read_hw_state();
324    test_ignore_hw_state();
325    return 0;
326}
327