Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 229919 | Differences between
and this patch

Collapse All | Expand All

(-)synaptics-0.14.6-org/synaptics.c (-18 / +26 lines)
Lines 61-70 Link Here
61
61
62
#include <unistd.h>
62
#include <unistd.h>
63
#include <sys/ioctl.h>
63
#include <sys/ioctl.h>
64
#include <string.h>
65
#include <sys/ipc.h>
66
#include <sys/shm.h>
67
#include <sys/types.h>
68
#include <sys/stat.h>
69
#include <fcntl.h>
70
#include <stdio.h>
71
#include <math.h>
72
#include <errno.h>
64
#include <misc.h>
73
#include <misc.h>
65
#include <xf86.h>
74
#include <xf86.h>
66
#define NEED_XF86_TYPES
75
#define NEED_XF86_TYPES
67
#include <xf86_ansic.h>
68
#include <xf86_OSproc.h>
76
#include <xf86_OSproc.h>
69
#include <xf86Xinput.h>
77
#include <xf86Xinput.h>
70
#include "mipointer.h"
78
#include "mipointer.h"
Lines 224-237 Link Here
224
	return TRUE;			    /* Already allocated */
232
	return TRUE;			    /* Already allocated */
225
233
226
    if (priv->shm_config) {
234
    if (priv->shm_config) {
227
	if ((shmid = xf86shmget(SHM_SYNAPTICS, 0, 0)) != -1)
235
	if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
228
	    xf86shmctl(shmid, XF86IPC_RMID, NULL);
236
	    shmctl(shmid, IPC_RMID, NULL);
229
	if ((shmid = xf86shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM),
237
	if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM),
230
				0777 | XF86IPC_CREAT)) == -1) {
238
				0777 | IPC_CREAT)) == -1) {
231
	    xf86Msg(X_ERROR, "%s error shmget\n", local->name);
239
	    xf86Msg(X_ERROR, "%s error shmget\n", local->name);
232
	    return FALSE;
240
	    return FALSE;
233
	}
241
	}
234
	if ((priv->synpara = (SynapticsSHM*)xf86shmat(shmid, NULL, 0)) == NULL) {
242
	if ((priv->synpara = (SynapticsSHM*)shmat(shmid, NULL, 0)) == NULL) {
235
	    xf86Msg(X_ERROR, "%s error shmat\n", local->name);
243
	    xf86Msg(X_ERROR, "%s error shmat\n", local->name);
236
	    return FALSE;
244
	    return FALSE;
237
	}
245
	}
Lines 257-264 Link Here
257
	return;
265
	return;
258
266
259
    if (priv->shm_config) {
267
    if (priv->shm_config) {
260
	if ((shmid = xf86shmget(SHM_SYNAPTICS, 0, 0)) != -1)
268
	if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
261
	    xf86shmctl(shmid, XF86IPC_RMID, NULL);
269
	    shmctl(shmid, IPC_RMID, NULL);
262
    } else {
270
    } else {
263
	xfree(priv->synpara);
271
	xfree(priv->synpara);
264
    }
272
    }
Lines 272-278 Link Here
272
    char *str_par;
280
    char *str_par;
273
    double value;
281
    double value;
274
    str_par = xf86FindOptionValue(options, optname);
282
    str_par = xf86FindOptionValue(options, optname);
275
    if ((!str_par) || (xf86sscanf(str_par, "%lf", &value) != 1))
283
    if ((!str_par) || (sscanf(str_par, "%lf", &value) != 1))
276
	return default_value;
284
	return default_value;
277
    return value;
285
    return value;
278
}
286
}
Lines 437-444 Link Here
437
    priv->fifofd = -1;
445
    priv->fifofd = -1;
438
    if (repeater) {
446
    if (repeater) {
439
	/* create repeater fifo */
447
	/* create repeater fifo */
440
	if ((xf86mknod(repeater, 666, XF86_S_IFIFO) != 0) &&
448
	if ((mknod(repeater, 666, S_IFIFO) != 0) &&
441
	    (xf86errno != xf86_EEXIST)) {
449
	    (errno != EEXIST)) {
442
	    xf86Msg(X_ERROR, "%s can't create repeater fifo\n", local->name);
450
	    xf86Msg(X_ERROR, "%s can't create repeater fifo\n", local->name);
443
	} else {
451
	} else {
444
	    /* open the repeater fifo */
452
	    /* open the repeater fifo */
Lines 447-453 Link Here
447
		xf86Msg(X_ERROR, "%s repeater device open failed\n", local->name);
455
		xf86Msg(X_ERROR, "%s repeater device open failed\n", local->name);
448
	    }
456
	    }
449
	}
457
	}
450
	xf86free(repeater);
458
	free(repeater);
451
    }
459
    }
452
460
453
    if (!QueryHardware(local)) {
461
    if (!QueryHardware(local)) {
Lines 634-640 Link Here
634
static int
642
static int
635
move_distance(int dx, int dy)
643
move_distance(int dx, int dy)
636
{
644
{
637
    return xf86sqrt((dx * dx) + (dy * dy));
645
    return sqrt((dx * dx) + (dy * dy));
638
}
646
}
639
647
640
/*
648
/*
Lines 669-682 Link Here
669
    double xCenter = (priv->synpara->left_edge + priv->synpara->right_edge) / 2.0;
677
    double xCenter = (priv->synpara->left_edge + priv->synpara->right_edge) / 2.0;
670
    double yCenter = (priv->synpara->top_edge + priv->synpara->bottom_edge) / 2.0;
678
    double yCenter = (priv->synpara->top_edge + priv->synpara->bottom_edge) / 2.0;
671
679
672
    return xf86atan2(-(y - yCenter), x - xCenter);
680
    return atan2(-(y - yCenter), x - xCenter);
673
}
681
}
674
682
675
/* return angle difference */
683
/* return angle difference */
676
static double
684
static double
677
diffa(double a1, double a2)
685
diffa(double a1, double a2)
678
{
686
{
679
    double da = xf86fmod(a2 - a1, 2 * M_PI);
687
    double da = fmod(a2 - a1, 2 * M_PI);
680
    if (da < 0)
688
    if (da < 0)
681
	da += 2 * M_PI;
689
	da += 2 * M_PI;
682
    if (da > M_PI)
690
    if (da > M_PI)
Lines 784-790 Link Here
784
	int c;
792
	int c;
785
	while ((c = XisbRead(priv->comm.buffer)) >= 0) {
793
	while ((c = XisbRead(priv->comm.buffer)) >= 0) {
786
	    unsigned char u = (unsigned char)c;
794
	    unsigned char u = (unsigned char)c;
787
	    xf86write(priv->fifofd, &u, 1);
795
	    write(priv->fifofd, &u, 1);
788
	    if (++count >= 3)
796
	    if (++count >= 3)
789
		break;
797
		break;
790
	}
798
	}
Lines 1280-1289 Link Here
1280
1288
1281
	    /* save the fraction, report the integer part */
1289
	    /* save the fraction, report the integer part */
1282
	    tmpf = dx * speed + x_edge_speed * dtime + priv->frac_x;
1290
	    tmpf = dx * speed + x_edge_speed * dtime + priv->frac_x;
1283
	    priv->frac_x = xf86modf(tmpf, &integral);
1291
	    priv->frac_x = modf(tmpf, &integral);
1284
	    dx = integral;
1292
	    dx = integral;
1285
	    tmpf = dy * speed + y_edge_speed * dtime + priv->frac_y;
1293
	    tmpf = dy * speed + y_edge_speed * dtime + priv->frac_y;
1286
	    priv->frac_y = xf86modf(tmpf, &integral);
1294
	    priv->frac_y = modf(tmpf, &integral);
1287
	    dy = integral;
1295
	    dy = integral;
1288
	}
1296
	}
1289
1297
(-)synaptics-0.14.6-org/synaptics.c~ (+1856 lines)
Line 0 Link Here
1
/*
2
 *   Copyright 2006 Stefan Bethge <stefan.bethge@web.de>
3
 *     patch for two-fingered scrolling
4
 *
5
 *   Copyright 2004 Matthias Ihmig <m.ihmig@gmx.net>
6
 *     patch for pressure dependent EdgeMotion speed
7
 *
8
 *   Copyright 2004 Alexei Gilchrist <alexei@physics.uq.edu.au>
9
 *     patch for circular scrolling
10
 *
11
 *   Copyright 2003 Jörg Bösner <ich@joerg-boesner.de>
12
 *     patch for switching the touchpad off (for example, when a
13
 *     USB mouse is connected)
14
 *
15
 *   Copyright 2003 Hartwig Felger <hgfelger@hgfelger.de>
16
 *     patch to make the horizontal wheel replacement buttons work.
17
 *
18
 *   Copyright 2002 Peter Osterlund <petero2@telia.com>
19
 *     patches for fast scrolling, palm detection, edge motion,
20
 *     horizontal scrolling
21
 *
22
 *   Copyright 2002 S. Lehner <sam_x@bluemail.ch>
23
 *     for newer Firmware (5.8) protocol changes for 3rd to 6th button
24
 *
25
 *   Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
26
 *     start merging tpconfig and gpm code to an xfree input module
27
 *     adding some changes and extensions (ex. 3rd and 4th button)
28
 *
29
 *   Copyright (c) 1999 Henry Davies <hdavies@ameritech.net> for the
30
 *     absolute to relative translation code (from the gpm source)
31
 *     and some other ideas
32
 *
33
 *   Synaptics Passthrough Support
34
 *   Copyright (c) 2002 Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
35
 *   adapted to version 0.12.1
36
 *   Copyright (c) 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
37
 *
38
 *   This program is free software; you can redistribute it and/or
39
 *   modify it under the terms of the GNU General Public License
40
 *   as published by the Free Software Foundation; either version 2
41
 *   of the License, or (at your option) any later version.
42
 *
43
 *   This program is distributed in the hope that it will be useful,
44
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
45
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
46
 *   GNU General Public License for more details.
47
 *
48
 *   You should have received a copy of the GNU General Public License
49
 *   along with this program; if not, write to the Free Software
50
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
51
 *
52
 *
53
 * Trademarks are the property of their respective owners.
54
 *
55
 */
56
57
58
/*****************************************************************************
59
 *	Standard Headers
60
 ****************************************************************************/
61
62
#include <unistd.h>
63
#include <sys/ioctl.h>
64
#include <string.h>
65
#include <sys/ipc.h>
66
#include <sys/shm.h>
67
#include <sys/types.h>
68
#include <sys/stat.h>
69
#include <fcntl.h>
70
#include <stdio.h>
71
#include <math.h>
72
#include <errno.h>
73
#include <misc.h>
74
#include <xf86.h>
75
#define NEED_XF86_TYPES
76
#include <xf86_OSproc.h>
77
#include <xf86Xinput.h>
78
#include "mipointer.h"
79
#ifdef XFREE_4_0_3
80
#include <xf86Optrec.h>  		/* needed for Options */
81
#endif
82
83
84
/*****************************************************************************
85
 *	Local Headers
86
 ****************************************************************************/
87
#define SYNAPTICS_PRIVATE
88
#include "synaptics.h"
89
90
/*****************************************************************************
91
 *	Variables without includable headers
92
 ****************************************************************************/
93
94
/*****************************************************************************
95
 *	Local Variables and Types
96
 ****************************************************************************/
97
98
typedef enum {
99
    BOTTOM_EDGE = 1,
100
    TOP_EDGE = 2,
101
    LEFT_EDGE = 4,
102
    RIGHT_EDGE = 8,
103
    LEFT_BOTTOM_EDGE = BOTTOM_EDGE | LEFT_EDGE,
104
    RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE,
105
    RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE,
106
    LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE
107
} edge_type;
108
109
#define MAX(a, b) (((a)>(b))?(a):(b))
110
#define MIN(a, b) (((a)<(b))?(a):(b))
111
#define TIME_DIFF(a, b) ((int)((a)-(b)))
112
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
113
114
#ifndef M_PI
115
#define M_PI 3.14159265358979323846
116
#endif
117
118
#ifndef M_SQRT1_2
119
#define M_SQRT1_2  0.70710678118654752440  /* 1/sqrt(2) */
120
#endif
121
122
/*****************************************************************************
123
 * Forward declaration
124
 ****************************************************************************/
125
static InputInfoPtr SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
126
static Bool DeviceControl(DeviceIntPtr, int);
127
static void ReadInput(LocalDevicePtr);
128
static int HandleState(LocalDevicePtr, struct SynapticsHwState*);
129
static int ControlProc(LocalDevicePtr, xDeviceCtl*);
130
static void CloseProc(LocalDevicePtr);
131
static int SwitchMode(ClientPtr, DeviceIntPtr, int);
132
static Bool ConvertProc(LocalDevicePtr, int, int, int, int, int, int, int, int, int*, int*);
133
static Bool DeviceInit(DeviceIntPtr);
134
static Bool DeviceOn(DeviceIntPtr);
135
static Bool DeviceOff(DeviceIntPtr);
136
static Bool DeviceClose(DeviceIntPtr);
137
static Bool QueryHardware(LocalDevicePtr);
138
139
140
InputDriverRec SYNAPTICS = {
141
    1,
142
    "synaptics",
143
    NULL,
144
    SynapticsPreInit,
145
    /*SynapticsUnInit*/ NULL,
146
    NULL,
147
    0
148
};
149
150
#ifdef XFree86LOADER
151
152
static XF86ModuleVersionInfo VersionRec = {
153
    "synaptics",
154
    MODULEVENDORSTRING,
155
    MODINFOSTRING1,
156
    MODINFOSTRING2,
157
    XF86_VERSION_CURRENT,
158
    1, 0, 0,
159
    ABI_CLASS_XINPUT,
160
    ABI_XINPUT_VERSION,
161
    MOD_CLASS_XINPUT,
162
    {0, 0, 0, 0}				/* signature, to be patched into the file by
163
						 * a tool */
164
};
165
166
167
static pointer
168
SetupProc(pointer module, pointer options, int *errmaj, int *errmin)
169
{
170
    xf86AddInputDriver(&SYNAPTICS, module, 0);
171
    return module;
172
}
173
174
XF86ModuleData synapticsModuleData = {&VersionRec, &SetupProc, NULL };
175
176
#endif /* XFree86LOADER */
177
178
179
/*****************************************************************************
180
 *	Function Definitions
181
 ****************************************************************************/
182
183
static void
184
SetDeviceAndProtocol(LocalDevicePtr local)
185
{
186
    char *str_par;
187
    SynapticsPrivate *priv = local->private;
188
    enum SynapticsProtocol proto = SYN_PROTO_PSAUX;
189
190
    str_par = xf86FindOptionValue(local->options, "Protocol");
191
    if (str_par && !strcmp(str_par, "psaux")) {
192
	/* Already set up */
193
    } else if (str_par && !strcmp(str_par, "event")) {
194
	proto = SYN_PROTO_EVENT;
195
    } else if (str_par && !strcmp(str_par, "psm")) {
196
	proto = SYN_PROTO_PSM;
197
    } else if (str_par && !strcmp(str_par, "alps")) {
198
	proto = SYN_PROTO_ALPS;
199
    } else { /* default to auto-dev */
200
	if (event_proto_operations.AutoDevProbe(local))
201
	    proto = SYN_PROTO_EVENT;
202
    }
203
    switch (proto) {
204
    case SYN_PROTO_PSAUX:
205
	priv->proto_ops = &psaux_proto_operations;
206
	break;
207
    case SYN_PROTO_EVENT:
208
	priv->proto_ops = &event_proto_operations;
209
	break;
210
    case SYN_PROTO_PSM:
211
	priv->proto_ops = &psm_proto_operations;
212
	break;
213
    case SYN_PROTO_ALPS:
214
	priv->proto_ops = &alps_proto_operations;
215
	break;
216
    }
217
}
218
219
/*
220
 * Allocate and initialize memory for the SynapticsSHM data to hold driver
221
 * parameter settings.
222
 * The function will allocate shared memory if priv->shm_config is TRUE.
223
 * The allocated data is initialized from priv->synpara_default.
224
 */
225
static Bool
226
alloc_param_data(LocalDevicePtr local)
227
{
228
    int shmid;
229
    SynapticsPrivate *priv = local->private;
230
231
    if (priv->synpara)
232
	return TRUE;			    /* Already allocated */
233
234
    if (priv->shm_config) {
235
	if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
236
	    shmctl(shmid, IPC_RMID, NULL);
237
	if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM),
238
				0777 | IPC_CREAT)) == -1) {
239
	    xf86Msg(X_ERROR, "%s error shmget\n", local->name);
240
	    return FALSE;
241
	}
242
	if ((priv->synpara = (SynapticsSHM*)shmat(shmid, NULL, 0)) == NULL) {
243
	    xf86Msg(X_ERROR, "%s error shmat\n", local->name);
244
	    return FALSE;
245
	}
246
    } else {
247
	priv->synpara = xcalloc(1, sizeof(SynapticsSHM));
248
	if (!priv->synpara)
249
	    return FALSE;
250
    }
251
252
    *(priv->synpara) = priv->synpara_default;
253
    return TRUE;
254
}
255
256
/*
257
 * Free SynapticsSHM data previously allocated by alloc_param_data().
258
 */
259
static void
260
free_param_data(SynapticsPrivate *priv)
261
{
262
    int shmid;
263
264
    if (!priv->synpara)
265
	return;
266
267
    if (priv->shm_config) {
268
	if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
269
	    shmctl(shmid, IPC_RMID, NULL);
270
    } else {
271
	xfree(priv->synpara);
272
    }
273
274
    priv->synpara = NULL;
275
}
276
277
static double
278
synSetFloatOption(pointer options, const char *optname, double default_value)
279
{
280
    char *str_par;
281
    double value;
282
    str_par = xf86FindOptionValue(options, optname);
283
    if ((!str_par) || (sscanf(str_par, "%lf", &value) != 1))
284
	return default_value;
285
    return value;
286
}
287
288
/*
289
 *  called by the module loader for initialization
290
 */
291
static InputInfoPtr
292
SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
293
{
294
    LocalDevicePtr local;
295
    SynapticsPrivate *priv;
296
#ifdef XFREE_4_0_3
297
    XF86OptionPtr optList;
298
#else
299
    pointer optList;
300
#endif
301
    SynapticsSHM *pars;
302
    char *repeater;
303
    pointer opts;
304
305
    /* allocate memory for SynapticsPrivateRec */
306
    priv = xcalloc(1, sizeof(SynapticsPrivate));
307
    if (!priv)
308
	return NULL;
309
310
    /* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */
311
    local = xf86AllocateInput(drv, 0);
312
    if (!local) {
313
	xfree(priv);
314
	return NULL;
315
    }
316
317
    /* initialize the InputInfoRec */
318
    local->name                    = dev->identifier;
319
    local->type_name               = XI_MOUSE; /* XI_TOUCHPAD and KDE killed the X Server at startup ? */
320
    local->device_control          = DeviceControl;
321
    local->read_input              = ReadInput;
322
    local->control_proc            = ControlProc;
323
    local->close_proc              = CloseProc;
324
    local->switch_mode             = SwitchMode;
325
    local->conversion_proc         = ConvertProc;
326
    local->reverse_conversion_proc = NULL;
327
    local->dev                     = NULL;
328
    local->private                 = priv;
329
    local->private_flags           = 0;
330
    local->flags                   = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
331
    local->conf_idev               = dev;
332
    local->motion_history_proc     = xf86GetMotionEvents;
333
    local->history_size            = 0;
334
    local->always_core_feedback    = 0;
335
336
    xf86Msg(X_INFO, "Synaptics touchpad driver version %s (%d)\n", VERSION, VERSION_ID);
337
338
    xf86CollectInputOptions(local, NULL, NULL);
339
340
    opts = local->options;
341
342
    xf86OptionListReport(opts);
343
344
    SetDeviceAndProtocol(local);
345
346
    /* open the touchpad device */
347
    local->fd = xf86OpenSerial(opts);
348
    if (local->fd == -1) {
349
	ErrorF("Synaptics driver unable to open device\n");
350
	goto SetupProc_fail;
351
    }
352
    xf86ErrorFVerb(6, "port opened successfully\n");
353
354
    /* initialize variables */
355
    priv->timer = NULL;
356
    priv->repeatButtons = 0;
357
    priv->nextRepeat = 0;
358
    priv->count_packet_finger = 0;
359
    priv->tap_state = TS_START;
360
    priv->tap_button = 0;
361
    priv->tap_button_state = TBS_BUTTON_UP;
362
    priv->touch_on.millis = 0;
363
364
    /* install shared memory or normal memory for parameters */
365
    priv->shm_config = xf86SetBoolOption(opts, "SHMConfig", FALSE);
366
367
    /* read the parameters */
368
    pars = &priv->synpara_default;
369
    pars->version = VERSION_ID;
370
    pars->left_edge = xf86SetIntOption(opts, "LeftEdge", 1900);
371
    pars->right_edge = xf86SetIntOption(opts, "RightEdge", 5400);
372
    pars->top_edge = xf86SetIntOption(opts, "TopEdge", 1900);
373
    pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", 4000);
374
    pars->finger_low = xf86SetIntOption(opts, "FingerLow", 25);
375
    pars->finger_high = xf86SetIntOption(opts, "FingerHigh", 30);
376
    pars->tap_time = xf86SetIntOption(opts, "MaxTapTime", 180);
377
    pars->tap_move = xf86SetIntOption(opts, "MaxTapMove", 220);
378
    pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180);
379
    pars->click_time = xf86SetIntOption(opts, "ClickTime", 100);
380
    pars->fast_taps = xf86SetIntOption(opts, "FastTaps", FALSE);
381
    pars->emulate_mid_button_time = xf86SetIntOption(opts,
382
							      "EmulateMidButtonTime", 75);
383
    pars->scroll_dist_vert = xf86SetIntOption(opts, "VertScrollDelta", 100);
384
    pars->scroll_dist_horiz = xf86SetIntOption(opts, "HorizScrollDelta", 100);
385
    pars->scroll_edge_vert = xf86SetBoolOption(opts, "VertEdgeScroll", TRUE);
386
    pars->scroll_edge_horiz = xf86SetBoolOption(opts, "HorizEdgeScroll", TRUE);
387
    pars->scroll_twofinger_vert = xf86SetBoolOption(opts, "VertTwoFingerScroll", FALSE);
388
    pars->scroll_twofinger_horiz = xf86SetBoolOption(opts, "HorizTwoFingerScroll", FALSE);
389
    pars->edge_motion_min_z = xf86SetIntOption(opts, "EdgeMotionMinZ", 30);
390
    pars->edge_motion_max_z = xf86SetIntOption(opts, "EdgeMotionMaxZ", 160);
391
    pars->edge_motion_min_speed = xf86SetIntOption(opts, "EdgeMotionMinSpeed", 1);
392
    pars->edge_motion_max_speed = xf86SetIntOption(opts, "EdgeMotionMaxSpeed", 400);
393
    pars->edge_motion_use_always = xf86SetBoolOption(opts, "EdgeMotionUseAlways", FALSE);
394
    repeater = xf86SetStrOption(opts, "Repeater", NULL);
395
    pars->updown_button_scrolling = xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
396
    pars->leftright_button_scrolling = xf86SetBoolOption(opts, "LeftRightScrolling", TRUE);
397
    pars->updown_button_repeat = xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE);
398
    pars->leftright_button_repeat = xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE);
399
    pars->scroll_button_repeat = xf86SetIntOption(opts,"ScrollButtonRepeat", 100);
400
    pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", 0);
401
    pars->guestmouse_off = xf86SetBoolOption(opts, "GuestMouseOff", FALSE);
402
    pars->locked_drags = xf86SetBoolOption(opts, "LockedDrags", FALSE);
403
    pars->tap_action[RT_TAP] = xf86SetIntOption(opts, "RTCornerButton", 2);
404
    pars->tap_action[RB_TAP] = xf86SetIntOption(opts, "RBCornerButton", 3);
405
    pars->tap_action[LT_TAP] = xf86SetIntOption(opts, "LTCornerButton", 0);
406
    pars->tap_action[LB_TAP] = xf86SetIntOption(opts, "LBCornerButton", 0);
407
    pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1",     1);
408
    pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2",     2);
409
    pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3",     3);
410
    pars->circular_scrolling = xf86SetBoolOption(opts, "CircularScrolling", FALSE);
411
    pars->circular_trigger   = xf86SetIntOption(opts, "CircScrollTrigger", 0);
412
    pars->circular_pad       = xf86SetBoolOption(opts, "CircularPad", FALSE);
413
    pars->palm_detect        = xf86SetBoolOption(opts, "PalmDetect", TRUE);
414
    pars->palm_min_width     = xf86SetIntOption(opts, "PalmMinWidth", 10);
415
    pars->palm_min_z         = xf86SetIntOption(opts, "PalmMinZ", 200);
416
    pars->single_tap_timeout = xf86SetIntOption(opts, "SingleTapTimeout", 180);
417
    pars->press_motion_min_z = xf86SetIntOption(opts, "PressureMotionMinZ", pars->edge_motion_min_z);
418
    pars->press_motion_max_z = xf86SetIntOption(opts, "PressureMotionMaxZ", pars->edge_motion_max_z);
419
420
    pars->min_speed = synSetFloatOption(opts, "MinSpeed", 0.09);
421
    pars->max_speed = synSetFloatOption(opts, "MaxSpeed", 0.18);
422
    pars->accl = synSetFloatOption(opts, "AccelFactor", 0.0015);
423
    pars->scroll_dist_circ = synSetFloatOption(opts, "CircScrollDelta", 0.1);
424
    pars->coasting_speed = synSetFloatOption(opts, "CoastingSpeed", 0.0);
425
    pars->press_motion_min_factor = synSetFloatOption(opts, "PressureMotionMinFactor", 1.0);
426
    pars->press_motion_max_factor = synSetFloatOption(opts, "PressureMotionMaxFactor", 1.0);
427
428
    /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
429
    if (pars->top_edge > pars->bottom_edge) {
430
	int tmp = pars->top_edge;
431
	pars->top_edge = pars->bottom_edge;
432
	pars->bottom_edge = tmp;
433
	xf86Msg(X_WARNING, "%s: TopEdge is bigger than BottomEdge. Fixing.\n",
434
		local->name);
435
    }
436
437
    priv->largest_valid_x = MIN(pars->right_edge, XMAX_NOMINAL);
438
439
    if (!alloc_param_data(local))
440
	goto SetupProc_fail;
441
442
    priv->comm.buffer = XisbNew(local->fd, 200);
443
    DBG(9, XisbTrace(priv->comm.buffer, 1));
444
445
    priv->fifofd = -1;
446
    if (repeater) {
447
	/* create repeater fifo */
448
	if ((mknod(repeater, 666, S_IFIFO) != 0) &&
449
	    (errno != xf86_EEXIST)) {
450
	    xf86Msg(X_ERROR, "%s can't create repeater fifo\n", local->name);
451
	} else {
452
	    /* open the repeater fifo */
453
	    optList = xf86NewOption("Device", repeater);
454
	    if ((priv->fifofd = xf86OpenSerial(optList)) == -1) {
455
		xf86Msg(X_ERROR, "%s repeater device open failed\n", local->name);
456
	    }
457
	}
458
	free(repeater);
459
    }
460
461
    if (!QueryHardware(local)) {
462
	xf86Msg(X_ERROR, "%s Unable to query/initialize Synaptics hardware.\n", local->name);
463
	goto SetupProc_fail;
464
    }
465
466
    local->history_size = xf86SetIntOption(opts, "HistorySize", 0);
467
468
    xf86ProcessCommonOptions(local, opts);
469
    local->flags |= XI86_CONFIGURED;
470
471
    if (local->fd != -1) {
472
	if (priv->comm.buffer) {
473
	    XisbFree(priv->comm.buffer);
474
	    priv->comm.buffer = NULL;
475
	}
476
	xf86CloseSerial(local->fd);
477
    }
478
    local->fd = -1;
479
    return local;
480
481
 SetupProc_fail:
482
    if (local->fd >= 0) {
483
	xf86CloseSerial(local->fd);
484
	local->fd = -1;
485
    }
486
487
    if (priv->comm.buffer)
488
	XisbFree(priv->comm.buffer);
489
    free_param_data(priv);
490
    /* Freeing priv makes the X server crash. Don't know why.
491
       xfree(priv);
492
    */
493
    return local;
494
}
495
496
/*
497
 *  Alter the control parameters for the mouse. Note that all special
498
 *  protocol values are handled by dix.
499
 */
500
static void
501
SynapticsCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
502
{
503
    DBG(3, ErrorF("SynapticsCtrl called.\n"));
504
    /*
505
      pInfo = device->public.devicePrivate;
506
      pMse = pInfo->private;
507
508
      pMse->num       = ctrl->num;
509
      pMse->den       = ctrl->den;
510
      pMse->threshold = ctrl->threshold;
511
    */
512
}
513
514
static Bool
515
DeviceControl(DeviceIntPtr dev, int mode)
516
{
517
    Bool RetValue;
518
519
    switch (mode) {
520
    case DEVICE_INIT:
521
	RetValue = DeviceInit(dev);
522
	break;
523
    case DEVICE_ON:
524
	RetValue = DeviceOn(dev);
525
	break;
526
    case DEVICE_OFF:
527
	RetValue = DeviceOff(dev);
528
	break;
529
    case DEVICE_CLOSE:
530
	RetValue = DeviceClose(dev);
531
	break;
532
    default:
533
	RetValue = BadValue;
534
    }
535
536
    return RetValue;
537
}
538
539
static Bool
540
DeviceOn(DeviceIntPtr dev)
541
{
542
    LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
543
    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
544
545
    DBG(3, ErrorF("Synaptics DeviceOn called\n"));
546
547
    SetDeviceAndProtocol(local);
548
    local->fd = xf86OpenSerial(local->options);
549
    if (local->fd == -1) {
550
	xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name);
551
	return !Success;
552
    }
553
554
    priv->proto_ops->DeviceOnHook(local);
555
556
    priv->comm.buffer = XisbNew(local->fd, 64);
557
    if (!priv->comm.buffer) {
558
	xf86CloseSerial(local->fd);
559
	local->fd = -1;
560
	return !Success;
561
    }
562
563
    xf86FlushInput(local->fd);
564
565
    /* reinit the pad */
566
    QueryHardware(local);
567
    xf86AddEnabledDevice(local);
568
    dev->public.on = TRUE;
569
570
    return Success;
571
}
572
573
static Bool
574
DeviceOff(DeviceIntPtr dev)
575
{
576
    LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
577
    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
578
579
    DBG(3, ErrorF("Synaptics DeviceOff called\n"));
580
581
    if (local->fd != -1) {
582
	TimerFree(priv->timer);
583
	priv->timer = NULL;
584
	xf86RemoveEnabledDevice(local);
585
	priv->proto_ops->DeviceOffHook(local);
586
	if (priv->comm.buffer) {
587
	    XisbFree(priv->comm.buffer);
588
	    priv->comm.buffer = NULL;
589
	}
590
	xf86CloseSerial(local->fd);
591
    }
592
    dev->public.on = FALSE;
593
    return Success;
594
}
595
596
static Bool
597
DeviceClose(DeviceIntPtr dev)
598
{
599
    Bool RetValue;
600
    LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
601
    SynapticsPrivate *priv = (SynapticsPrivate *) local->private;
602
603
    RetValue = DeviceOff(dev);
604
    free_param_data(priv);
605
    return RetValue;
606
}
607
608
static Bool
609
DeviceInit(DeviceIntPtr dev)
610
{
611
    LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
612
    unsigned char map[SYN_MAX_BUTTONS + 1];
613
    int i;
614
615
    DBG(3, ErrorF("Synaptics DeviceInit called\n"));
616
617
    for (i = 0; i <= SYN_MAX_BUTTONS; i++)
618
	map[i] = i;
619
620
    dev->public.on = FALSE;
621
622
    InitPointerDeviceStruct((DevicePtr)dev, map,
623
			    SYN_MAX_BUTTONS,
624
			    miPointerGetMotionEvents, SynapticsCtrl,
625
			    miPointerGetMotionBufferSize());
626
627
    /* X valuator */
628
    xf86InitValuatorAxisStruct(dev, 0, 0, -1, 1, 0, 1);
629
    xf86InitValuatorDefaults(dev, 0);
630
    /* Y valuator */
631
    xf86InitValuatorAxisStruct(dev, 1, 0, -1, 1, 0, 1);
632
    xf86InitValuatorDefaults(dev, 1);
633
634
    xf86MotionHistoryAllocate(local);
635
636
    if (!alloc_param_data(local))
637
	return !Success;
638
639
    return Success;
640
}
641
642
static int
643
move_distance(int dx, int dy)
644
{
645
    return sqrt((dx * dx) + (dy * dy));
646
}
647
648
/*
649
 * Convert from absolute X/Y coordinates to a coordinate system where
650
 * -1 corresponds to the left/upper edge and +1 corresponds to the
651
 * right/lower edge.
652
 */
653
static void
654
relative_coords(SynapticsPrivate *priv, int x, int y,
655
		double *relX, double *relY)
656
{
657
    int minX = priv->synpara->left_edge;
658
    int maxX = priv->synpara->right_edge;
659
    int minY = priv->synpara->top_edge;
660
    int maxY = priv->synpara->bottom_edge;
661
    double xCenter = (minX + maxX) / 2.0;
662
    double yCenter = (minY + maxY) / 2.0;
663
664
    if ((maxX - xCenter > 0) && (maxY - yCenter > 0)) {
665
	*relX = (x - xCenter) / (maxX - xCenter);
666
	*relY = (y - yCenter) / (maxY - yCenter);
667
    } else {
668
	*relX = 0;
669
	*relY = 0;
670
    }
671
}
672
673
/* return angle of point relative to center */
674
static double
675
angle(SynapticsPrivate *priv, int x, int y)
676
{
677
    double xCenter = (priv->synpara->left_edge + priv->synpara->right_edge) / 2.0;
678
    double yCenter = (priv->synpara->top_edge + priv->synpara->bottom_edge) / 2.0;
679
680
    return atan2(-(y - yCenter), x - xCenter);
681
}
682
683
/* return angle difference */
684
static double
685
diffa(double a1, double a2)
686
{
687
    double da = fmod(a2 - a1, 2 * M_PI);
688
    if (da < 0)
689
	da += 2 * M_PI;
690
    if (da > M_PI)
691
	da -= 2 * M_PI;
692
    return da;
693
}
694
695
static edge_type
696
circular_edge_detection(SynapticsPrivate *priv, int x, int y)
697
{
698
    edge_type edge = 0;
699
    double relX, relY, relR;
700
701
    relative_coords(priv, x, y, &relX, &relY);
702
    relR = relX * relX + relY * relY;
703
704
    if (relR > 1) {
705
	/* we are outside the ellipse enclosed by the edge parameters */
706
	if (relX > M_SQRT1_2)
707
	    edge |= RIGHT_EDGE;
708
	else if (relX < -M_SQRT1_2)
709
	    edge |= LEFT_EDGE;
710
711
	if (relY < -M_SQRT1_2)
712
	    edge |= TOP_EDGE;
713
	else if (relY > M_SQRT1_2)
714
	    edge |= BOTTOM_EDGE;
715
    }
716
717
    return edge;
718
}
719
720
static edge_type
721
edge_detection(SynapticsPrivate *priv, int x, int y)
722
{
723
    edge_type edge = 0;
724
725
    if (priv->synpara->circular_pad)
726
	return circular_edge_detection(priv, x, y);
727
728
    if (x > priv->synpara->right_edge)
729
	edge |= RIGHT_EDGE;
730
    else if (x < priv->synpara->left_edge)
731
	edge |= LEFT_EDGE;
732
733
    if (y < priv->synpara->top_edge)
734
	edge |= TOP_EDGE;
735
    else if (y > priv->synpara->bottom_edge)
736
	edge |= BOTTOM_EDGE;
737
738
    return edge;
739
}
740
741
static CARD32
742
timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
743
{
744
    LocalDevicePtr local = (LocalDevicePtr) (arg);
745
    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
746
    struct SynapticsHwState hw;
747
    int delay;
748
    int sigstate;
749
    CARD32 wakeUpTime;
750
751
    sigstate = xf86BlockSIGIO();
752
753
    hw = priv->hwState;
754
    hw.guest_dx = hw.guest_dy = 0;
755
    hw.millis = now;
756
    delay = HandleState(local, &hw);
757
758
    /*
759
     * Workaround for wraparound bug in the TimerSet function. This bug is already
760
     * fixed in CVS, but this driver needs to work with XFree86 versions 4.2.x and
761
     * 4.3.x too.
762
     */
763
    wakeUpTime = now + delay;
764
    if (wakeUpTime <= now)
765
	wakeUpTime = 0xffffffffL;
766
767
    priv->timer = TimerSet(priv->timer, TimerAbsolute, wakeUpTime, timerFunc, local);
768
769
    xf86UnblockSIGIO(sigstate);
770
771
    return 0;
772
}
773
774
static int
775
clamp(int val, int min, int max)
776
{
777
    if (val < min)
778
	return min;
779
    else if (val < max)
780
	return val;
781
    else
782
	return max;
783
}
784
785
static Bool
786
SynapticsGetHwState(LocalDevicePtr local, SynapticsPrivate *priv,
787
		    struct SynapticsHwState *hw)
788
{
789
    if (priv->fifofd >= 0) {
790
	/* when there is no synaptics touchpad pipe the data to the repeater fifo */
791
	int count = 0;
792
	int c;
793
	while ((c = XisbRead(priv->comm.buffer)) >= 0) {
794
	    unsigned char u = (unsigned char)c;
795
	    write(priv->fifofd, &u, 1);
796
	    if (++count >= 3)
797
		break;
798
	}
799
	return FALSE;
800
    }
801
    return priv->proto_ops->ReadHwState(local, &priv->synhw, priv->proto_ops,
802
					&priv->comm, hw);
803
}
804
805
/*
806
 *  called for each full received packet from the touchpad
807
 */
808
static void
809
ReadInput(LocalDevicePtr local)
810
{
811
    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
812
    struct SynapticsHwState hw;
813
    int delay = 0;
814
    Bool newDelay = FALSE;
815
816
    while (SynapticsGetHwState(local, priv, &hw)) {
817
	hw.millis = GetTimeInMillis();
818
	priv->hwState = hw;
819
	delay = HandleState(local, &hw);
820
	newDelay = TRUE;
821
    }
822
823
    if (newDelay)
824
	priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, local);
825
}
826
827
static int
828
HandleMidButtonEmulation(SynapticsPrivate *priv, struct SynapticsHwState *hw, int *delay)
829
{
830
    SynapticsSHM *para = priv->synpara;
831
    Bool done = FALSE;
832
    int timeleft;
833
    int mid = 0;
834
835
    while (!done) {
836
	switch (priv->mid_emu_state) {
837
	case MBE_OFF:
838
	    priv->button_delay_millis = hw->millis;
839
	    if (hw->left) {
840
		priv->mid_emu_state = MBE_LEFT;
841
	    } else if (hw->right) {
842
		priv->mid_emu_state = MBE_RIGHT;
843
	    } else {
844
		done = TRUE;
845
	    }
846
	    break;
847
	case MBE_LEFT:
848
	    timeleft = TIME_DIFF(priv->button_delay_millis + para->emulate_mid_button_time,
849
				 hw->millis);
850
	    if (timeleft > 0)
851
		*delay = MIN(*delay, timeleft);
852
	    if (!hw->left || (timeleft <= 0)) {
853
		hw->left = TRUE;
854
		priv->mid_emu_state = MBE_TIMEOUT;
855
		done = TRUE;
856
	    } else if (hw->right) {
857
		priv->mid_emu_state = MBE_MID;
858
	    } else {
859
		hw->left = FALSE;
860
		done = TRUE;
861
	    }
862
	    break;
863
	case MBE_RIGHT:
864
	    timeleft = TIME_DIFF(priv->button_delay_millis + para->emulate_mid_button_time,
865
				 hw->millis);
866
	    if (timeleft > 0)
867
		*delay = MIN(*delay, timeleft);
868
	    if (!hw->right || (timeleft <= 0)) {
869
		hw->right = TRUE;
870
		priv->mid_emu_state = MBE_TIMEOUT;
871
		done = TRUE;
872
	    } else if (hw->left) {
873
		priv->mid_emu_state = MBE_MID;
874
	    } else {
875
		hw->right = FALSE;
876
		done = TRUE;
877
	    }
878
	    break;
879
	case MBE_MID:
880
	    if (!hw->left && !hw->right) {
881
		priv->mid_emu_state = MBE_OFF;
882
	    } else {
883
		mid = TRUE;
884
		hw->left = hw->right = FALSE;
885
		done = TRUE;
886
	    }
887
	    break;
888
	case MBE_TIMEOUT:
889
	    if (!hw->left && !hw->right) {
890
		priv->mid_emu_state = MBE_OFF;
891
	    } else {
892
		done = TRUE;
893
	    }
894
	}
895
    }
896
    return mid;
897
}
898
899
static int
900
SynapticsDetectFinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
901
{
902
    SynapticsSHM *para = priv->synpara;
903
    int finger;
904
905
    /* finger detection thru pressure and threshold */
906
    finger = (((hw->z > para->finger_high) && !priv->finger_flag) ||
907
	      ((hw->z > para->finger_low)  &&  priv->finger_flag));
908
909
    if (!para->palm_detect)
910
	return finger;
911
912
    /* palm detection */
913
    if (finger) {
914
	if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width))
915
	    priv->palm = TRUE;
916
    } else {
917
	priv->palm = FALSE;
918
    }
919
    if (hw->x == 0)
920
	priv->avg_width = 0;
921
    else
922
	priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
923
    if (finger && !priv->finger_flag) {
924
	int safe_width = MAX(hw->fingerWidth, priv->avg_width);
925
	if (hw->numFingers > 1)
926
	    finger = TRUE;			/* more than one finger -> not a palm */
927
	else if ((safe_width < 6) && (priv->prev_z < para->finger_high))
928
	    finger = TRUE;			/* thin finger, distinct touch -> not a palm */
929
	else if ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))
930
	    finger = TRUE;			/* thin finger, distinct touch -> not a palm */
931
	else if (hw->z > priv->prev_z + 1)	/* z not stable, may be a palm */
932
	    finger = FALSE;
933
	else if (hw->z < priv->prev_z - 5)	/* z not stable, may be a palm */
934
	    finger = FALSE;
935
	else if (hw->z > para->palm_min_z)	/* z too large -> probably palm */
936
	    finger = FALSE;
937
	else if (hw->fingerWidth > para->palm_min_width) /* finger width too large -> probably palm */
938
	    finger = FALSE;
939
    }
940
    priv->prev_z = hw->z;
941
942
    if (priv->palm)
943
	finger = FALSE;
944
945
    return finger;
946
}
947
948
static void
949
SelectTapButton(SynapticsPrivate *priv, edge_type edge)
950
{
951
    TapEvent tap;
952
953
    if (priv->synpara->touchpad_off == 2) {
954
	priv->tap_button = 0;
955
	return;
956
    }
957
958
    switch (priv->tap_max_fingers) {
959
    case 1:
960
    default:
961
	switch (edge) {
962
	case RIGHT_TOP_EDGE:
963
	    DBG(7, ErrorF("right top edge\n"));
964
	    tap = RT_TAP;
965
	    break;
966
	case RIGHT_BOTTOM_EDGE:
967
	    DBG(7, ErrorF("right bottom edge\n"));
968
	    tap = RB_TAP;
969
	    break;
970
	case LEFT_TOP_EDGE:
971
	    DBG(7, ErrorF("left top edge\n"));
972
	    tap = LT_TAP;
973
	    break;
974
	case LEFT_BOTTOM_EDGE:
975
	    DBG(7, ErrorF("left bottom edge\n"));
976
	    tap = LB_TAP;
977
	    break;
978
	default:
979
	    DBG(7, ErrorF("no edge\n"));
980
	    tap = F1_TAP;
981
	    break;
982
	}
983
	break;
984
    case 2:
985
	DBG(7, ErrorF("two finger tap\n"));
986
	tap = F2_TAP;
987
	break;
988
    case 3:
989
	DBG(7, ErrorF("three finger tap\n"));
990
	tap = F3_TAP;
991
	break;
992
    }
993
994
    priv->tap_button = priv->synpara->tap_action[tap];
995
    priv->tap_button = clamp(priv->tap_button, 0, SYN_MAX_BUTTONS);
996
}
997
998
static void
999
SetTapState(SynapticsPrivate *priv, enum TapState tap_state, int millis)
1000
{
1001
    SynapticsSHM *para = priv->synpara;
1002
    DBG(7, ErrorF("SetTapState - %d -> %d (millis:%d)\n", priv->tap_state, tap_state, millis));
1003
    switch (tap_state) {
1004
    case TS_START:
1005
	priv->tap_button_state = TBS_BUTTON_UP;
1006
	priv->tap_max_fingers = 0;
1007
	break;
1008
    case TS_1:
1009
	priv->tap_button_state = TBS_BUTTON_UP;
1010
	break;
1011
    case TS_2A:
1012
	if (para->fast_taps)
1013
	    priv->tap_button_state = TBS_BUTTON_DOWN;
1014
	else
1015
	    priv->tap_button_state = TBS_BUTTON_UP;
1016
	break;
1017
    case TS_2B:
1018
	priv->tap_button_state = TBS_BUTTON_UP;
1019
	break;
1020
    case TS_3:
1021
	priv->tap_button_state = TBS_BUTTON_DOWN;
1022
	break;
1023
    case TS_SINGLETAP:
1024
	if (para->fast_taps)
1025
	    priv->tap_button_state = TBS_BUTTON_UP;
1026
	else
1027
	    priv->tap_button_state = TBS_BUTTON_DOWN;
1028
	priv->touch_on.millis = millis;
1029
	break;
1030
    default:
1031
	break;
1032
    }
1033
    priv->tap_state = tap_state;
1034
}
1035
1036
static int
1037
GetTimeOut(SynapticsPrivate *priv)
1038
{
1039
    SynapticsSHM *para = priv->synpara;
1040
1041
    switch (priv->tap_state) {
1042
    case TS_1:
1043
    case TS_3:
1044
    case TS_5:
1045
	return para->tap_time;
1046
    case TS_SINGLETAP:
1047
	return para->click_time;
1048
    case TS_2A:
1049
	return para->single_tap_timeout;
1050
    case TS_2B:
1051
	return para->tap_time_2;
1052
    default:
1053
	return -1;			    /* No timeout */
1054
    }
1055
}
1056
1057
static int
1058
HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw,
1059
		    edge_type edge, Bool finger)
1060
{
1061
    SynapticsSHM *para = priv->synpara;
1062
    Bool touch, release, is_timeout, move;
1063
    int timeleft, timeout;
1064
    int delay = 1000000000;
1065
1066
    if (priv->palm)
1067
	return delay;
1068
1069
    touch = finger && !priv->finger_flag;
1070
    release = !finger && priv->finger_flag;
1071
    move = FALSE;
1072
    if (touch) {
1073
	priv->touch_on.x = hw->x;
1074
	priv->touch_on.y = hw->y;
1075
	priv->touch_on.millis = hw->millis;
1076
    } else if (release) {
1077
	priv->touch_on.millis = hw->millis;
1078
	move = ((priv->tap_max_fingers <= 1) &&
1079
		((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
1080
		 (abs(hw->y - priv->touch_on.y) >= para->tap_move)));
1081
    }
1082
    if (hw->z > para->finger_high)
1083
	if (priv->tap_max_fingers < hw->numFingers)
1084
	    priv->tap_max_fingers = hw->numFingers;
1085
    timeout = GetTimeOut(priv);
1086
    timeleft = TIME_DIFF(priv->touch_on.millis + timeout, hw->millis);
1087
    is_timeout = timeleft <= 0;
1088
1089
 restart:
1090
    switch (priv->tap_state) {
1091
    case TS_START:
1092
	if (touch)
1093
	    SetTapState(priv, TS_1, hw->millis);
1094
	break;
1095
    case TS_1:
1096
	if (is_timeout || move) {
1097
	    SetTapState(priv, TS_MOVE, hw->millis);
1098
	    goto restart;
1099
	} else if (release) {
1100
	    SelectTapButton(priv, edge);
1101
	    SetTapState(priv, TS_2A, hw->millis);
1102
	}
1103
	break;
1104
    case TS_MOVE:
1105
	if (release)
1106
	    SetTapState(priv, TS_START, hw->millis);
1107
	break;
1108
    case TS_2A:
1109
	if (touch)
1110
	    SetTapState(priv, TS_3, hw->millis);
1111
	else if (is_timeout)
1112
	    SetTapState(priv, TS_SINGLETAP, hw->millis);
1113
	break;
1114
    case TS_2B:
1115
	if (touch) {
1116
	    SetTapState(priv, TS_3, hw->millis);
1117
	} else if (is_timeout) {
1118
	    SetTapState(priv, TS_START, hw->millis);
1119
	    priv->tap_button_state = TBS_BUTTON_DOWN_UP;
1120
	}
1121
	break;
1122
    case TS_SINGLETAP:
1123
	if (touch)
1124
	    SetTapState(priv, TS_1, hw->millis);
1125
	else if (is_timeout)
1126
	    SetTapState(priv, TS_START, hw->millis);
1127
	break;
1128
    case TS_3:
1129
	if (is_timeout || move) {
1130
	    SetTapState(priv, TS_DRAG, hw->millis);
1131
	    goto restart;
1132
	} else if (release)
1133
	    SetTapState(priv, TS_2B, hw->millis);
1134
	break;
1135
    case TS_DRAG:
1136
	if (release) {
1137
	    if (para->locked_drags)
1138
		SetTapState(priv, TS_4, hw->millis);
1139
	    else
1140
		SetTapState(priv, TS_START, hw->millis);
1141
	}
1142
	break;
1143
    case TS_4:
1144
	if (touch)
1145
	    SetTapState(priv, TS_5, hw->millis);
1146
	break;
1147
    case TS_5:
1148
	if (is_timeout || move) {
1149
	    SetTapState(priv, TS_DRAG, hw->millis);
1150
	    goto restart;
1151
	} else if (release)
1152
	    SetTapState(priv, TS_START, hw->millis);
1153
	break;
1154
    }
1155
1156
    timeout = GetTimeOut(priv);
1157
    if (timeout >= 0) {
1158
	timeleft = TIME_DIFF(priv->touch_on.millis + timeout, hw->millis);
1159
	delay = clamp(timeleft, 1, delay);
1160
    }
1161
    return delay;
1162
}
1163
1164
#define HIST(a) (priv->move_hist[((priv->hist_index - (a) + SYNAPTICS_MOVE_HISTORY) % SYNAPTICS_MOVE_HISTORY)])
1165
1166
static void
1167
store_history(SynapticsPrivate *priv, int x, int y, unsigned int millis)
1168
{
1169
    int idx = (priv->hist_index + 1) % SYNAPTICS_MOVE_HISTORY;
1170
    priv->move_hist[idx].x = x;
1171
    priv->move_hist[idx].y = y;
1172
    priv->move_hist[idx].millis = millis;
1173
    priv->hist_index = idx;
1174
}
1175
1176
/*
1177
 * Estimate the slope for the data sequence [x3, x2, x1, x0] by using
1178
 * linear regression to fit a line to the data and use the slope of the
1179
 * line.
1180
 */
1181
static double
1182
estimate_delta(double x0, double x1, double x2, double x3)
1183
{
1184
    return x0 * 0.3 + x1 * 0.1 - x2 * 0.1 - x3 * 0.3;
1185
}
1186
1187
static int
1188
ComputeDeltas(SynapticsPrivate *priv, struct SynapticsHwState *hw,
1189
	      edge_type edge, int *dxP, int *dyP)
1190
{
1191
    SynapticsSHM *para = priv->synpara;
1192
    Bool moving_state;
1193
    int dist;
1194
    double dx, dy;
1195
    double speed, integral;
1196
    int delay = 1000000000;
1197
1198
    dx = dy = 0;
1199
1200
    moving_state = FALSE;
1201
    switch (priv->tap_state) {
1202
    case TS_MOVE:
1203
    case TS_DRAG:
1204
	moving_state = TRUE;
1205
	break;
1206
    case TS_1:
1207
    case TS_3:
1208
    case TS_5:
1209
	if (hw->numFingers == 1)
1210
	    moving_state = TRUE;
1211
	break;
1212
    default:
1213
	break;
1214
    }
1215
    if (moving_state && !priv->palm &&
1216
	!priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on &&
1217
	!priv->vert_scroll_twofinger_on && !priv->horiz_scroll_twofinger_on &&
1218
	!priv->circ_scroll_on) {
1219
	delay = MIN(delay, 13);
1220
	if (priv->count_packet_finger > 3) { /* min. 3 packets */
1221
	    double tmpf;
1222
	    int x_edge_speed = 0;
1223
	    int y_edge_speed = 0;
1224
	    double dtime = (hw->millis - HIST(0).millis) / 1000.0;
1225
	    dx = estimate_delta(hw->x, HIST(0).x, HIST(1).x, HIST(2).x);
1226
	    dy = estimate_delta(hw->y, HIST(0).y, HIST(1).y, HIST(2).y);
1227
1228
	    if ((priv->tap_state == TS_DRAG) || para->edge_motion_use_always) {
1229
		int minZ = para->edge_motion_min_z;
1230
		int maxZ = para->edge_motion_max_z;
1231
		int minSpd = para->edge_motion_min_speed;
1232
		int maxSpd = para->edge_motion_max_speed;
1233
		int edge_speed;
1234
1235
		if (hw->z <= minZ) {
1236
		    edge_speed = minSpd;
1237
		} else if (hw->z >= maxZ) {
1238
		    edge_speed = maxSpd;
1239
		} else {
1240
		    edge_speed = minSpd + (hw->z - minZ) * (maxSpd - minSpd) / (maxZ - minZ);
1241
		}
1242
		if (!priv->synpara->circular_pad) {
1243
		    /* on rectangular pad */
1244
		    if (edge & RIGHT_EDGE) {
1245
			x_edge_speed = edge_speed;
1246
		    } else if (edge & LEFT_EDGE) {
1247
			x_edge_speed = -edge_speed;
1248
		    }
1249
		    if (edge & TOP_EDGE) {
1250
			y_edge_speed = -edge_speed;
1251
		    } else if (edge & BOTTOM_EDGE) {
1252
			y_edge_speed = edge_speed;
1253
		    }
1254
		} else if (edge) {
1255
		    /* at edge of circular pad */
1256
		    double relX, relY;
1257
1258
		    relative_coords(priv, hw->x, hw->y, &relX, &relY);
1259
		    x_edge_speed = (int)(edge_speed * relX);
1260
		    y_edge_speed = (int)(edge_speed * relY);
1261
		}
1262
	    }
1263
1264
	    /* speed depending on distance/packet */
1265
	    dist = move_distance(dx, dy);
1266
	    speed = dist * para->accl;
1267
	    if (speed > para->max_speed) {  /* set max speed factor */
1268
		speed = para->max_speed;
1269
	    } else if (speed < para->min_speed) { /* set min speed factor */
1270
		speed = para->min_speed;
1271
	    }
1272
1273
	    /* modify speed according to pressure */
1274
	    {
1275
		int minZ = para->press_motion_min_z;
1276
		int maxZ = para->press_motion_max_z;
1277
		double minFctr = para->press_motion_min_factor;
1278
		double maxFctr = para->press_motion_max_factor;
1279
1280
		if (hw->z <= minZ) {
1281
		    speed *= minFctr;
1282
		} else if (hw->z >= maxZ) {
1283
		    speed *= maxFctr;
1284
		} else {
1285
		    speed *= minFctr + (hw->z - minZ) * (maxFctr - minFctr) / (maxZ - minZ);
1286
		}
1287
	    }
1288
1289
	    /* save the fraction, report the integer part */
1290
	    tmpf = dx * speed + x_edge_speed * dtime + priv->frac_x;
1291
	    priv->frac_x = modf(tmpf, &integral);
1292
	    dx = integral;
1293
	    tmpf = dy * speed + y_edge_speed * dtime + priv->frac_y;
1294
	    priv->frac_y = modf(tmpf, &integral);
1295
	    dy = integral;
1296
	}
1297
1298
	priv->count_packet_finger++;
1299
    } else {				    /* reset packet counter */
1300
	priv->count_packet_finger = 0;
1301
    }
1302
1303
    /* Add guest device movements */
1304
    if (!para->guestmouse_off) {
1305
	dx += hw->guest_dx;
1306
	dy += hw->guest_dy;
1307
    }
1308
1309
    *dxP = dx;
1310
    *dyP = dy;
1311
1312
    /* generate a history of the absolute positions */
1313
    store_history(priv, hw->x, hw->y, hw->millis);
1314
1315
    return delay;
1316
}
1317
1318
struct ScrollData {
1319
    int left, right, up, down;
1320
};
1321
1322
static void
1323
start_coasting(SynapticsPrivate *priv, struct SynapticsHwState *hw, edge_type edge,
1324
	       Bool vertical)
1325
{
1326
    SynapticsSHM *para = priv->synpara;
1327
1328
    priv->autoscroll_y = 0.0;
1329
    priv->autoscroll_x = 0.0;
1330
1331
    if ((priv->scroll_packet_count > 3) && (para->coasting_speed > 0.0)) {
1332
	double pkt_time = (HIST(0).millis - HIST(3).millis) / 1000.0;
1333
	if (vertical) {
1334
	    double dy = estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
1335
	    int sdelta = para->scroll_dist_vert;
1336
	    if ((edge & RIGHT_EDGE) && pkt_time > 0 && sdelta > 0) {
1337
		double scrolls_per_sec = dy / pkt_time / sdelta;
1338
		if (fabs(scrolls_per_sec) >= para->coasting_speed) {
1339
		    priv->autoscroll_yspd = scrolls_per_sec;
1340
		    priv->autoscroll_y = (hw->y - priv->scroll_y) / (double)sdelta;
1341
		}
1342
	    }
1343
	} else {
1344
	    double dx = estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
1345
	    int sdelta = para->scroll_dist_horiz;
1346
	    if ((edge & BOTTOM_EDGE) && pkt_time > 0 && sdelta > 0) {
1347
		double scrolls_per_sec = dx / pkt_time / sdelta;
1348
		if (fabs(scrolls_per_sec) >= para->coasting_speed) {
1349
		    priv->autoscroll_xspd = scrolls_per_sec;
1350
		    priv->autoscroll_x = (hw->x - priv->scroll_x) / (double)sdelta;
1351
		}
1352
	    }
1353
	}
1354
    }
1355
    priv->scroll_packet_count = 0;
1356
}
1357
1358
static int
1359
HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
1360
		edge_type edge, Bool finger, struct ScrollData *sd)
1361
{
1362
    SynapticsSHM *para = priv->synpara;
1363
    int delay = 1000000000;
1364
1365
    sd->left = sd->right = sd->up = sd->down = 0;
1366
1367
    if (priv->synpara->touchpad_off == 2) {
1368
	priv->autoscroll_xspd = 0;
1369
	priv->autoscroll_yspd = 0;
1370
	priv->circ_scroll_on = FALSE;
1371
	priv->vert_scroll_edge_on = FALSE;
1372
	priv->horiz_scroll_edge_on = FALSE;
1373
	priv->vert_scroll_twofinger_on = FALSE;
1374
	priv->horiz_scroll_twofinger_on = FALSE;
1375
	return delay;
1376
    }
1377
1378
    /* scroll detection */
1379
    if (finger && !priv->finger_flag) {
1380
	priv->autoscroll_xspd = 0;
1381
	priv->autoscroll_yspd = 0;
1382
	priv->scroll_packet_count = 0;
1383
	if (para->circular_scrolling) {
1384
	    if ((para->circular_trigger == 0 && edge) ||
1385
		(para->circular_trigger == 1 && edge & TOP_EDGE) ||
1386
		(para->circular_trigger == 2 && edge & TOP_EDGE && edge & RIGHT_EDGE) ||
1387
		(para->circular_trigger == 3 && edge & RIGHT_EDGE) ||
1388
		(para->circular_trigger == 4 && edge & RIGHT_EDGE && edge & BOTTOM_EDGE) ||
1389
		(para->circular_trigger == 5 && edge & BOTTOM_EDGE) ||
1390
		(para->circular_trigger == 6 && edge & BOTTOM_EDGE && edge & LEFT_EDGE) ||
1391
		(para->circular_trigger == 7 && edge & LEFT_EDGE) ||
1392
		(para->circular_trigger == 8 && edge & LEFT_EDGE && edge & TOP_EDGE)) {
1393
		priv->circ_scroll_on = TRUE;
1394
		priv->circ_scroll_vert = TRUE;
1395
		priv->scroll_a = angle(priv, hw->x, hw->y);
1396
		DBG(7, ErrorF("circular scroll detected on edge\n"));
1397
	    }
1398
	}
1399
	if (!priv->circ_scroll_on) {
1400
	    if (hw->numFingers == 2) {
1401
		if ((para->scroll_twofinger_vert) && (para->scroll_dist_vert != 0)) {
1402
		    priv->vert_scroll_twofinger_on = TRUE;
1403
		    priv->scroll_y = hw->y;
1404
		    DBG(7, ErrorF("vert two-finger scroll detected\n"));
1405
		}
1406
		if ((para->scroll_twofinger_horiz) && (para->scroll_dist_horiz != 0)) {
1407
		    priv->horiz_scroll_twofinger_on = TRUE;
1408
		    priv->scroll_x = hw->x;
1409
		    DBG(7, ErrorF("horiz two-finger scroll detected\n"));
1410
		}
1411
	    }
1412
	    if (!priv->vert_scroll_twofinger_on && !priv->horiz_scroll_twofinger_on) {
1413
		if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
1414
		    (edge & RIGHT_EDGE)) {
1415
		    priv->vert_scroll_edge_on = TRUE;
1416
		    priv->scroll_y = hw->y;
1417
		    DBG(7, ErrorF("vert edge scroll detected on right edge\n"));
1418
		}
1419
		if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0) &&
1420
		    (edge & BOTTOM_EDGE)) {
1421
		    priv->horiz_scroll_edge_on = TRUE;
1422
		    priv->scroll_x = hw->x;
1423
		    DBG(7, ErrorF("horiz edge scroll detected on bottom edge\n"));
1424
		}
1425
	    }
1426
	}
1427
    }
1428
    {
1429
	Bool oldv = priv->vert_scroll_edge_on || (priv->circ_scroll_on && priv->circ_scroll_vert);
1430
	Bool oldh = priv->horiz_scroll_edge_on || (priv->circ_scroll_on && !priv->circ_scroll_vert);
1431
	if (priv->circ_scroll_on && !finger) {
1432
	    /* circular scroll locks in until finger is raised */
1433
	    DBG(7, ErrorF("cicular scroll off\n"));
1434
	    priv->circ_scroll_on = FALSE;
1435
	}
1436
1437
	if (hw->numFingers < 2) {
1438
	    if (priv->vert_scroll_twofinger_on) {
1439
		DBG(7, ErrorF("vert two-finger scroll off\n"));
1440
		priv->vert_scroll_twofinger_on = FALSE;
1441
	    }
1442
	    if (priv->horiz_scroll_twofinger_on) {
1443
		DBG(7, ErrorF("horiz two-finger scroll off\n"));
1444
		priv->horiz_scroll_twofinger_on = FALSE;
1445
	    }
1446
	}
1447
1448
	if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) {
1449
	    DBG(7, ErrorF("vert edge scroll off\n"));
1450
	    priv->vert_scroll_edge_on = FALSE;
1451
	}
1452
	if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) {
1453
	    DBG(7, ErrorF("horiz edge scroll off\n"));
1454
	    priv->horiz_scroll_edge_on = FALSE;
1455
	}
1456
	if ((oldv || oldh) &&
1457
	    !(priv->circ_scroll_on || priv->vert_scroll_edge_on ||
1458
	      priv->horiz_scroll_edge_on)) {
1459
	    start_coasting(priv, hw, edge, oldv);
1460
	}
1461
    }
1462
1463
    /* if hitting a corner (top right or bottom right) while vertical scrolling
1464
       is active, switch over to circular scrolling smoothly */
1465
    if (priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on &&
1466
	para->circular_scrolling) {
1467
	if ((edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) {
1468
	    priv->vert_scroll_edge_on = FALSE;
1469
	    priv->circ_scroll_on = TRUE;
1470
	    priv->circ_scroll_vert = TRUE;
1471
	    priv->scroll_a = angle(priv, hw->x, hw->y);
1472
	    DBG(7, ErrorF("switching to circular scrolling\n"));
1473
	}
1474
    }
1475
    /* Same treatment for horizontal scrolling */
1476
    if (priv->horiz_scroll_edge_on && !priv->vert_scroll_edge_on &&
1477
	para->circular_scrolling) {
1478
	if ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) {
1479
	    priv->horiz_scroll_edge_on = FALSE;
1480
	    priv->circ_scroll_on = TRUE;
1481
	    priv->circ_scroll_vert = FALSE;
1482
	    priv->scroll_a = angle(priv, hw->x, hw->y);
1483
	    DBG(7, ErrorF("switching to circular scrolling\n"));
1484
	}
1485
    }
1486
1487
    if (priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
1488
	priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
1489
	priv->circ_scroll_on) {
1490
	priv->scroll_packet_count++;
1491
    }
1492
1493
    if (priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on) {
1494
	/* + = down, - = up */
1495
	int delta = para->scroll_dist_vert;
1496
	if (delta > 0) {
1497
	    while (hw->y - priv->scroll_y > delta) {
1498
		sd->down++;
1499
		priv->scroll_y += delta;
1500
	    }
1501
	    while (hw->y - priv->scroll_y < -delta) {
1502
		sd->up++;
1503
		priv->scroll_y -= delta;
1504
	    }
1505
	}
1506
    }
1507
    if (priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on) {
1508
	/* + = right, - = left */
1509
	int delta = para->scroll_dist_horiz;
1510
	if (delta > 0) {
1511
	    while (hw->x - priv->scroll_x > delta) {
1512
		sd->right++;
1513
		priv->scroll_x += delta;
1514
	    }
1515
	    while (hw->x - priv->scroll_x < -delta) {
1516
		sd->left++;
1517
		priv->scroll_x -= delta;
1518
	    }
1519
	}
1520
    }
1521
    if (priv->circ_scroll_on) {
1522
	/* + = counter clockwise, - = clockwise */
1523
	double delta = para->scroll_dist_circ;
1524
	if (delta >= 0.005) {
1525
	    while (diffa(priv->scroll_a, angle(priv, hw->x, hw->y)) > delta) {
1526
		if (priv->circ_scroll_vert)
1527
		    sd->up++;
1528
		else
1529
		    sd->right++;
1530
		priv->scroll_a += delta;
1531
		if (priv->scroll_a > M_PI)
1532
		    priv->scroll_a -= 2 * M_PI;
1533
	    }
1534
	    while (diffa(priv->scroll_a, angle(priv, hw->x, hw->y)) < -delta) {
1535
		if (priv->circ_scroll_vert)
1536
		    sd->down++;
1537
		else
1538
		    sd->left++;
1539
		priv->scroll_a -= delta;
1540
		if (priv->scroll_a < -M_PI)
1541
		    priv->scroll_a += 2 * M_PI;
1542
	    }
1543
	}
1544
    }
1545
1546
    if (priv->autoscroll_yspd) {
1547
	double dtime = (hw->millis - HIST(0).millis) / 1000.0;
1548
	priv->autoscroll_y += priv->autoscroll_yspd * dtime;
1549
	delay = MIN(delay, 20);
1550
	while (priv->autoscroll_y > 1.0) {
1551
	    sd->down++;
1552
	    priv->autoscroll_y -= 1.0;
1553
	}
1554
	while (priv->autoscroll_y < -1.0) {
1555
	    sd->up++;
1556
	    priv->autoscroll_y += 1.0;
1557
	}
1558
    }
1559
    if (priv->autoscroll_xspd) {
1560
	double dtime = (hw->millis - HIST(0).millis) / 1000.0;
1561
	priv->autoscroll_x += priv->autoscroll_xspd * dtime;
1562
	delay = MIN(delay, 20);
1563
	while (priv->autoscroll_x > 1.0) {
1564
	    sd->right++;
1565
	    priv->autoscroll_x -= 1.0;
1566
	}
1567
	while (priv->autoscroll_x < -1.0) {
1568
	    sd->left++;
1569
	    priv->autoscroll_x += 1.0;
1570
	}
1571
    }
1572
1573
    return delay;
1574
}
1575
1576
/*
1577
 * React on changes in the hardware state. This function is called every time
1578
 * the hardware state changes. The return value is used to specify how many
1579
 * milliseconds to wait before calling the function again if no state change
1580
 * occurs.
1581
 */
1582
static int
1583
HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
1584
{
1585
    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
1586
    SynapticsSHM *para = priv->synpara;
1587
    Bool finger;
1588
    int dx, dy, buttons, rep_buttons, id;
1589
    edge_type edge;
1590
    int change;
1591
    struct ScrollData scroll;
1592
    int double_click, repeat_delay;
1593
    int delay = 1000000000;
1594
    int timeleft;
1595
    int i;
1596
1597
    /* update hardware state in shared memory */
1598
    para->x = hw->x;
1599
    para->y = hw->y;
1600
    para->z = hw->z;
1601
    para->numFingers = hw->numFingers;
1602
    para->fingerWidth = hw->fingerWidth;
1603
    para->left = hw->left;
1604
    para->right = hw->right;
1605
    para->up = hw->up;
1606
    para->down = hw->down;
1607
    for (i = 0; i < 8; i++)
1608
	para->multi[i] = hw->multi[i];
1609
    para->middle = hw->middle;
1610
    para->guest_left = hw->guest_left;
1611
    para->guest_mid = hw->guest_mid;
1612
    para->guest_right = hw->guest_right;
1613
    para->guest_dx = hw->guest_dx;
1614
    para->guest_dy = hw->guest_dy;
1615
1616
    /* If touchpad is switched off, we skip the whole thing and return delay */
1617
    if (para->touchpad_off == 1)
1618
	return delay;
1619
1620
    /* Treat the first two multi buttons as up/down for now. */
1621
    hw->up |= hw->multi[0];
1622
    hw->down |= hw->multi[1];
1623
1624
    if (!para->guestmouse_off) {
1625
	hw->left |= hw->guest_left;
1626
	hw->middle |= hw->guest_mid;
1627
	hw->right |= hw->guest_right;
1628
    }
1629
1630
    /* 3rd button emulation */
1631
    hw->middle |= HandleMidButtonEmulation(priv, hw, &delay);
1632
1633
    /* Up/Down button scrolling or middle/double click */
1634
    double_click = FALSE;
1635
    if (!para->updown_button_scrolling) {
1636
	if (hw->down) {		/* map down button to middle button */
1637
	    hw->middle = TRUE;
1638
	}
1639
1640
	if (hw->up) {		/* up button generates double click */
1641
	    if (!priv->prev_up)
1642
		double_click = TRUE;
1643
	}
1644
	priv->prev_up = hw->up;
1645
1646
	/* reset up/down button events */
1647
	hw->up = hw->down = FALSE;
1648
    }
1649
1650
    /* Left/right button scrolling, or middle clicks */
1651
    if (!para->leftright_button_scrolling) {
1652
	if (hw->multi[2] || hw->multi[3])
1653
	    hw->middle = TRUE;
1654
1655
	/* reset left/right button events */
1656
	hw->multi[2] = hw->multi[3] = FALSE;
1657
    }
1658
1659
    /*
1660
     * Some touchpads have a scroll wheel region where a very large X
1661
     * coordinate is reported. For such touchpads, we adjust the X
1662
     * coordinate to eliminate the discontinuity.
1663
     */
1664
    if (hw->x <= XMAX_VALID) {
1665
	if (priv->largest_valid_x < hw->x)
1666
	    priv->largest_valid_x = hw->x;
1667
    } else {
1668
	hw->x = priv->largest_valid_x;
1669
    }
1670
1671
    edge = edge_detection(priv, hw->x, hw->y);
1672
1673
    finger = SynapticsDetectFinger(priv, hw);
1674
1675
    /* tap and drag detection */
1676
    timeleft = HandleTapProcessing(priv, hw, edge, finger);
1677
    if (timeleft > 0)
1678
	delay = MIN(delay, timeleft);
1679
1680
    timeleft = HandleScrolling(priv, hw, edge, finger, &scroll);
1681
    if (timeleft > 0)
1682
	delay = MIN(delay, timeleft);
1683
1684
    timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy);
1685
    delay = MIN(delay, timeleft);
1686
1687
    rep_buttons = ((para->updown_button_repeat ? 0x18 : 0) |
1688
		   (para->leftright_button_repeat ? 0x60 : 0));
1689
1690
    buttons = ((hw->left     ? 0x01 : 0) |
1691
	       (hw->middle   ? 0x02 : 0) |
1692
	       (hw->right    ? 0x04 : 0) |
1693
	       (hw->up       ? 0x08 : 0) |
1694
	       (hw->down     ? 0x10 : 0) |
1695
	       (hw->multi[2] ? 0x20 : 0) |
1696
	       (hw->multi[3] ? 0x40 : 0));
1697
1698
    if (priv->tap_button > 0) {
1699
	int tap_mask = 1 << (priv->tap_button - 1);
1700
	if (priv->tap_button_state == TBS_BUTTON_DOWN_UP) {
1701
	    if (tap_mask != (priv->lastButtons & tap_mask)) {
1702
		xf86PostButtonEvent(local->dev, FALSE, priv->tap_button, TRUE, 0, 0);
1703
		priv->lastButtons |= tap_mask;
1704
	    }
1705
	    priv->tap_button_state = TBS_BUTTON_UP;
1706
	}
1707
	if (priv->tap_button_state == TBS_BUTTON_DOWN)
1708
	    buttons |= tap_mask;
1709
    }
1710
1711
    /* Post events */
1712
    if (dx || dy)
1713
	xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy);
1714
1715
    change = buttons ^ priv->lastButtons;
1716
    while (change) {
1717
	id = ffs(change); /* number of first set bit 1..32 is returned */
1718
	change &= ~(1 << (id - 1));
1719
	xf86PostButtonEvent(local->dev, FALSE, id, (buttons & (1 << (id - 1))), 0, 0);
1720
    }
1721
1722
    while (scroll.up-- > 0) {
1723
	xf86PostButtonEvent(local->dev, FALSE, 4, !hw->up, 0, 0);
1724
	xf86PostButtonEvent(local->dev, FALSE, 4, hw->up, 0, 0);
1725
    }
1726
    while (scroll.down-- > 0) {
1727
	xf86PostButtonEvent(local->dev, FALSE, 5, !hw->down, 0, 0);
1728
	xf86PostButtonEvent(local->dev, FALSE, 5, hw->down, 0, 0);
1729
    }
1730
    while (scroll.left-- > 0) {
1731
	xf86PostButtonEvent(local->dev, FALSE, 6, TRUE, 0, 0);
1732
	xf86PostButtonEvent(local->dev, FALSE, 6, FALSE, 0, 0);
1733
    }
1734
    while (scroll.right-- > 0) {
1735
	xf86PostButtonEvent(local->dev, FALSE, 7, TRUE, 0, 0);
1736
	xf86PostButtonEvent(local->dev, FALSE, 7, FALSE, 0, 0);
1737
    }
1738
    if (double_click) {
1739
	int i;
1740
	for (i = 0; i < 2; i++) {
1741
	    xf86PostButtonEvent(local->dev, FALSE, 1, !hw->left, 0, 0);
1742
	    xf86PostButtonEvent(local->dev, FALSE, 1, hw->left, 0, 0);
1743
	}
1744
    }
1745
1746
    /* Handle auto repeat buttons */
1747
    repeat_delay = clamp(para->scroll_button_repeat, SBR_MIN, SBR_MAX);
1748
    if (((hw->up || hw->down) && para->updown_button_repeat &&
1749
	 para->updown_button_scrolling) ||
1750
	((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat &&
1751
	 para->leftright_button_scrolling)) {
1752
	priv->repeatButtons = buttons & rep_buttons;
1753
	if (!priv->nextRepeat) {
1754
	    priv->nextRepeat = hw->millis + repeat_delay * 2;
1755
	}
1756
    } else {
1757
	priv->repeatButtons = 0;
1758
	priv->nextRepeat = 0;
1759
    }
1760
1761
    if (priv->repeatButtons) {
1762
	timeleft = TIME_DIFF(priv->nextRepeat, hw->millis);
1763
	if (timeleft > 0)
1764
	    delay = MIN(delay, timeleft);
1765
	if (timeleft <= 0) {
1766
	    int change, id;
1767
	    change = priv->repeatButtons;
1768
	    while (change) {
1769
		id = ffs(change);
1770
		change &= ~(1 << (id - 1));
1771
		xf86PostButtonEvent(local->dev, FALSE, id, FALSE, 0, 0);
1772
		xf86PostButtonEvent(local->dev, FALSE, id, TRUE, 0, 0);
1773
	    }
1774
1775
	    priv->nextRepeat = hw->millis + repeat_delay;
1776
	    delay = MIN(delay, repeat_delay);
1777
	}
1778
    }
1779
1780
    /* Save old values of some state variables */
1781
    priv->finger_flag = finger;
1782
    priv->lastButtons = buttons;
1783
1784
    return delay;
1785
}
1786
1787
static int
1788
ControlProc(LocalDevicePtr local, xDeviceCtl * control)
1789
{
1790
    DBG(3, ErrorF("Control Proc called\n"));
1791
    return Success;
1792
}
1793
1794
1795
static void
1796
CloseProc(LocalDevicePtr local)
1797
{
1798
    DBG(3, ErrorF("Close Proc called\n"));
1799
}
1800
1801
static int
1802
SwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
1803
{
1804
    ErrorF("SwitchMode called\n");
1805
    return Success;
1806
}
1807
1808
static Bool
1809
ConvertProc(LocalDevicePtr local,
1810
	    int first,
1811
	    int num,
1812
	    int v0,
1813
	    int v1,
1814
	    int v2,
1815
	    int v3,
1816
	    int v4,
1817
	    int v5,
1818
	    int *x,
1819
	    int *y)
1820
{
1821
    if (first != 0 || num != 2)
1822
	return FALSE;
1823
1824
    *x = v0;
1825
    *y = v1;
1826
1827
    return TRUE;
1828
}
1829
1830
1831
static Bool
1832
QueryHardware(LocalDevicePtr local)
1833
{
1834
    SynapticsPrivate *priv = (SynapticsPrivate *) local->private;
1835
    SynapticsSHM *para = priv->synpara;
1836
1837
    priv->comm.protoBufTail = 0;
1838
1839
    if (priv->proto_ops->QueryHardware(local, &priv->synhw)) {
1840
	para->synhw = priv->synhw;
1841
	if (priv->fifofd != -1) {
1842
	    xf86CloseSerial(priv->fifofd);
1843
	    priv->fifofd = -1;
1844
	}
1845
	return TRUE;
1846
    }
1847
1848
    if (priv->fifofd == -1) {
1849
	xf86Msg(X_ERROR, "%s no synaptics touchpad detected and no repeater device\n",
1850
		local->name);
1851
	return FALSE;
1852
    }
1853
    xf86Msg(X_PROBED, "%s no synaptics touchpad, data piped to repeater fifo\n", local->name);
1854
    priv->proto_ops->DeviceOffHook(local);
1855
    return TRUE;
1856
}

Return to bug 229919