synclient.c 12.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 *   Copyright 2002-2004 Peter Osterlund <petero2@telia.com>
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2
 *   of the License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

20
#include <stdio.h>
21
#include <stdlib.h>
22
23
24
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
25
#include <sys/time.h>
26
#include <unistd.h>
27
#include <string.h>
28
29
#include <stddef.h>
#include <math.h>
30

Peter Osterlund's avatar
Peter Osterlund committed
31
32
#include <X11/Xdefs.h>
#include "synaptics.h"
33

34
enum ParaType {
35
36
37
    PT_INT,
    PT_BOOL,
    PT_DOUBLE
38
39
40
};

struct Parameter {
Peter Osterlund's avatar
Peter Osterlund committed
41
    char *name;				    /* Name of parameter */
42
43
44
45
    int offset;				    /* Offset in shared memory area */
    enum ParaType type;			    /* Type of parameter */
    double min_val;			    /* Minimum allowed value */
    double max_val;			    /* Maximum allowed value */
46
47
48
49
50
};

#define DEFINE_PAR(name, memb, type, min_val, max_val) \
{ name, offsetof(SynapticsSHM, memb), (type), (min_val), (max_val) }

51
static struct Parameter params[] = {
52
53
54
55
56
57
58
59
    DEFINE_PAR("LeftEdge",             left_edge,               PT_INT,    0, 10000),
    DEFINE_PAR("RightEdge",            right_edge,              PT_INT,    0, 10000),
    DEFINE_PAR("TopEdge",              top_edge,                PT_INT,    0, 10000),
    DEFINE_PAR("BottomEdge",           bottom_edge,             PT_INT,    0, 10000),
    DEFINE_PAR("FingerLow",            finger_low,              PT_INT,    0, 255),
    DEFINE_PAR("FingerHigh",           finger_high,             PT_INT,    0, 255),
    DEFINE_PAR("MaxTapTime",           tap_time,                PT_INT,    0, 1000),
    DEFINE_PAR("MaxTapMove",           tap_move,                PT_INT,    0, 2000),
Peter Osterlund's avatar
Peter Osterlund committed
60
    DEFINE_PAR("MaxDoubleTapTime",     tap_time_2,              PT_INT,    0, 1000),
61
    DEFINE_PAR("SingleTapTimeout",     single_tap_timeout,      PT_INT,    0, 1000),
Peter Osterlund's avatar
Peter Osterlund committed
62
    DEFINE_PAR("ClickTime",            click_time,              PT_INT,    0, 1000),
63
    DEFINE_PAR("FastTaps",             fast_taps,               PT_BOOL,   0, 1),
64
    DEFINE_PAR("EmulateMidButtonTime", emulate_mid_button_time, PT_INT,    0, 1000),
65
    DEFINE_PAR("EmulateTwoFingerMinZ", emulate_twofinger_z,     PT_INT,    0, 1000),
66
67
    DEFINE_PAR("VertScrollDelta",      scroll_dist_vert,        PT_INT,    0, 1000),
    DEFINE_PAR("HorizScrollDelta",     scroll_dist_horiz,       PT_INT,    0, 1000),
68
69
70
71
    DEFINE_PAR("VertEdgeScroll",       scroll_edge_vert,        PT_BOOL,   0, 1),
    DEFINE_PAR("HorizEdgeScroll",      scroll_edge_horiz,       PT_BOOL,   0, 1),
    DEFINE_PAR("VertTwoFingerScroll",  scroll_twofinger_vert,   PT_BOOL,   0, 1),
    DEFINE_PAR("HorizTwoFingerScroll", scroll_twofinger_horiz,  PT_BOOL,   0, 1),
72
73
74
    DEFINE_PAR("MinSpeed",             min_speed,               PT_DOUBLE, 0, 1.0),
    DEFINE_PAR("MaxSpeed",             max_speed,               PT_DOUBLE, 0, 1.0),
    DEFINE_PAR("AccelFactor",          accl,                    PT_DOUBLE, 0, 0.2),
75
76
    DEFINE_PAR("EdgeMotionMinZ",       edge_motion_min_z,       PT_INT,    1, 255),
    DEFINE_PAR("EdgeMotionMaxZ",       edge_motion_max_z,       PT_INT,    1, 255),
77
78
    DEFINE_PAR("EdgeMotionMinSpeed",   edge_motion_min_speed,   PT_INT,    0, 1000),
    DEFINE_PAR("EdgeMotionMaxSpeed",   edge_motion_max_speed,   PT_INT,    0, 1000),
79
    DEFINE_PAR("EdgeMotionUseAlways",  edge_motion_use_always,  PT_BOOL,   0, 1),
80
    DEFINE_PAR("UpDownScrolling",      updown_button_scrolling, PT_BOOL,   0, 1),
81
82
83
84
    DEFINE_PAR("LeftRightScrolling",   leftright_button_scrolling, PT_BOOL,   0, 1),
    DEFINE_PAR("UpDownRepeat",         updown_button_repeat,    PT_BOOL,   0, 1),
    DEFINE_PAR("LeftRightRepeat",      leftright_button_repeat, PT_BOOL,   0, 1),
    DEFINE_PAR("ScrollButtonRepeat",   scroll_button_repeat,    PT_INT,    SBR_MIN , SBR_MAX),
85
    DEFINE_PAR("TouchpadOff",          touchpad_off,            PT_INT,    0, 2),
86
    DEFINE_PAR("GuestMouseOff",        guestmouse_off,          PT_BOOL,   0, 1),
87
    DEFINE_PAR("LockedDrags",          locked_drags,            PT_BOOL,   0, 1),
88
89
90
91
92
93
94
    DEFINE_PAR("RTCornerButton",       tap_action[RT_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
    DEFINE_PAR("RBCornerButton",       tap_action[RB_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
    DEFINE_PAR("LTCornerButton",       tap_action[LT_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
    DEFINE_PAR("LBCornerButton",       tap_action[LB_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
    DEFINE_PAR("TapButton1",           tap_action[F1_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
    DEFINE_PAR("TapButton2",           tap_action[F2_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
    DEFINE_PAR("TapButton3",           tap_action[F3_TAP],      PT_INT,    0, SYN_MAX_BUTTONS),
95
96
97
    DEFINE_PAR("CircularScrolling",    circular_scrolling,      PT_BOOL,   0, 1),
    DEFINE_PAR("CircScrollDelta",      scroll_dist_circ,        PT_DOUBLE, .01, 3),
    DEFINE_PAR("CircScrollTrigger",    circular_trigger,        PT_INT,    0, 8),
98
    DEFINE_PAR("CircularPad",          circular_pad,            PT_BOOL,   0, 1),
99
100
101
    DEFINE_PAR("PalmDetect",           palm_detect,             PT_BOOL,   0, 1),
    DEFINE_PAR("PalmMinWidth",         palm_min_width,          PT_INT,    0, 15),
    DEFINE_PAR("PalmMinZ",             palm_min_z,              PT_INT,    0, 255),
102
    DEFINE_PAR("CoastingSpeed",        coasting_speed,          PT_DOUBLE, 0, 20),
103
104
105
106
    DEFINE_PAR("PressureMotionMinZ",   press_motion_min_z,      PT_INT,    1, 255),
    DEFINE_PAR("PressureMotionMaxZ",   press_motion_max_z,      PT_INT,    1, 255),
    DEFINE_PAR("PressureMotionMinFactor", press_motion_min_factor, PT_DOUBLE, 0, 10.0),
    DEFINE_PAR("PressureMotionMaxFactor", press_motion_max_factor, PT_DOUBLE, 0, 10.0), 
107
    { 0, 0, 0, 0, 0 }
108
109
};

Peter Osterlund's avatar
Peter Osterlund committed
110
111
112
113
114
115
116
117
118
static void
show_hw_info(SynapticsSHM *synshm)
{
    printf("Hardware properties:\n");
    if (synshm->synhw.model_id) {
	printf("    Model Id     = %08x\n", synshm->synhw.model_id);
	printf("    Capabilities = %08x\n", synshm->synhw.capabilities);
	printf("    Identity     = %08x\n", synshm->synhw.identity);
    } else {
119
120
121
	printf("    Can't detect hardware properties.\n");
	printf("    This is normal if you are running linux kernel 2.6.\n");
	printf("    Check the kernel log for touchpad hardware information.\n");
Peter Osterlund's avatar
Peter Osterlund committed
122
    }
123
    printf("Driver version: %d\n", VERSION_ID);
Peter Osterlund's avatar
Peter Osterlund committed
124
125
126
127
}

static void
show_settings(SynapticsSHM *synshm)
128
{
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    int i;

    printf("Parameter settings:\n");
    for (i = 0; params[i].name; i++) {
	struct Parameter* par = &params[i];
	switch (par->type) {
	case PT_INT:
	    printf("    %-20s = %d\n", par->name, *(int*)((char*)synshm + par->offset));
	    break;
	case PT_BOOL:
	    printf("    %-20s = %d\n", par->name, *(Bool*)((char*)synshm + par->offset));
	    break;
	case PT_DOUBLE:
	    printf("    %-20s = %g\n", par->name, *(double*)((char*)synshm + par->offset));
	    break;
144
	}
145
    }
146
147
}

Peter Osterlund's avatar
Peter Osterlund committed
148
149
static void
set_variables(SynapticsSHM *synshm, int argc, char *argv[], int first_cmd)
150
{
151
152
    int i;
    for (i = first_cmd; i < argc; i++) {
Peter Osterlund's avatar
Peter Osterlund committed
153
154
	char *cmd = argv[i];
	char *eqp = index(cmd, '=');
155
156
157
158
159
	if (eqp) {
	    int j;
	    int found = 0;
	    *eqp = 0;
	    for (j = 0; params[j].name; j++) {
160
		if (strcasecmp(cmd, params[j].name) == 0) {
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
		    found = 1;
		    break;
		}
	    }
	    if (found) {
		double val = atof(&eqp[1]);
		struct Parameter* par = &params[j];

		if (val < par->min_val)
		    val = par->min_val;
		if (val > par->max_val)
		    val = par->max_val;

		switch (par->type) {
		case PT_INT:
		    *(int*)((char*)synshm + par->offset) = (int)rint(val);
		    break;
		case PT_BOOL:
		    *(Bool*)((char*)synshm + par->offset) = (Bool)rint(val);
		    break;
		case PT_DOUBLE:
		    *(double*)((char*)synshm + par->offset) = val;
		    break;
184
		}
185
186
187
188
189
	    } else {
		printf("Unknown parameter %s\n", cmd);
	    }
	} else {
	    printf("Invalid command: %s\n", cmd);
190
	}
191
    }
192
193
}

Peter Osterlund's avatar
Peter Osterlund committed
194
195
static int
is_equal(SynapticsSHM *s1, SynapticsSHM *s2)
196
{
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    int i;

    if ((s1->x           != s2->x) ||
	(s1->y           != s2->y) ||
	(s1->z           != s2->z) ||
	(s1->numFingers  != s2->numFingers) ||
	(s1->fingerWidth != s2->fingerWidth) ||
	(s1->left        != s2->left) ||
	(s1->right       != s2->right) ||
	(s1->up          != s2->up) ||
	(s1->down        != s2->down) ||
	(s1->middle      != s2->middle) ||
	(s1->guest_left  != s2->guest_left) ||
	(s1->guest_mid   != s2->guest_mid) ||
	(s1->guest_right != s2->guest_right) ||
	(s1->guest_dx    != s2->guest_dx) ||
	(s1->guest_dy    != s2->guest_dy))
	return 0;

    for (i = 0; i < 8; i++)
	if (s1->multi[i] != s2->multi[i])
	    return 0;

    return 1;
221
222
}

Peter Osterlund's avatar
Peter Osterlund committed
223
224
static double
get_time()
225
226
227
228
229
230
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + tv.tv_usec / 1000000.0;
}

Peter Osterlund's avatar
Peter Osterlund committed
231
232
static void
monitor(SynapticsSHM *synshm, int delay)
Peter Osterlund's avatar
Peter Osterlund committed
233
{
234
    int header = 0;
235
    SynapticsSHM old;
236
237
    double t0 = get_time();

238
239
240
    memset(&old, 0, sizeof(SynapticsSHM));
    old.x = -1;				    /* Force first equality test to fail */

Peter Osterlund's avatar
Peter Osterlund committed
241
    while (1) {
242
243
	SynapticsSHM cur = *synshm;
	if (!is_equal(&old, &cur)) {
244
	    if (!header) {
245
		printf("%8s  %4s %4s %3s %s %2s %2s %s %s %s %s  %8s  "
246
		       "%2s %2s %2s %3s %3s\n",
247
		       "time", "x", "y", "z", "f", "w", "l", "r", "u", "d", "m",
248
		       "multi", "gl", "gm", "gr", "gdx", "gdy");
249
250
251
		header = 20;
	    }
	    header--;
252
	    printf("%8.3f  %4d %4d %3d %d %2d %2d %d %d %d %d  %d%d%d%d%d%d%d%d  "
253
		   "%2d %2d %2d %3d %3d\n",
254
		   get_time() - t0,
255
		   cur.x, cur.y, cur.z, cur.numFingers, cur.fingerWidth,
256
		   cur.left, cur.right, cur.up, cur.down, cur.middle,
257
		   cur.multi[0], cur.multi[1], cur.multi[2], cur.multi[3],
258
259
260
		   cur.multi[4], cur.multi[5], cur.multi[6], cur.multi[7],
		   cur.guest_left, cur.guest_mid, cur.guest_right,
		   cur.guest_dx, cur.guest_dy);
261
	    fflush(stdout);
262
	    old = cur;
263
	}
264
265
	usleep(delay * 1000);
    }
266
267
}

Peter Osterlund's avatar
Peter Osterlund committed
268
269
static void
usage()
270
{
271
    fprintf(stderr, "Usage: synclient [-m interval] [-h] [-l] [-V] [-?] [var1=value1 [var2=value2] ...]\n");
272
273
274
275
    fprintf(stderr, "  -m monitor changes to the touchpad state.\n"
	    "     interval specifies how often (in ms) to poll the touchpad state\n");
    fprintf(stderr, "  -h Show detected hardware properties\n");
    fprintf(stderr, "  -l List current user settings\n");
276
    fprintf(stderr, "  -V Print synclient version string and exit\n");
277
278
279
    fprintf(stderr, "  -? Show this help message\n");
    fprintf(stderr, "  var=value  Set user parameter 'var' to 'value'.\n");
    exit(1);
280
281
}

Peter Osterlund's avatar
Peter Osterlund committed
282
283
int
main(int argc, char *argv[])
284
{
285
286
287
288
289
290
291
292
293
294
295
    SynapticsSHM *synshm;
    int shmid;

    int c;
    int delay = -1;
    int do_monitor = 0;
    int dump_hw = 0;
    int dump_settings = 0;
    int first_cmd;

    /* Parse command line parameters */
296
    while ((c = getopt(argc, argv, "m:hlV")) != -1) {
297
298
299
300
	switch (c) {
	case 'm':
	    do_monitor = 1;
	    if ((delay = atoi(optarg)) < 0)
301
		usage();
302
303
304
305
306
307
308
	    break;
	case 'h':
	    dump_hw = 1;
	    break;
	case 'l':
	    dump_settings = 1;
	    break;
309
310
311
	case 'V':
	    printf("%s\n", VERSION);
	    exit(0);
312
313
	default:
	    usage();
314
	}
315
316
317
318
319
320
    }
    first_cmd = optind;
    if (!do_monitor && !dump_hw && !dump_settings && first_cmd == argc)
	usage();

    /* Connect to the shared memory area */
Peter Osterlund's avatar
Peter Osterlund committed
321
    if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM), 0)) == -1) {
322
323
324
325
326
327
	if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) == -1) {
	    fprintf(stderr, "Can't access shared memory area. SHMConfig disabled?\n");
	    exit(1);
	} else {
	    fprintf(stderr, "Incorrect size of shared memory area. Incompatible driver version?\n");
	    exit(1);
328
	}
329
    }
Peter Osterlund's avatar
Peter Osterlund committed
330
    if ((synshm = (SynapticsSHM*) shmat(shmid, NULL, 0)) == NULL) {
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
	perror("shmat");
	exit(1);
    }

    /* Perform requested actions */
    if (dump_hw) {
	show_hw_info(synshm);
    }
    set_variables(synshm, argc, argv, first_cmd);
    if (dump_settings) {
	show_settings(synshm);
    }
    if (do_monitor) {
	monitor(synshm, delay);
    }

    exit(0);
348
}