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