1ed6184dfSmrg/*
2ed6184dfSmrg * Copyright © 2013-2017 Red Hat, Inc.
3ed6184dfSmrg * Copyright © 2020 Povilas Kanapickas <povilas@radix.lt>
4ed6184dfSmrg *
5ed6184dfSmrg * Permission to use, copy, modify, distribute, and sell this software
6ed6184dfSmrg * and its documentation for any purpose is hereby granted without
7ed6184dfSmrg * fee, provided that the above copyright notice appear in all copies
8ed6184dfSmrg * and that both that copyright notice and this permission notice
9ed6184dfSmrg * appear in supporting documentation, and that the name of Red Hat
10ed6184dfSmrg * not be used in advertising or publicity pertaining to distribution
11ed6184dfSmrg * of the software without specific, written prior permission.  Red
12ed6184dfSmrg * Hat makes no representations about the suitability of this software
13ed6184dfSmrg * for any purpose.  It is provided "as is" without express or implied
14ed6184dfSmrg * warranty.
15ed6184dfSmrg *
16ed6184dfSmrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17ed6184dfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18ed6184dfSmrg * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19ed6184dfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20ed6184dfSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21ed6184dfSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22ed6184dfSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23ed6184dfSmrg */
24ed6184dfSmrg
25ed6184dfSmrg#ifdef HAVE_XORG_CONFIG_H
26ed6184dfSmrg#include <xorg-config.h>
27ed6184dfSmrg#endif
28ed6184dfSmrg
29ed6184dfSmrg#include <errno.h>
30ed6184dfSmrg#include <fcntl.h>
31ed6184dfSmrg#include <unistd.h>
32ed6184dfSmrg#include <exevents.h>
33ed6184dfSmrg#include <input.h>
34ed6184dfSmrg#include <xkbsrv.h>
35ed6184dfSmrg#include <xf86.h>
36ed6184dfSmrg#include <xf86Xinput.h>
37ed6184dfSmrg#include "xorgVersion.h"
38ed6184dfSmrg#include <xserver-properties.h>
39ed6184dfSmrg#include <os.h>
40ed6184dfSmrg#include <X11/Xatom.h>
41ed6184dfSmrg
42ed6184dfSmrg#include <sys/socket.h>
43ed6184dfSmrg#include <sys/stat.h>
44ed6184dfSmrg#include <sys/un.h>
45ed6184dfSmrg#include <stdbool.h>
46ed6184dfSmrg
47ed6184dfSmrg#include "xf86-input-inputtest-protocol.h"
48ed6184dfSmrg
49ed6184dfSmrg#define MAX_POINTER_NUM_AXES 5 /* x, y, hscroll, vscroll, [pressure] */
50ed6184dfSmrg#define MAX_TOUCH_NUM_AXES 5 /* x, y, hscroll, vscroll, pressure */
51ed6184dfSmrg#define TOUCH_MAX_SLOTS 15
52ed6184dfSmrg
53ed6184dfSmrg#define TOUCH_AXIS_MAX 0xffff
54ed6184dfSmrg#define TABLET_PRESSURE_AXIS_MAX 2047
55ed6184dfSmrg
56ed6184dfSmrg#define EVENT_BUFFER_SIZE 4096
57ed6184dfSmrg
58ed6184dfSmrgenum xf86ITDeviceType {
59ed6184dfSmrg    DEVICE_KEYBOARD = 1,
60ed6184dfSmrg    DEVICE_POINTER,
61ed6184dfSmrg    DEVICE_POINTER_GESTURE,
62ed6184dfSmrg    DEVICE_POINTER_ABS,
63ed6184dfSmrg    DEVICE_POINTER_ABS_PROXIMITY,
64ed6184dfSmrg    DEVICE_TOUCH,
65ed6184dfSmrg};
66ed6184dfSmrg
67ed6184dfSmrgenum xf86ITClientState {
68ed6184dfSmrg    CLIENT_STATE_NOT_CONNECTED = 0,
69ed6184dfSmrg
70ed6184dfSmrg    /* connection_fd is valid */
71ed6184dfSmrg    CLIENT_STATE_NEW,
72ed6184dfSmrg
73ed6184dfSmrg    /* connection_fd is valid and client_protocol.{major,minor} are set */
74ed6184dfSmrg    CLIENT_STATE_READY,
75ed6184dfSmrg};
76ed6184dfSmrg
77ed6184dfSmrgtypedef struct {
78ed6184dfSmrg    InputInfoPtr pInfo;
79ed6184dfSmrg
80ed6184dfSmrg    int socket_fd;  /* for accepting new clients */
81ed6184dfSmrg    int connection_fd; /* current client connection */
82ed6184dfSmrg
83ed6184dfSmrg    char *socket_path;
84ed6184dfSmrg
85ed6184dfSmrg    enum xf86ITClientState client_state;
86ed6184dfSmrg    struct {
87ed6184dfSmrg        int major, minor;
88ed6184dfSmrg    } client_protocol;
89ed6184dfSmrg
90ed6184dfSmrg    struct {
91ed6184dfSmrg        char data[EVENT_BUFFER_SIZE];
92ed6184dfSmrg        int valid_length;
93ed6184dfSmrg    } buffer;
94ed6184dfSmrg
95ed6184dfSmrg    uint32_t device_type;
96ed6184dfSmrg
97ed6184dfSmrg    /*  last_processed_event_num == last_event_num and waiting_for_drain != 0 must never be true
98ed6184dfSmrg        both at the same time. This would mean that we are waiting for the input queue to be
99ed6184dfSmrg        processed, yet all events have already been processed, i.e. a deadlock.
100ed6184dfSmrg
101ed6184dfSmrg        waiting_for_drain_mutex protects concurrent access to waiting_for_drain variable which
102ed6184dfSmrg        may be modified from multiple threads.
103ed6184dfSmrg    */
104ed6184dfSmrg    pthread_mutex_t waiting_for_drain_mutex;
105ed6184dfSmrg    bool waiting_for_drain;
106ed6184dfSmrg    int last_processed_event_num;
107ed6184dfSmrg    int last_event_num;
108ed6184dfSmrg
109ed6184dfSmrg    ValuatorMask *valuators;
110ed6184dfSmrg    ValuatorMask *valuators_unaccelerated;
111ed6184dfSmrg} xf86ITDevice, *xf86ITDevicePtr;
112ed6184dfSmrg
113ed6184dfSmrgstatic void
114ed6184dfSmrgread_input_from_connection(InputInfoPtr pInfo);
115ed6184dfSmrg
116ed6184dfSmrgstatic Bool
117ed6184dfSmrgnotify_sync_finished(ClientPtr ptr, void *closure)
118ed6184dfSmrg{
119ed6184dfSmrg    int fd = (int)(intptr_t) closure;
120ed6184dfSmrg    xf86ITResponseSyncFinished response;
121ed6184dfSmrg    response.header.length = sizeof(response);
122ed6184dfSmrg    response.header.type = XF86IT_RESPONSE_SYNC_FINISHED;
123ed6184dfSmrg
124ed6184dfSmrg    input_lock();
125ed6184dfSmrg    /*  we don't really care whether the write succeeds. It may fail if the device is
126ed6184dfSmrg        already shut down and the descriptor is closed.
127ed6184dfSmrg    */
128ed6184dfSmrg    if (write(fd, &response, response.header.length) != response.header.length) {
129ed6184dfSmrg        LogMessageVerbSigSafe(X_ERROR, 0,
130ed6184dfSmrg                              "inputtest: Failed to write sync response: %s\n",
131ed6184dfSmrg                              strerror(errno));
132ed6184dfSmrg    }
133ed6184dfSmrg    input_unlock();
134ed6184dfSmrg    return TRUE;
135ed6184dfSmrg}
136ed6184dfSmrg
137ed6184dfSmrgstatic void
138ed6184dfSmrginput_drain_callback(CallbackListPtr *callback, void *data, void *call_data)
139ed6184dfSmrg{
140ed6184dfSmrg    void *drain_write_closure;
141ed6184dfSmrg    InputInfoPtr pInfo = data;
142ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
143ed6184dfSmrg    bool notify_synchronization = false;
144ed6184dfSmrg
145ed6184dfSmrg    pthread_mutex_lock(&driver_data->waiting_for_drain_mutex);
146ed6184dfSmrg    driver_data->last_processed_event_num = driver_data->last_event_num;
147ed6184dfSmrg    if (driver_data->waiting_for_drain) {
148ed6184dfSmrg        driver_data->waiting_for_drain = false;
149ed6184dfSmrg        notify_synchronization = true;
150ed6184dfSmrg    }
151ed6184dfSmrg    pthread_mutex_unlock(&driver_data->waiting_for_drain_mutex);
152ed6184dfSmrg
153ed6184dfSmrg    if (notify_synchronization) {
154ed6184dfSmrg        drain_write_closure = (void*)(intptr_t) driver_data->connection_fd;
155ed6184dfSmrg        /* One input event may result in additional sets of events being submitted to the
156ed6184dfSmrg           input queue from the input processing code itself. This results in
157ed6184dfSmrg           input_drain_callback being called multiple times.
158ed6184dfSmrg
159ed6184dfSmrg           We therefore schedule a WorkProc (to be run when the server is no longer busy)
160ed6184dfSmrg           to notify the client when all current events have been processed.
161ed6184dfSmrg         */
162ed6184dfSmrg        xf86IDrvMsg(pInfo, X_DEBUG, "Synchronization finished\n");
163ed6184dfSmrg        QueueWorkProc(notify_sync_finished, NULL, drain_write_closure);
164ed6184dfSmrg    }
165ed6184dfSmrg}
166ed6184dfSmrg
167ed6184dfSmrgstatic void
168ed6184dfSmrgread_events(int fd, int ready, void *data)
169ed6184dfSmrg{
170ed6184dfSmrg    DeviceIntPtr dev = (DeviceIntPtr) data;
171ed6184dfSmrg    InputInfoPtr pInfo = dev->public.devicePrivate;
172ed6184dfSmrg    read_input_from_connection(pInfo);
173ed6184dfSmrg}
174ed6184dfSmrg
175ed6184dfSmrgstatic void
176ed6184dfSmrgtry_accept_connection(int fd, int ready, void *data)
177ed6184dfSmrg{
178ed6184dfSmrg    DeviceIntPtr dev = (DeviceIntPtr) data;
179ed6184dfSmrg    InputInfoPtr pInfo = dev->public.devicePrivate;
180ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
181ed6184dfSmrg    int connection_fd;
182ed6184dfSmrg    int flags;
183ed6184dfSmrg
184ed6184dfSmrg    if (driver_data->connection_fd >= 0)
185ed6184dfSmrg        return;
186ed6184dfSmrg
187ed6184dfSmrg    connection_fd = accept(driver_data->socket_fd, NULL, NULL);
188ed6184dfSmrg    if (connection_fd < 0) {
189ed6184dfSmrg        if (errno == EAGAIN || errno == EWOULDBLOCK)
190ed6184dfSmrg            return;
191ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Failed to accept a connection\n");
192ed6184dfSmrg        return;
193ed6184dfSmrg    }
194ed6184dfSmrg
195ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Accepted input control connection\n");
196ed6184dfSmrg
197ed6184dfSmrg    flags = fcntl(connection_fd, F_GETFL, 0);
198ed6184dfSmrg    fcntl(connection_fd, F_SETFL, flags | O_NONBLOCK);
199ed6184dfSmrg
200ed6184dfSmrg    driver_data->connection_fd = connection_fd;
201ed6184dfSmrg    xf86AddInputEventDrainCallback(input_drain_callback, pInfo);
202ed6184dfSmrg    SetNotifyFd(driver_data->connection_fd, read_events, X_NOTIFY_READ, dev);
203ed6184dfSmrg
204ed6184dfSmrg    driver_data->client_state = CLIENT_STATE_NEW;
205ed6184dfSmrg}
206ed6184dfSmrg
207ed6184dfSmrgstatic int
208ed6184dfSmrgdevice_on(DeviceIntPtr dev)
209ed6184dfSmrg{
210ed6184dfSmrg    InputInfoPtr pInfo = dev->public.devicePrivate;
211ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
212ed6184dfSmrg
213ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Device turned on\n");
214ed6184dfSmrg
215ed6184dfSmrg    xf86AddEnabledDevice(pInfo);
216ed6184dfSmrg    dev->public.on = TRUE;
217ed6184dfSmrg    driver_data->buffer.valid_length = 0;
218ed6184dfSmrg
219ed6184dfSmrg    try_accept_connection(-1, 0, dev);
220ed6184dfSmrg    if (driver_data->connection_fd < 0)
221ed6184dfSmrg        SetNotifyFd(driver_data->socket_fd, try_accept_connection, X_NOTIFY_READ, dev);
222ed6184dfSmrg
223ed6184dfSmrg    return Success;
224ed6184dfSmrg}
225ed6184dfSmrg
226ed6184dfSmrgstatic void
227ed6184dfSmrgteardown_client_connection(InputInfoPtr pInfo)
228ed6184dfSmrg{
229ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
230ed6184dfSmrg    if (driver_data->client_state != CLIENT_STATE_NOT_CONNECTED) {
231ed6184dfSmrg        RemoveNotifyFd(driver_data->connection_fd);
232ed6184dfSmrg        xf86RemoveInputEventDrainCallback(input_drain_callback, pInfo);
233ed6184dfSmrg
234ed6184dfSmrg        close(driver_data->connection_fd);
235ed6184dfSmrg        driver_data->connection_fd = -1;
236ed6184dfSmrg    }
237ed6184dfSmrg    RemoveNotifyFd(driver_data->socket_fd);
238ed6184dfSmrg    driver_data->client_state = CLIENT_STATE_NOT_CONNECTED;
239ed6184dfSmrg}
240ed6184dfSmrg
241ed6184dfSmrgstatic int
242ed6184dfSmrgdevice_off(DeviceIntPtr dev)
243ed6184dfSmrg{
244ed6184dfSmrg    InputInfoPtr pInfo = dev->public.devicePrivate;
245ed6184dfSmrg
246ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Device turned off\n");
247ed6184dfSmrg
248ed6184dfSmrg    if (dev->public.on) {
249ed6184dfSmrg        teardown_client_connection(pInfo);
250ed6184dfSmrg        xf86RemoveEnabledDevice(pInfo);
251ed6184dfSmrg    }
252ed6184dfSmrg    dev->public.on = FALSE;
253ed6184dfSmrg    return Success;
254ed6184dfSmrg}
255ed6184dfSmrg
256ed6184dfSmrgstatic void
257ed6184dfSmrgptr_ctl(DeviceIntPtr dev, PtrCtrl *ctl)
258ed6184dfSmrg{
259ed6184dfSmrg}
260ed6184dfSmrg
261ed6184dfSmrgstatic void
262ed6184dfSmrginit_button_map(unsigned char *btnmap, size_t size)
263ed6184dfSmrg{
264ed6184dfSmrg    int i;
265ed6184dfSmrg
266ed6184dfSmrg    memset(btnmap, 0, size);
267ed6184dfSmrg    for (i = 0; i < size; i++)
268ed6184dfSmrg        btnmap[i] = i;
269ed6184dfSmrg}
270ed6184dfSmrg
271ed6184dfSmrgstatic void
272ed6184dfSmrginit_button_labels(Atom *labels, size_t size)
273ed6184dfSmrg{
274ed6184dfSmrg    assert(size > 10);
275ed6184dfSmrg
276ed6184dfSmrg    memset(labels, 0, size * sizeof(Atom));
277ed6184dfSmrg    labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
278ed6184dfSmrg    labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
279ed6184dfSmrg    labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
280ed6184dfSmrg    labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
281ed6184dfSmrg    labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
282ed6184dfSmrg    labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
283ed6184dfSmrg    labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
284ed6184dfSmrg    labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_SIDE);
285ed6184dfSmrg    labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_EXTRA);
286ed6184dfSmrg    labels[9] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_FORWARD);
287ed6184dfSmrg    labels[10] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_BACK);
288ed6184dfSmrg}
289ed6184dfSmrg
290ed6184dfSmrgstatic void
291ed6184dfSmrginit_pointer(InputInfoPtr pInfo)
292ed6184dfSmrg{
293ed6184dfSmrg    DeviceIntPtr dev= pInfo->dev;
294ed6184dfSmrg    int min, max, res;
295ed6184dfSmrg    int nbuttons = 7;
296ed6184dfSmrg    bool has_pressure = false;
297ed6184dfSmrg    int num_axes = 0;
298ed6184dfSmrg
299ed6184dfSmrg    unsigned char btnmap[MAX_BUTTONS + 1];
300ed6184dfSmrg    Atom btnlabels[MAX_BUTTONS];
301ed6184dfSmrg    Atom axislabels[MAX_POINTER_NUM_AXES];
302ed6184dfSmrg
303ed6184dfSmrg    nbuttons = xf86SetIntOption(pInfo->options, "PointerButtonCount", 7);
304ed6184dfSmrg    has_pressure = xf86SetBoolOption(pInfo->options, "PointerHasPressure",
305ed6184dfSmrg                                     false);
306ed6184dfSmrg
307ed6184dfSmrg    init_button_map(btnmap, ARRAY_SIZE(btnmap));
308ed6184dfSmrg    init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
309ed6184dfSmrg
310ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
311ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
312ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
313ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
314ed6184dfSmrg    if (has_pressure)
315ed6184dfSmrg        axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
316ed6184dfSmrg
317ed6184dfSmrg    InitPointerDeviceStruct((DevicePtr)dev,
318ed6184dfSmrg                            btnmap,
319ed6184dfSmrg                            nbuttons,
320ed6184dfSmrg                            btnlabels,
321ed6184dfSmrg                            ptr_ctl,
322ed6184dfSmrg                            GetMotionHistorySize(),
323ed6184dfSmrg                            num_axes,
324ed6184dfSmrg                            axislabels);
325ed6184dfSmrg    min = -1;
326ed6184dfSmrg    max = -1;
327ed6184dfSmrg    res = 0;
328ed6184dfSmrg
329ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 0, XIGetKnownProperty(AXIS_LABEL_PROP_REL_X),
330ed6184dfSmrg                               min, max, res * 1000, 0, res * 1000, Relative);
331ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 1, XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y),
332ed6184dfSmrg                               min, max, res * 1000, 0, res * 1000, Relative);
333ed6184dfSmrg
334ed6184dfSmrg    SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, 120, 0);
335ed6184dfSmrg    SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, 120, 0);
336ed6184dfSmrg
337ed6184dfSmrg    if (has_pressure) {
338ed6184dfSmrg        xf86InitValuatorAxisStruct(dev, 4,
339ed6184dfSmrg            XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE),
340ed6184dfSmrg            0, 1000, 1, 1, 1, Absolute);
341ed6184dfSmrg    }
342ed6184dfSmrg}
343ed6184dfSmrg
344ed6184dfSmrgstatic void
345ed6184dfSmrginit_pointer_absolute(InputInfoPtr pInfo)
346ed6184dfSmrg{
347ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
348ed6184dfSmrg    int min, max, res;
349ed6184dfSmrg    int nbuttons = 7;
350ed6184dfSmrg    bool has_pressure = false;
351ed6184dfSmrg    int num_axes = 0;
352ed6184dfSmrg
353ed6184dfSmrg    unsigned char btnmap[MAX_BUTTONS + 1];
354ed6184dfSmrg    Atom btnlabels[MAX_BUTTONS];
355ed6184dfSmrg    Atom axislabels[MAX_POINTER_NUM_AXES];
356ed6184dfSmrg
357ed6184dfSmrg    nbuttons = xf86SetIntOption(pInfo->options, "PointerButtonCount", 7);
358ed6184dfSmrg    has_pressure = xf86SetBoolOption(pInfo->options, "PointerHasPressure",
359ed6184dfSmrg                                     false);
360ed6184dfSmrg
361ed6184dfSmrg    init_button_map(btnmap, ARRAY_SIZE(btnmap));
362ed6184dfSmrg    init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
363ed6184dfSmrg
364ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
365ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
366ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
367ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
368ed6184dfSmrg    if (has_pressure)
369ed6184dfSmrg        axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
370ed6184dfSmrg
371ed6184dfSmrg    InitPointerDeviceStruct((DevicePtr)dev,
372ed6184dfSmrg                            btnmap,
373ed6184dfSmrg                            nbuttons,
374ed6184dfSmrg                            btnlabels,
375ed6184dfSmrg                            ptr_ctl,
376ed6184dfSmrg                            GetMotionHistorySize(),
377ed6184dfSmrg                            num_axes ,
378ed6184dfSmrg                            axislabels);
379ed6184dfSmrg    min = 0;
380ed6184dfSmrg    max = TOUCH_AXIS_MAX;
381ed6184dfSmrg    res = 0;
382ed6184dfSmrg
383ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 0, XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X),
384ed6184dfSmrg                               min, max, res * 1000, 0, res * 1000, Absolute);
385ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 1, XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y),
386ed6184dfSmrg                               min, max, res * 1000, 0, res * 1000, Absolute);
387ed6184dfSmrg
388ed6184dfSmrg    SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, 120, 0);
389ed6184dfSmrg    SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, 120, 0);
390ed6184dfSmrg
391ed6184dfSmrg    if (has_pressure) {
392ed6184dfSmrg        xf86InitValuatorAxisStruct(dev, 4,
393ed6184dfSmrg            XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE),
394ed6184dfSmrg            0, 1000, 1, 1, 1, Absolute);
395ed6184dfSmrg    }
396ed6184dfSmrg}
397ed6184dfSmrg
398ed6184dfSmrgstatic void
399ed6184dfSmrginit_proximity(InputInfoPtr pInfo)
400ed6184dfSmrg{
401ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
402ed6184dfSmrg    InitProximityClassDeviceStruct(dev);
403ed6184dfSmrg}
404ed6184dfSmrg
405ed6184dfSmrgstatic void
406ed6184dfSmrginit_keyboard(InputInfoPtr pInfo)
407ed6184dfSmrg{
408ed6184dfSmrg    DeviceIntPtr dev= pInfo->dev;
409ed6184dfSmrg    XkbRMLVOSet rmlvo = {0};
410ed6184dfSmrg    XkbRMLVOSet defaults = {0};
411ed6184dfSmrg
412ed6184dfSmrg    XkbGetRulesDflts(&defaults);
413ed6184dfSmrg
414ed6184dfSmrg    rmlvo.rules = xf86SetStrOption(pInfo->options, "xkb_rules", defaults.rules);
415ed6184dfSmrg    rmlvo.model = xf86SetStrOption(pInfo->options, "xkb_model", defaults.model);
416ed6184dfSmrg    rmlvo.layout = xf86SetStrOption(pInfo->options, "xkb_layout", defaults.layout);
417ed6184dfSmrg    rmlvo.variant = xf86SetStrOption(pInfo->options, "xkb_variant", defaults.variant);
418ed6184dfSmrg    rmlvo.options = xf86SetStrOption(pInfo->options, "xkb_options", defaults.options);
419ed6184dfSmrg
420ed6184dfSmrg    InitKeyboardDeviceStruct(dev, &rmlvo, NULL, NULL);
421ed6184dfSmrg    XkbFreeRMLVOSet(&rmlvo, FALSE);
422ed6184dfSmrg    XkbFreeRMLVOSet(&defaults, FALSE);
423ed6184dfSmrg}
424ed6184dfSmrg
425ed6184dfSmrgstatic void
426ed6184dfSmrginit_touch(InputInfoPtr pInfo)
427ed6184dfSmrg{
428ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
429ed6184dfSmrg    int min, max, res;
430ed6184dfSmrg    unsigned char btnmap[MAX_BUTTONS + 1];
431ed6184dfSmrg    Atom btnlabels[MAX_BUTTONS];
432ed6184dfSmrg    Atom axislabels[MAX_TOUCH_NUM_AXES];
433ed6184dfSmrg    int num_axes = 0;
434ed6184dfSmrg    int nbuttons = 7;
435ed6184dfSmrg    int ntouches = TOUCH_MAX_SLOTS;
436ed6184dfSmrg
437ed6184dfSmrg    init_button_map(btnmap, ARRAY_SIZE(btnmap));
438ed6184dfSmrg    init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
439ed6184dfSmrg
440ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X);
441ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y);
442ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
443ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
444ed6184dfSmrg    axislabels[num_axes++] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_PRESSURE);
445ed6184dfSmrg
446ed6184dfSmrg    InitPointerDeviceStruct((DevicePtr)dev,
447ed6184dfSmrg                            btnmap,
448ed6184dfSmrg                            nbuttons,
449ed6184dfSmrg                            btnlabels,
450ed6184dfSmrg                            ptr_ctl,
451ed6184dfSmrg                            GetMotionHistorySize(),
452ed6184dfSmrg                            num_axes,
453ed6184dfSmrg                            axislabels);
454ed6184dfSmrg    min = 0;
455ed6184dfSmrg    max = TOUCH_AXIS_MAX;
456ed6184dfSmrg    res = 0;
457ed6184dfSmrg
458ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 0,
459ed6184dfSmrg                               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X),
460ed6184dfSmrg                               min, max, res * 1000, 0, res * 1000, Absolute);
461ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 1,
462ed6184dfSmrg                               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y),
463ed6184dfSmrg                               min, max, res * 1000, 0, res * 1000, Absolute);
464ed6184dfSmrg
465ed6184dfSmrg    SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, 120, 0);
466ed6184dfSmrg    SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, 120, 0);
467ed6184dfSmrg
468ed6184dfSmrg    xf86InitValuatorAxisStruct(dev, 4,
469ed6184dfSmrg                               XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_PRESSURE),
470ed6184dfSmrg                               min, TABLET_PRESSURE_AXIS_MAX, res * 1000, 0, res * 1000, Absolute);
471ed6184dfSmrg
472ed6184dfSmrg    ntouches = xf86SetIntOption(pInfo->options, "TouchCount", TOUCH_MAX_SLOTS);
473ed6184dfSmrg    if (ntouches == 0) /* unknown */
474ed6184dfSmrg        ntouches = TOUCH_MAX_SLOTS;
475ed6184dfSmrg    InitTouchClassDeviceStruct(dev, ntouches, XIDirectTouch, 2);
476ed6184dfSmrg}
477ed6184dfSmrg
478ed6184dfSmrgstatic void
479ed6184dfSmrginit_gesture(InputInfoPtr pInfo)
480ed6184dfSmrg{
481ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
482ed6184dfSmrg    int ntouches = TOUCH_MAX_SLOTS;
483ed6184dfSmrg    InitGestureClassDeviceStruct(dev, ntouches);
484ed6184dfSmrg}
485ed6184dfSmrg
486ed6184dfSmrgstatic void
487ed6184dfSmrgdevice_init(DeviceIntPtr dev)
488ed6184dfSmrg{
489ed6184dfSmrg    InputInfoPtr pInfo = dev->public.devicePrivate;
490ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
491ed6184dfSmrg
492ed6184dfSmrg    dev->public.on = FALSE;
493ed6184dfSmrg
494ed6184dfSmrg    switch (driver_data->device_type) {
495ed6184dfSmrg        case DEVICE_KEYBOARD:
496ed6184dfSmrg            init_keyboard(pInfo);
497ed6184dfSmrg            break;
498ed6184dfSmrg        case DEVICE_POINTER:
499ed6184dfSmrg            init_pointer(pInfo);
500ed6184dfSmrg            break;
501ed6184dfSmrg        case DEVICE_POINTER_GESTURE:
502ed6184dfSmrg            init_pointer(pInfo);
503ed6184dfSmrg            init_gesture(pInfo);
504ed6184dfSmrg            break;
505ed6184dfSmrg        case DEVICE_POINTER_ABS:
506ed6184dfSmrg            init_pointer_absolute(pInfo);
507ed6184dfSmrg            break;
508ed6184dfSmrg        case DEVICE_POINTER_ABS_PROXIMITY:
509ed6184dfSmrg            init_pointer_absolute(pInfo);
510ed6184dfSmrg            init_proximity(pInfo);
511ed6184dfSmrg            break;
512ed6184dfSmrg        case DEVICE_TOUCH:
513ed6184dfSmrg            init_touch(pInfo);
514ed6184dfSmrg            break;
515ed6184dfSmrg    }
516ed6184dfSmrg}
517ed6184dfSmrg
518ed6184dfSmrgstatic void
519ed6184dfSmrgdevice_destroy(DeviceIntPtr dev)
520ed6184dfSmrg{
521ed6184dfSmrg    InputInfoPtr pInfo = dev->public.devicePrivate;
522ed6184dfSmrg    xf86IDrvMsg(pInfo, X_INFO, "Close\n");
523ed6184dfSmrg}
524ed6184dfSmrg
525ed6184dfSmrgstatic int
526ed6184dfSmrgdevice_control(DeviceIntPtr dev, int mode)
527ed6184dfSmrg{
528ed6184dfSmrg    switch (mode) {
529ed6184dfSmrg        case DEVICE_INIT:
530ed6184dfSmrg            device_init(dev);
531ed6184dfSmrg            break;
532ed6184dfSmrg        case DEVICE_ON:
533ed6184dfSmrg            device_on(dev);
534ed6184dfSmrg            break;
535ed6184dfSmrg        case DEVICE_OFF:
536ed6184dfSmrg            device_off(dev);
537ed6184dfSmrg            break;
538ed6184dfSmrg        case DEVICE_CLOSE:
539ed6184dfSmrg            device_destroy(dev);
540ed6184dfSmrg            break;
541ed6184dfSmrg    }
542ed6184dfSmrg
543ed6184dfSmrg    return Success;
544ed6184dfSmrg}
545ed6184dfSmrg
546ed6184dfSmrgstatic void
547ed6184dfSmrgconvert_to_valuator_mask(xf86ITValuatorData *event, ValuatorMask *mask)
548ed6184dfSmrg{
549ed6184dfSmrg    valuator_mask_zero(mask);
550ed6184dfSmrg    for (int i = 0; i < min(XF86IT_MAX_VALUATORS, MAX_VALUATORS); ++i) {
551ed6184dfSmrg        if (BitIsOn(event->mask, i)) {
552ed6184dfSmrg            if (event->has_unaccelerated) {
553ed6184dfSmrg                valuator_mask_set_unaccelerated(mask, i, event->valuators[i],
554ed6184dfSmrg                                                event->unaccelerated[i]);
555ed6184dfSmrg            } else {
556ed6184dfSmrg                valuator_mask_set_double(mask, i, event->valuators[i]);
557ed6184dfSmrg            }
558ed6184dfSmrg        }
559ed6184dfSmrg    }
560ed6184dfSmrg}
561ed6184dfSmrg
562ed6184dfSmrgstatic void
563ed6184dfSmrghandle_client_version(InputInfoPtr pInfo, xf86ITEventClientVersion *event)
564ed6184dfSmrg{
565ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
566ed6184dfSmrg    xf86ITResponseServerVersion response;
567ed6184dfSmrg
568ed6184dfSmrg    response.header.length = sizeof(response);
569ed6184dfSmrg    response.header.type = XF86IT_RESPONSE_SERVER_VERSION;
570ed6184dfSmrg    response.major = XF86IT_PROTOCOL_VERSION_MAJOR;
571ed6184dfSmrg    response.minor = XF86IT_PROTOCOL_VERSION_MINOR;
572ed6184dfSmrg
573ed6184dfSmrg    if (write(driver_data->connection_fd, &response, response.header.length) != response.header.length) {
574ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Error writing driver version: %s\n", strerror(errno));
575ed6184dfSmrg        teardown_client_connection(pInfo);
576ed6184dfSmrg        return;
577ed6184dfSmrg    }
578ed6184dfSmrg
579ed6184dfSmrg    if (event->major != XF86IT_PROTOCOL_VERSION_MAJOR ||
580ed6184dfSmrg        event->minor > XF86IT_PROTOCOL_VERSION_MINOR)
581ed6184dfSmrg    {
582ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Unsupported protocol version: %d.%d (current %d.%d)\n",
583ed6184dfSmrg                    event->major, event->minor,
584ed6184dfSmrg                    XF86IT_PROTOCOL_VERSION_MAJOR,
585ed6184dfSmrg                    XF86IT_PROTOCOL_VERSION_MINOR);
586ed6184dfSmrg        teardown_client_connection(pInfo);
587ed6184dfSmrg        return;
588ed6184dfSmrg    }
589ed6184dfSmrg
590ed6184dfSmrg    driver_data->client_protocol.major = event->major;
591ed6184dfSmrg    driver_data->client_protocol.minor = event->minor;
592ed6184dfSmrg
593ed6184dfSmrg    driver_data->client_state = CLIENT_STATE_READY;
594ed6184dfSmrg}
595ed6184dfSmrg
596ed6184dfSmrgstatic void
597ed6184dfSmrghandle_wait_for_sync(InputInfoPtr pInfo)
598ed6184dfSmrg{
599ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
600ed6184dfSmrg    bool notify_synchronization = false;
601ed6184dfSmrg    void *drain_write_closure;
602ed6184dfSmrg
603ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling sync event\n");
604ed6184dfSmrg
605ed6184dfSmrg    pthread_mutex_lock(&driver_data->waiting_for_drain_mutex);
606ed6184dfSmrg    if (driver_data->last_processed_event_num == driver_data->last_event_num) {
607ed6184dfSmrg        notify_synchronization = true;
608ed6184dfSmrg    } else {
609ed6184dfSmrg        driver_data->waiting_for_drain = true;
610ed6184dfSmrg    }
611ed6184dfSmrg    pthread_mutex_unlock(&driver_data->waiting_for_drain_mutex);
612ed6184dfSmrg
613ed6184dfSmrg    if (notify_synchronization) {
614ed6184dfSmrg        drain_write_closure = (void*)(intptr_t) driver_data->connection_fd;
615ed6184dfSmrg        xf86IDrvMsg(pInfo, X_DEBUG, "Synchronization finished\n");
616ed6184dfSmrg        notify_sync_finished(NULL, drain_write_closure);
617ed6184dfSmrg    }
618ed6184dfSmrg}
619ed6184dfSmrg
620ed6184dfSmrgstatic void
621ed6184dfSmrghandle_motion(InputInfoPtr pInfo, xf86ITEventMotion *event)
622ed6184dfSmrg{
623ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
624ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
625ed6184dfSmrg    ValuatorMask *mask = driver_data->valuators;
626ed6184dfSmrg
627ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling motion event\n");
628ed6184dfSmrg
629ed6184dfSmrg    driver_data->last_event_num++;
630ed6184dfSmrg
631ed6184dfSmrg    convert_to_valuator_mask(&event->valuators, mask);
632ed6184dfSmrg    xf86PostMotionEventM(dev, event->is_absolute ? Absolute : Relative, mask);
633ed6184dfSmrg}
634ed6184dfSmrg
635ed6184dfSmrgstatic void
636ed6184dfSmrghandle_proximity(InputInfoPtr pInfo, xf86ITEventProximity *event)
637ed6184dfSmrg{
638ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
639ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
640ed6184dfSmrg    ValuatorMask *mask = driver_data->valuators;
641ed6184dfSmrg
642ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling proximity event\n");
643ed6184dfSmrg
644ed6184dfSmrg    driver_data->last_event_num++;
645ed6184dfSmrg
646ed6184dfSmrg    convert_to_valuator_mask(&event->valuators, mask);
647ed6184dfSmrg    xf86PostProximityEventM(dev, event->is_prox_in, mask);
648ed6184dfSmrg}
649ed6184dfSmrg
650ed6184dfSmrgstatic void
651ed6184dfSmrghandle_button(InputInfoPtr pInfo, xf86ITEventButton *event)
652ed6184dfSmrg{
653ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
654ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
655ed6184dfSmrg    ValuatorMask *mask = driver_data->valuators;
656ed6184dfSmrg
657ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling button event\n");
658ed6184dfSmrg
659ed6184dfSmrg    driver_data->last_event_num++;
660ed6184dfSmrg
661ed6184dfSmrg    convert_to_valuator_mask(&event->valuators, mask);
662ed6184dfSmrg    xf86PostButtonEventM(dev, event->is_absolute ? Absolute : Relative, event->button,
663ed6184dfSmrg                         event->is_press, mask);
664ed6184dfSmrg}
665ed6184dfSmrg
666ed6184dfSmrgstatic void
667ed6184dfSmrghandle_key(InputInfoPtr pInfo, xf86ITEventKey *event)
668ed6184dfSmrg{
669ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
670ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
671ed6184dfSmrg
672ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling key event\n");
673ed6184dfSmrg
674ed6184dfSmrg    driver_data->last_event_num++;
675ed6184dfSmrg
676ed6184dfSmrg    xf86PostKeyboardEvent(dev, event->key_code, event->is_press);
677ed6184dfSmrg}
678ed6184dfSmrg
679ed6184dfSmrgstatic void
680ed6184dfSmrghandle_touch(InputInfoPtr pInfo, xf86ITEventTouch *event)
681ed6184dfSmrg{
682ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
683ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
684ed6184dfSmrg    ValuatorMask *mask = driver_data->valuators;
685ed6184dfSmrg
686ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling touch event\n");
687ed6184dfSmrg
688ed6184dfSmrg    driver_data->last_event_num++;
689ed6184dfSmrg
690ed6184dfSmrg    convert_to_valuator_mask(&event->valuators, mask);
691ed6184dfSmrg    xf86PostTouchEvent(dev, event->touchid, event->touch_type, 0, mask);
692ed6184dfSmrg}
693ed6184dfSmrg
694ed6184dfSmrgstatic void
695ed6184dfSmrghandle_gesture_swipe(InputInfoPtr pInfo, xf86ITEventGestureSwipe *event)
696ed6184dfSmrg{
697ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
698ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
699ed6184dfSmrg
700ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling gesture swipe event\n");
701ed6184dfSmrg
702ed6184dfSmrg    driver_data->last_event_num++;
703ed6184dfSmrg
704ed6184dfSmrg    xf86PostGestureSwipeEvent(dev, event->gesture_type, event->num_touches, event->flags,
705ed6184dfSmrg                              event->delta_x, event->delta_y,
706ed6184dfSmrg                              event->delta_unaccel_x, event->delta_unaccel_y);
707ed6184dfSmrg}
708ed6184dfSmrg
709ed6184dfSmrgstatic void
710ed6184dfSmrghandle_gesture_pinch(InputInfoPtr pInfo, xf86ITEventGesturePinch *event)
711ed6184dfSmrg{
712ed6184dfSmrg    DeviceIntPtr dev = pInfo->dev;
713ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
714ed6184dfSmrg
715ed6184dfSmrg    xf86IDrvMsg(pInfo, X_DEBUG, "Handling gesture pinch event\n");
716ed6184dfSmrg
717ed6184dfSmrg    driver_data->last_event_num++;
718ed6184dfSmrg
719ed6184dfSmrg    xf86PostGesturePinchEvent(dev, event->gesture_type, event->num_touches, event->flags,
720ed6184dfSmrg                              event->delta_x, event->delta_y,
721ed6184dfSmrg                              event->delta_unaccel_x, event->delta_unaccel_y,
722ed6184dfSmrg                              event->scale, event->delta_angle);
723ed6184dfSmrg}
724ed6184dfSmrg
725ed6184dfSmrgstatic void
726ed6184dfSmrgclient_new_handle_event(InputInfoPtr pInfo, xf86ITEventAny *event)
727ed6184dfSmrg{
728ed6184dfSmrg    switch (event->header.type) {
729ed6184dfSmrg        case XF86IT_EVENT_CLIENT_VERSION:
730ed6184dfSmrg            handle_client_version(pInfo, &event->version);
731ed6184dfSmrg            break;
732ed6184dfSmrg        default:
733ed6184dfSmrg            xf86IDrvMsg(pInfo, X_ERROR, "Event before client is ready: event type %d\n",
734ed6184dfSmrg                        event->header.type);
735ed6184dfSmrg            teardown_client_connection(pInfo);
736ed6184dfSmrg            break;
737ed6184dfSmrg    }
738ed6184dfSmrg}
739ed6184dfSmrg
740ed6184dfSmrgstatic void
741ed6184dfSmrgclient_ready_handle_event(InputInfoPtr pInfo, xf86ITEventAny *event)
742ed6184dfSmrg{
743ed6184dfSmrg    switch (event->header.type) {
744ed6184dfSmrg        case XF86IT_EVENT_WAIT_FOR_SYNC:
745ed6184dfSmrg            handle_wait_for_sync(pInfo);
746ed6184dfSmrg            break;
747ed6184dfSmrg        case XF86IT_EVENT_MOTION:
748ed6184dfSmrg            handle_motion(pInfo, &event->motion);
749ed6184dfSmrg            break;
750ed6184dfSmrg        case XF86IT_EVENT_PROXIMITY:
751ed6184dfSmrg            handle_proximity(pInfo, &event->proximity);
752ed6184dfSmrg            break;
753ed6184dfSmrg        case XF86IT_EVENT_BUTTON:
754ed6184dfSmrg            handle_button(pInfo, &event->button);
755ed6184dfSmrg            break;
756ed6184dfSmrg        case XF86IT_EVENT_KEY:
757ed6184dfSmrg            handle_key(pInfo, &event->key);
758ed6184dfSmrg            break;
759ed6184dfSmrg        case XF86IT_EVENT_TOUCH:
760ed6184dfSmrg            handle_touch(pInfo, &event->touch);
761ed6184dfSmrg            break;
762ed6184dfSmrg        case XF86IT_EVENT_GESTURE_PINCH:
763ed6184dfSmrg            handle_gesture_pinch(pInfo, &(event->pinch));
764ed6184dfSmrg            break;
765ed6184dfSmrg        case XF86IT_EVENT_GESTURE_SWIPE:
766ed6184dfSmrg            handle_gesture_swipe(pInfo, &(event->swipe));
767ed6184dfSmrg            break;
768ed6184dfSmrg        case XF86IT_EVENT_CLIENT_VERSION:
769ed6184dfSmrg            xf86IDrvMsg(pInfo, X_ERROR, "Only single ClientVersion event is allowed\n");
770ed6184dfSmrg            teardown_client_connection(pInfo);
771ed6184dfSmrg            break;
772ed6184dfSmrg        default:
773ed6184dfSmrg            xf86IDrvMsg(pInfo, X_ERROR, "Invalid event when client is ready %d\n",
774ed6184dfSmrg                        event->header.type);
775ed6184dfSmrg            teardown_client_connection(pInfo);
776ed6184dfSmrg            break;
777ed6184dfSmrg    }
778ed6184dfSmrg}
779ed6184dfSmrg
780ed6184dfSmrgstatic void
781ed6184dfSmrghandle_event(InputInfoPtr pInfo, xf86ITEventAny *event)
782ed6184dfSmrg{
783ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
784ed6184dfSmrg
785ed6184dfSmrg    if (!pInfo->dev->public.on)
786ed6184dfSmrg        return;
787ed6184dfSmrg
788ed6184dfSmrg    switch (driver_data->client_state) {
789ed6184dfSmrg        case CLIENT_STATE_NOT_CONNECTED:
790ed6184dfSmrg            xf86IDrvMsg(pInfo, X_ERROR, "Got event when client is not connected\n");
791ed6184dfSmrg            break;
792ed6184dfSmrg        case CLIENT_STATE_NEW:
793ed6184dfSmrg            client_new_handle_event(pInfo, event);
794ed6184dfSmrg            break;
795ed6184dfSmrg        case CLIENT_STATE_READY:
796ed6184dfSmrg            client_ready_handle_event(pInfo, event);
797ed6184dfSmrg            break;
798ed6184dfSmrg    }
799ed6184dfSmrg}
800ed6184dfSmrg
801ed6184dfSmrgstatic bool
802ed6184dfSmrgis_supported_event(enum xf86ITEventType type)
803ed6184dfSmrg{
804ed6184dfSmrg    switch (type) {
805ed6184dfSmrg        case XF86IT_EVENT_CLIENT_VERSION:
806ed6184dfSmrg        case XF86IT_EVENT_WAIT_FOR_SYNC:
807ed6184dfSmrg        case XF86IT_EVENT_MOTION:
808ed6184dfSmrg        case XF86IT_EVENT_PROXIMITY:
809ed6184dfSmrg        case XF86IT_EVENT_BUTTON:
810ed6184dfSmrg        case XF86IT_EVENT_KEY:
811ed6184dfSmrg        case XF86IT_EVENT_TOUCH:
812ed6184dfSmrg        case XF86IT_EVENT_GESTURE_PINCH:
813ed6184dfSmrg        case XF86IT_EVENT_GESTURE_SWIPE:
814ed6184dfSmrg            return true;
815ed6184dfSmrg    }
816ed6184dfSmrg    return false;
817ed6184dfSmrg}
818ed6184dfSmrg
819ed6184dfSmrgstatic int
820ed6184dfSmrgget_event_size(enum xf86ITEventType type)
821ed6184dfSmrg{
822ed6184dfSmrg    switch (type) {
823ed6184dfSmrg        case XF86IT_EVENT_CLIENT_VERSION: return sizeof(xf86ITEventClientVersion);
824ed6184dfSmrg        case XF86IT_EVENT_WAIT_FOR_SYNC: return sizeof(xf86ITEventWaitForSync);
825ed6184dfSmrg        case XF86IT_EVENT_MOTION: return sizeof(xf86ITEventMotion);
826ed6184dfSmrg        case XF86IT_EVENT_PROXIMITY: return sizeof(xf86ITEventProximity);
827ed6184dfSmrg        case XF86IT_EVENT_BUTTON: return sizeof(xf86ITEventButton);
828ed6184dfSmrg        case XF86IT_EVENT_KEY: return sizeof(xf86ITEventKey);
829ed6184dfSmrg        case XF86IT_EVENT_TOUCH: return sizeof(xf86ITEventTouch);
830ed6184dfSmrg        case XF86IT_EVENT_GESTURE_PINCH: return sizeof(xf86ITEventGesturePinch);
831ed6184dfSmrg        case XF86IT_EVENT_GESTURE_SWIPE: return sizeof(xf86ITEventGestureSwipe);
832ed6184dfSmrg    }
833ed6184dfSmrg    abort();
834ed6184dfSmrg}
835ed6184dfSmrg
836ed6184dfSmrgstatic void
837ed6184dfSmrgread_input_from_connection(InputInfoPtr pInfo)
838ed6184dfSmrg{
839ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
840ed6184dfSmrg
841ed6184dfSmrg    while (1) {
842ed6184dfSmrg        int processed_size = 0;
843ed6184dfSmrg        int read_size = read(driver_data->connection_fd,
844ed6184dfSmrg                             driver_data->buffer.data + driver_data->buffer.valid_length,
845ed6184dfSmrg                             EVENT_BUFFER_SIZE - driver_data->buffer.valid_length);
846ed6184dfSmrg
847ed6184dfSmrg        if (read_size < 0) {
848ed6184dfSmrg            if (errno == EAGAIN || errno == EWOULDBLOCK)
849ed6184dfSmrg                return;
850ed6184dfSmrg
851ed6184dfSmrg            xf86IDrvMsg(pInfo, X_ERROR, "Error reading events: %s\n", strerror(errno));
852ed6184dfSmrg            teardown_client_connection(pInfo);
853ed6184dfSmrg            return;
854ed6184dfSmrg        }
855ed6184dfSmrg
856ed6184dfSmrg        driver_data->buffer.valid_length += read_size;
857ed6184dfSmrg
858ed6184dfSmrg        while (1) {
859dc61d50dSmrg            xf86ITEventHeader event_header;
860ed6184dfSmrg            char *event_begin = driver_data->buffer.data + processed_size;
861ed6184dfSmrg
862ed6184dfSmrg            if (driver_data->buffer.valid_length - processed_size < sizeof(xf86ITEventHeader))
863ed6184dfSmrg                break;
864ed6184dfSmrg
865dc61d50dSmrg            /* Note that event_begin pointer is not aligned, accessing it directly is
866dc61d50dSmrg               undefined behavior. We must use memcpy to copy the data to aligned data
867dc61d50dSmrg               area. Most compilers will optimize out this call out and use whatever
868dc61d50dSmrg               is most efficient to access unaligned data on a particular platform */
869dc61d50dSmrg            memcpy(&event_header, event_begin, sizeof(xf86ITEventHeader));
870ed6184dfSmrg
871dc61d50dSmrg            if (event_header.length >= EVENT_BUFFER_SIZE) {
872ed6184dfSmrg                xf86IDrvMsg(pInfo, X_ERROR, "Received event with too long length: %d\n",
873dc61d50dSmrg                            event_header.length);
874ed6184dfSmrg                teardown_client_connection(pInfo);
875ed6184dfSmrg                return;
876ed6184dfSmrg            }
877ed6184dfSmrg
878dc61d50dSmrg            if (driver_data->buffer.valid_length - processed_size < event_header.length)
879ed6184dfSmrg                break;
880ed6184dfSmrg
881dc61d50dSmrg            if (is_supported_event(event_header.type)) {
882dc61d50dSmrg                int expected_event_size = get_event_size(event_header.type);
883ed6184dfSmrg
884dc61d50dSmrg                if (event_header.length != expected_event_size) {
885ed6184dfSmrg                    xf86IDrvMsg(pInfo, X_ERROR, "Unexpected event length: was %d bytes, "
886ed6184dfSmrg                                "expected %d (event type: %d)\n",
887dc61d50dSmrg                                event_header.length, expected_event_size,
888dc61d50dSmrg                                (int) event_header.type);
889ed6184dfSmrg                    teardown_client_connection(pInfo);
890ed6184dfSmrg                    return;
891ed6184dfSmrg                }
892ed6184dfSmrg
893dc61d50dSmrg                /* We could use event_begin pointer directly, but we want to ensure correct
894dc61d50dSmrg                   data alignment (if only so that address sanitizer does not complain) */
895dc61d50dSmrg                xf86ITEventAny event_data;
896dc61d50dSmrg                memset(&event_data, 0, sizeof(event_data));
897dc61d50dSmrg                memcpy(&event_data, event_begin, event_header.length);
898dc61d50dSmrg                handle_event(pInfo, &event_data);
899ed6184dfSmrg            }
900dc61d50dSmrg            processed_size += event_header.length;
901ed6184dfSmrg        }
902ed6184dfSmrg
903ed6184dfSmrg        if (processed_size > 0) {
904ed6184dfSmrg            memmove(driver_data->buffer.data,
905ed6184dfSmrg                    driver_data->buffer.data + processed_size,
906ed6184dfSmrg                    driver_data->buffer.valid_length - processed_size);
907ed6184dfSmrg            driver_data->buffer.valid_length -= processed_size;
908ed6184dfSmrg        }
909ed6184dfSmrg
910ed6184dfSmrg        if (read_size == 0)
911ed6184dfSmrg            break;
912ed6184dfSmrg    }
913ed6184dfSmrg}
914ed6184dfSmrg
915ed6184dfSmrgstatic void
916ed6184dfSmrgread_input(InputInfoPtr pInfo)
917ed6184dfSmrg{
918ed6184dfSmrg    /* The test input driver does not set up the pInfo->fd and use the regular
919ed6184dfSmrg       read_input callback because we want to only accept the connection to
920ed6184dfSmrg       the controlling socket after the device is turned on.
921ed6184dfSmrg    */
922ed6184dfSmrg}
923ed6184dfSmrg
924ed6184dfSmrgstatic const char*
925ed6184dfSmrgget_type_name(InputInfoPtr pInfo, xf86ITDevicePtr driver_data)
926ed6184dfSmrg{
927ed6184dfSmrg    switch (driver_data->device_type) {
928ed6184dfSmrg        case DEVICE_TOUCH: return XI_TOUCHSCREEN;
929ed6184dfSmrg        case DEVICE_POINTER: return XI_MOUSE;
930ed6184dfSmrg        case DEVICE_POINTER_GESTURE: return XI_TOUCHPAD;
931ed6184dfSmrg        case DEVICE_POINTER_ABS: return XI_MOUSE;
932ed6184dfSmrg        case DEVICE_POINTER_ABS_PROXIMITY: return XI_TABLET;
933ed6184dfSmrg        case DEVICE_KEYBOARD: return XI_KEYBOARD;
934ed6184dfSmrg    }
935ed6184dfSmrg    xf86IDrvMsg(pInfo, X_ERROR, "Unexpected device type %d\n",
936ed6184dfSmrg                driver_data->device_type);
937ed6184dfSmrg    return XI_KEYBOARD;
938ed6184dfSmrg}
939ed6184dfSmrg
940ed6184dfSmrgstatic xf86ITDevicePtr
941ed6184dfSmrgdevice_alloc(void)
942ed6184dfSmrg{
943ed6184dfSmrg    xf86ITDevicePtr driver_data = calloc(sizeof(xf86ITDevice), 1);
944ed6184dfSmrg
945ed6184dfSmrg    if (!driver_data)
946ed6184dfSmrg        return NULL;
947ed6184dfSmrg
948ed6184dfSmrg    driver_data->socket_fd = -1;
949ed6184dfSmrg    driver_data->connection_fd = -1;
950ed6184dfSmrg
951ed6184dfSmrg    return driver_data;
952ed6184dfSmrg}
953ed6184dfSmrg
954ed6184dfSmrgstatic void
955ed6184dfSmrgfree_driver_data(xf86ITDevicePtr driver_data)
956ed6184dfSmrg{
957ed6184dfSmrg    if (driver_data) {
958ed6184dfSmrg        close(driver_data->connection_fd);
959ed6184dfSmrg        close(driver_data->socket_fd);
960ed6184dfSmrg        if (driver_data->socket_path)
961ed6184dfSmrg            unlink(driver_data->socket_path);
962ed6184dfSmrg        free(driver_data->socket_path);
963ed6184dfSmrg        pthread_mutex_destroy(&driver_data->waiting_for_drain_mutex);
964ed6184dfSmrg
965ed6184dfSmrg        if (driver_data->valuators)
966ed6184dfSmrg            valuator_mask_free(&driver_data->valuators);
967ed6184dfSmrg        if (driver_data->valuators_unaccelerated)
968ed6184dfSmrg            valuator_mask_free(&driver_data->valuators_unaccelerated);
969ed6184dfSmrg    }
970ed6184dfSmrg    free(driver_data);
971ed6184dfSmrg}
972ed6184dfSmrg
973ed6184dfSmrgstatic int
974ed6184dfSmrgpre_init(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
975ed6184dfSmrg{
976ed6184dfSmrg    xf86ITDevicePtr driver_data = NULL;
977ed6184dfSmrg    char *device_type_option;
978ed6184dfSmrg    struct sockaddr_un addr;
979ed6184dfSmrg
980ed6184dfSmrg    pInfo->type_name = 0;
981ed6184dfSmrg    pInfo->device_control = device_control;
982ed6184dfSmrg    pInfo->read_input = read_input;
983ed6184dfSmrg    pInfo->control_proc = NULL;
984ed6184dfSmrg    pInfo->switch_mode = NULL;
985ed6184dfSmrg
986ed6184dfSmrg    driver_data = device_alloc();
987ed6184dfSmrg    if (!driver_data)
988ed6184dfSmrg        goto fail;
989ed6184dfSmrg
990ed6184dfSmrg    driver_data->client_state = CLIENT_STATE_NOT_CONNECTED;
991ed6184dfSmrg    driver_data->last_event_num = 1;
992ed6184dfSmrg    driver_data->last_processed_event_num = 0;
993ed6184dfSmrg    driver_data->waiting_for_drain = false;
994ed6184dfSmrg    pthread_mutex_init(&driver_data->waiting_for_drain_mutex, NULL);
995ed6184dfSmrg
996ed6184dfSmrg    driver_data->valuators = valuator_mask_new(6);
997ed6184dfSmrg    if (!driver_data->valuators)
998ed6184dfSmrg        goto fail;
999ed6184dfSmrg
1000ed6184dfSmrg    driver_data->valuators_unaccelerated = valuator_mask_new(2);
1001ed6184dfSmrg    if (!driver_data->valuators_unaccelerated)
1002ed6184dfSmrg        goto fail;
1003ed6184dfSmrg
1004ed6184dfSmrg    driver_data->socket_path = xf86SetStrOption(pInfo->options, "SocketPath", NULL);
1005ed6184dfSmrg    if (!driver_data->socket_path){
1006ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "SocketPath must be specified\n");
1007ed6184dfSmrg        goto fail;
1008ed6184dfSmrg    }
1009ed6184dfSmrg
1010ed6184dfSmrg    if (strlen(driver_data->socket_path) >= sizeof(addr.sun_path)) {
1011ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "SocketPath is too long\n");
1012ed6184dfSmrg        goto fail;
1013ed6184dfSmrg    }
1014ed6184dfSmrg
1015ed6184dfSmrg    unlink(driver_data->socket_path);
1016ed6184dfSmrg
1017dc61d50dSmrg#ifdef SOCK_NONBLOCK
1018ed6184dfSmrg    driver_data->socket_fd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
1019dc61d50dSmrg#else
1020dc61d50dSmrg    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
1021dc61d50dSmrg    if (fd >= 0) {
1022dc61d50dSmrg        flags = fcntl(fd, F_GETFL, 0);
1023dc61d50dSmrg        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
1024dc61d50dSmrg            fd = -1;
1025dc61d50dSmrg        }
1026dc61d50dSmrg    }
1027dc61d50dSmrg    driver_data->socket_fd = fd;
1028dc61d50dSmrg#endif
1029dc61d50dSmrg
1030ed6184dfSmrg    if (driver_data->socket_fd < 0) {
1031ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Failed to create a socket for communication: %s\n",
1032ed6184dfSmrg                    strerror(errno));
1033ed6184dfSmrg        goto fail;
1034ed6184dfSmrg    }
1035ed6184dfSmrg
1036ed6184dfSmrg    memset(&addr, 0, sizeof(addr));
1037ed6184dfSmrg    addr.sun_family = AF_UNIX;
1038ed6184dfSmrg    strncpy(addr.sun_path, driver_data->socket_path, sizeof(addr.sun_path) - 1);
1039ed6184dfSmrg
1040ed6184dfSmrg    if (bind(driver_data->socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
1041ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Failed to assign address to the socket\n");
1042ed6184dfSmrg        goto fail;
1043ed6184dfSmrg    }
1044ed6184dfSmrg
1045ed6184dfSmrg    if (chmod(driver_data->socket_path, 0777) != 0) {
1046ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Failed to chmod the socket path\n");
1047ed6184dfSmrg        goto fail;
1048ed6184dfSmrg    }
1049ed6184dfSmrg
1050ed6184dfSmrg    if (listen(driver_data->socket_fd, 1) != 0) {
1051ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Failed to listen on the socket\n");
1052ed6184dfSmrg        goto fail;
1053ed6184dfSmrg    }
1054ed6184dfSmrg
1055ed6184dfSmrg    device_type_option = xf86SetStrOption(pInfo->options, "DeviceType", NULL);
1056ed6184dfSmrg    if (device_type_option == NULL) {
1057ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "DeviceType option must be specified\n");
1058ed6184dfSmrg        goto fail;
1059ed6184dfSmrg    }
1060ed6184dfSmrg
1061ed6184dfSmrg    if (strcmp(device_type_option, "Keyboard") == 0) {
1062ed6184dfSmrg        driver_data->device_type = DEVICE_KEYBOARD;
1063ed6184dfSmrg    } else if (strcmp(device_type_option, "Pointer") == 0) {
1064ed6184dfSmrg        driver_data->device_type = DEVICE_POINTER;
1065ed6184dfSmrg    } else if (strcmp(device_type_option, "PointerGesture") == 0) {
1066ed6184dfSmrg        driver_data->device_type = DEVICE_POINTER_GESTURE;
1067ed6184dfSmrg    } else if (strcmp(device_type_option, "PointerAbsolute") == 0) {
1068ed6184dfSmrg        driver_data->device_type = DEVICE_POINTER_ABS;
1069ed6184dfSmrg    } else if (strcmp(device_type_option, "PointerAbsoluteProximity") == 0) {
1070ed6184dfSmrg        driver_data->device_type = DEVICE_POINTER_ABS_PROXIMITY;
1071ed6184dfSmrg    } else if (strcmp(device_type_option, "Touch") == 0) {
1072ed6184dfSmrg        driver_data->device_type = DEVICE_TOUCH;
1073ed6184dfSmrg    } else {
1074ed6184dfSmrg        xf86IDrvMsg(pInfo, X_ERROR, "Unsupported DeviceType option.\n");
1075ed6184dfSmrg        goto fail;
1076ed6184dfSmrg    }
1077ed6184dfSmrg    free(device_type_option);
1078ed6184dfSmrg
1079ed6184dfSmrg    pInfo->private = driver_data;
1080ed6184dfSmrg    driver_data->pInfo = pInfo;
1081ed6184dfSmrg
1082ed6184dfSmrg    pInfo->type_name = get_type_name(pInfo, driver_data);
1083ed6184dfSmrg
1084ed6184dfSmrg    return Success;
1085ed6184dfSmrgfail:
1086ed6184dfSmrg    free_driver_data(driver_data);
1087ed6184dfSmrg    return BadValue;
1088ed6184dfSmrg}
1089ed6184dfSmrg
1090ed6184dfSmrgstatic void
1091ed6184dfSmrguninit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
1092ed6184dfSmrg{
1093ed6184dfSmrg    xf86ITDevicePtr driver_data = pInfo->private;
1094ed6184dfSmrg    free_driver_data(driver_data);
1095ed6184dfSmrg    pInfo->private = NULL;
1096ed6184dfSmrg    xf86DeleteInput(pInfo, flags);
1097ed6184dfSmrg}
1098ed6184dfSmrg
1099ed6184dfSmrgInputDriverRec driver = {
1100ed6184dfSmrg    .driverVersion = 1,
1101ed6184dfSmrg    .driverName = "inputtest",
1102ed6184dfSmrg    .PreInit = pre_init,
1103ed6184dfSmrg    .UnInit = uninit,
1104ed6184dfSmrg    .module = NULL,
1105ed6184dfSmrg    .default_options = NULL,
1106ed6184dfSmrg    .capabilities = 0
1107ed6184dfSmrg};
1108ed6184dfSmrg
1109ed6184dfSmrgstatic XF86ModuleVersionInfo version_info = {
1110ed6184dfSmrg    "inputtest",
1111ed6184dfSmrg    MODULEVENDORSTRING,
1112ed6184dfSmrg    MODINFOSTRING1,
1113ed6184dfSmrg    MODINFOSTRING2,
1114ed6184dfSmrg    XORG_VERSION_CURRENT,
1115ed6184dfSmrg    XORG_VERSION_MAJOR,
1116ed6184dfSmrg    XORG_VERSION_MINOR,
1117ed6184dfSmrg    XORG_VERSION_PATCH,
1118ed6184dfSmrg    ABI_CLASS_XINPUT,
1119ed6184dfSmrg    ABI_XINPUT_VERSION,
1120ed6184dfSmrg    MOD_CLASS_XINPUT,
1121ed6184dfSmrg    {0, 0, 0, 0}
1122ed6184dfSmrg};
1123ed6184dfSmrg
1124ed6184dfSmrgstatic void*
1125ed6184dfSmrgsetup_proc(void *module, void *options, int *errmaj, int *errmin)
1126ed6184dfSmrg{
1127ed6184dfSmrg    xf86AddInputDriver(&driver, module, 0);
1128ed6184dfSmrg    return module;
1129ed6184dfSmrg}
1130ed6184dfSmrg
1131ed6184dfSmrg_X_EXPORT XF86ModuleData inputtestModuleData = {
1132ed6184dfSmrg    .vers = &version_info,
1133ed6184dfSmrg    .setup = &setup_proc,
1134ed6184dfSmrg    .teardown = NULL
1135ed6184dfSmrg};
1136