Edit

IABSD.fr/xenocara/driver/xf86-input-synaptics/test/eventcomm-test.c

Branch :

  • Show log

    Commit

  • Author : shadchin
    Date : 2012-06-12 18:59:42
    Hash : b1c43b24
    Message : Update to xf86-input-synaptics 1.6.1 ok matthieu@

  • driver/xf86-input-synaptics/test/eventcomm-test.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 "synaptics.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;
    }