Lines 81-86
__FBSDID("$FreeBSD$");
Link Here
|
81 |
#include <sys/sysctl.h> |
81 |
#include <sys/sysctl.h> |
82 |
#include <sys/time.h> |
82 |
#include <sys/time.h> |
83 |
#include <sys/uio.h> |
83 |
#include <sys/uio.h> |
|
|
84 |
#include <sys/libkern.h> |
84 |
|
85 |
|
85 |
#include <sys/limits.h> |
86 |
#include <sys/limits.h> |
86 |
#include <sys/mouse.h> |
87 |
#include <sys/mouse.h> |
Lines 161-200
typedef struct packetbuf {
Link Here
|
161 |
#define PSM_PACKETQUEUE 128 |
162 |
#define PSM_PACKETQUEUE 128 |
162 |
#endif |
163 |
#endif |
163 |
|
164 |
|
164 |
enum { |
|
|
165 |
SYNAPTICS_SYSCTL_MIN_PRESSURE, |
166 |
SYNAPTICS_SYSCTL_MAX_PRESSURE, |
167 |
SYNAPTICS_SYSCTL_MAX_WIDTH, |
168 |
SYNAPTICS_SYSCTL_MARGIN_TOP, |
169 |
SYNAPTICS_SYSCTL_MARGIN_RIGHT, |
170 |
SYNAPTICS_SYSCTL_MARGIN_BOTTOM, |
171 |
SYNAPTICS_SYSCTL_MARGIN_LEFT, |
172 |
SYNAPTICS_SYSCTL_NA_TOP, |
173 |
SYNAPTICS_SYSCTL_NA_RIGHT, |
174 |
SYNAPTICS_SYSCTL_NA_BOTTOM, |
175 |
SYNAPTICS_SYSCTL_NA_LEFT, |
176 |
SYNAPTICS_SYSCTL_WINDOW_MIN, |
177 |
SYNAPTICS_SYSCTL_WINDOW_MAX, |
178 |
SYNAPTICS_SYSCTL_MULTIPLICATOR, |
179 |
SYNAPTICS_SYSCTL_WEIGHT_CURRENT, |
180 |
SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, |
181 |
SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, |
182 |
SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, |
183 |
SYNAPTICS_SYSCTL_DIV_MIN, |
184 |
SYNAPTICS_SYSCTL_DIV_MAX, |
185 |
SYNAPTICS_SYSCTL_DIV_MAX_NA, |
186 |
SYNAPTICS_SYSCTL_DIV_LEN, |
187 |
SYNAPTICS_SYSCTL_TAP_MAX_DELTA, |
188 |
SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, |
189 |
SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, |
190 |
SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, |
191 |
SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, |
192 |
SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, |
193 |
SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, |
194 |
SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, |
195 |
SYNAPTICS_SYSCTL_TOUCHPAD_OFF |
196 |
}; |
197 |
|
198 |
typedef struct synapticsinfo { |
165 |
typedef struct synapticsinfo { |
199 |
struct sysctl_ctx_list sysctl_ctx; |
166 |
struct sysctl_ctx_list sysctl_ctx; |
200 |
struct sysctl_oid *sysctl_tree; |
167 |
struct sysctl_oid *sysctl_tree; |
Lines 231-236
typedef struct synapticsinfo {
Link Here
|
231 |
int vscroll_div_min; |
198 |
int vscroll_div_min; |
232 |
int vscroll_div_max; |
199 |
int vscroll_div_max; |
233 |
int touchpad_off; |
200 |
int touchpad_off; |
|
|
201 |
int softbuttons_y; |
202 |
int softbutton2_x; |
203 |
int softbutton3_x; |
234 |
} synapticsinfo_t; |
204 |
} synapticsinfo_t; |
235 |
|
205 |
|
236 |
typedef struct synapticspacket { |
206 |
typedef struct synapticspacket { |
Lines 261-266
typedef struct synapticsaction {
Link Here
|
261 |
int tap_button; |
231 |
int tap_button; |
262 |
int in_taphold; |
232 |
int in_taphold; |
263 |
int in_vscroll; |
233 |
int in_vscroll; |
|
|
234 |
int is_fuzzy; |
264 |
} synapticsaction_t; |
235 |
} synapticsaction_t; |
265 |
|
236 |
|
266 |
enum { |
237 |
enum { |
Lines 295-300
typedef struct trackpointinfo {
Link Here
|
295 |
int skipback; |
266 |
int skipback; |
296 |
} trackpointinfo_t; |
267 |
} trackpointinfo_t; |
297 |
|
268 |
|
|
|
269 |
typedef struct finger { |
270 |
int x; |
271 |
int y; |
272 |
int p; |
273 |
int w; |
274 |
int flags; |
275 |
} finger_t; |
276 |
#define PSM_FINGER_IS_PEN (1<<0) |
277 |
#define PSM_FINGER_FUZZY (1<<1) |
278 |
#define PSM_FINGER_IS_SET(f) ((f).x != -1 && (f).y != -1 && (f).p != 0) |
279 |
#define PSM_FINGER_RESET(f) do \ |
280 |
(f) = (finger_t) { .x = -1, .y = -1, .p = 0, .w = 0, .flags = 0 }; \ |
281 |
while (0) |
282 |
|
283 |
typedef struct elantechhw { |
284 |
int hwversion; |
285 |
int fwversion; |
286 |
int sizex; |
287 |
int sizey; |
288 |
int dpmmx; |
289 |
int dpmmy; |
290 |
int ntracesx; |
291 |
int ntracesy; |
292 |
int issemimt; |
293 |
int isclickpad; |
294 |
int hascrc; |
295 |
int hastrackpad; |
296 |
int haspressure; |
297 |
} elantechhw_t; |
298 |
|
299 |
/* minimum versions supported by this driver */ |
300 |
#define ELANTECH_HW_IS_V1(fwver) ((fwver) < 0x020030 || (fwver) == 0x020600) |
301 |
|
302 |
#define ELANTECH_MAGIC(magic) \ |
303 |
((magic)[0] == 0x3c && (magic)[1] == 0x03 && \ |
304 |
((magic)[2] == 0xc8 || (magic)[2] == 0x00)) |
305 |
|
306 |
#define ELANTECH_FW_ID 0x00 |
307 |
#define ELANTECH_FW_VERSION 0x01 |
308 |
#define ELANTECH_CAPABILITIES 0x02 |
309 |
#define ELANTECH_SAMPLE 0x03 |
310 |
#define ELANTECH_RESOLUTION 0x04 |
311 |
#define ELANTECH_REG_READ 0x10 |
312 |
#define ELANTECH_REG_WRITE 0x11 |
313 |
#define ELANTECH_REG_RDWR 0x00 |
314 |
#define ELANTECH_CUSTOM_CMD 0xf8 |
315 |
|
316 |
#define ELANTECH_MAX_FINGERS 2 |
317 |
|
318 |
#define ELANTECH_FINGER_DEFAULT_P tap_threshold |
319 |
#define ELANTECH_FINGER_DEFAULT_W 1 |
320 |
#define ELANTECH_FINGER_SET_XYP(pb) (finger_t) { \ |
321 |
.x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \ |
322 |
.y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \ |
323 |
.p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \ |
324 |
.w = ELANTECH_FINGER_DEFAULT_W, \ |
325 |
.flags = 0 \ |
326 |
} |
327 |
|
328 |
enum { |
329 |
ELANTECH_PKT_NOP, |
330 |
ELANTECH_PKT_TRACKPOINT, |
331 |
ELANTECH_PKT_V2_COMMON, |
332 |
ELANTECH_PKT_V2_2FINGER, |
333 |
ELANTECH_PKT_V3, |
334 |
ELANTECH_PKT_V4_STATUS, |
335 |
ELANTECH_PKT_V4_HEAD, |
336 |
ELANTECH_PKT_V4_MOTION |
337 |
}; |
338 |
|
339 |
#define ELANTECH_PKT_IS_TRACKPOINT(pb) (((pb)->ipacket[3] & 0x0f) == 0x06) |
340 |
#define ELANTECH_PKT_IS_DEBOUNCE(pb, hwversion) ((hwversion) == 4 ? 0 : \ |
341 |
(pb)->ipacket[0] == ((hwversion) == 2 ? 0x84 : 0xc4) && \ |
342 |
(pb)->ipacket[1] == 0xff && (pb)->ipacket[2] == 0xff && \ |
343 |
(pb)->ipacket[3] == 0x02 && (pb)->ipacket[4] == 0xff && \ |
344 |
(pb)->ipacket[5] == 0xff) |
345 |
#define ELANTECH_PKT_IS_V2(pb) \ |
346 |
(((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x0f) == 0x02) |
347 |
#define ELANTECH_PKT_IS_V3_HEAD(pb, hascrc) ((hascrc) ? \ |
348 |
((pb)->ipacket[3] & 0x09) == 0x08 : \ |
349 |
((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0xcf) == 0x02) |
350 |
#define ELANTECH_PKT_IS_V3_TAIL(pb, hascrc) ((hascrc) ? \ |
351 |
((pb)->ipacket[3] & 0x09) == 0x09 : \ |
352 |
((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c) |
353 |
#define ELANTECH_PKT_IS_V4(pb, hascrc) ((hascrc) ? \ |
354 |
((pb)->ipacket[3] & 0x08) == 0x00 : \ |
355 |
((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10) |
356 |
|
357 |
typedef struct elantechaction { |
358 |
finger_t fingers[ELANTECH_MAX_FINGERS]; |
359 |
int nfingers; |
360 |
} elantechaction_t; |
361 |
|
298 |
/* driver control block */ |
362 |
/* driver control block */ |
299 |
struct psm_softc { /* Driver status information */ |
363 |
struct psm_softc { /* Driver status information */ |
300 |
int unit; |
364 |
int unit; |
Lines 309-314
struct psm_softc { /* Driver status information */
Link Here
|
309 |
synapticshw_t synhw; /* Synaptics hardware information */ |
373 |
synapticshw_t synhw; /* Synaptics hardware information */ |
310 |
synapticsinfo_t syninfo; /* Synaptics configuration */ |
374 |
synapticsinfo_t syninfo; /* Synaptics configuration */ |
311 |
synapticsaction_t synaction; /* Synaptics action context */ |
375 |
synapticsaction_t synaction; /* Synaptics action context */ |
|
|
376 |
elantechhw_t elanhw; /* Elantech hardware information */ |
377 |
elantechaction_t elanaction; /* Elantech action context */ |
312 |
int tphw; /* TrackPoint hardware information */ |
378 |
int tphw; /* TrackPoint hardware information */ |
313 |
trackpointinfo_t tpinfo; /* TrackPoint configuration */ |
379 |
trackpointinfo_t tpinfo; /* TrackPoint configuration */ |
314 |
mousemode_t mode; /* operation mode */ |
380 |
mousemode_t mode; /* operation mode */ |
Lines 331-336
struct psm_softc { /* Driver status information */
Link Here
|
331 |
struct timeval lastsoftintr; /* time of last soft interrupt */ |
397 |
struct timeval lastsoftintr; /* time of last soft interrupt */ |
332 |
struct timeval lastinputerr; /* time last sync error happened */ |
398 |
struct timeval lastinputerr; /* time last sync error happened */ |
333 |
struct timeval taptimeout; /* tap timeout for touchpads */ |
399 |
struct timeval taptimeout; /* tap timeout for touchpads */ |
|
|
400 |
struct timeval idletimeout; |
401 |
packetbuf_t idlepacket; /* packet to send after idle timeout */ |
334 |
int watchdog; /* watchdog timer flag */ |
402 |
int watchdog; /* watchdog timer flag */ |
335 |
struct callout callout; /* watchdog timer call out */ |
403 |
struct callout callout; /* watchdog timer call out */ |
336 |
struct callout softcallout; /* buffer timer call out */ |
404 |
struct callout softcallout; /* buffer timer call out */ |
Lines 389-394
TUNABLE_INT("hw.psm.synaptics_support", &synaptics_support);
Link Here
|
389 |
static int trackpoint_support = 0; |
457 |
static int trackpoint_support = 0; |
390 |
TUNABLE_INT("hw.psm.trackpoint_support", &trackpoint_support); |
458 |
TUNABLE_INT("hw.psm.trackpoint_support", &trackpoint_support); |
391 |
|
459 |
|
|
|
460 |
static int elantech_support = 0; |
461 |
TUNABLE_INT("hw.psm.elantech_support", &elantech_support); |
462 |
|
392 |
static int verbose = PSM_DEBUG; |
463 |
static int verbose = PSM_DEBUG; |
393 |
TUNABLE_INT("debug.psm.loglevel", &verbose); |
464 |
TUNABLE_INT("debug.psm.loglevel", &verbose); |
394 |
|
465 |
|
Lines 411-416
typedef struct old_mousemode {
Link Here
|
411 |
int accelfactor; |
482 |
int accelfactor; |
412 |
} old_mousemode_t; |
483 |
} old_mousemode_t; |
413 |
|
484 |
|
|
|
485 |
#define SYN_OFFSET(field) offsetof(struct psm_softc, syninfo.field) |
486 |
enum { |
487 |
SYNAPTICS_SYSCTL_MIN_PRESSURE = SYN_OFFSET(min_pressure), |
488 |
SYNAPTICS_SYSCTL_MAX_PRESSURE = SYN_OFFSET(max_pressure), |
489 |
SYNAPTICS_SYSCTL_MAX_WIDTH = SYN_OFFSET(max_width), |
490 |
SYNAPTICS_SYSCTL_MARGIN_TOP = SYN_OFFSET(margin_top), |
491 |
SYNAPTICS_SYSCTL_MARGIN_RIGHT = SYN_OFFSET(margin_right), |
492 |
SYNAPTICS_SYSCTL_MARGIN_BOTTOM = SYN_OFFSET(margin_bottom), |
493 |
SYNAPTICS_SYSCTL_MARGIN_LEFT = SYN_OFFSET(margin_left), |
494 |
SYNAPTICS_SYSCTL_NA_TOP = SYN_OFFSET(na_top), |
495 |
SYNAPTICS_SYSCTL_NA_RIGHT = SYN_OFFSET(na_right), |
496 |
SYNAPTICS_SYSCTL_NA_BOTTOM = SYN_OFFSET(na_bottom), |
497 |
SYNAPTICS_SYSCTL_NA_LEFT = SYN_OFFSET(na_left), |
498 |
SYNAPTICS_SYSCTL_WINDOW_MIN = SYN_OFFSET(window_min), |
499 |
SYNAPTICS_SYSCTL_WINDOW_MAX = SYN_OFFSET(window_max), |
500 |
SYNAPTICS_SYSCTL_MULTIPLICATOR = SYN_OFFSET(multiplicator), |
501 |
SYNAPTICS_SYSCTL_WEIGHT_CURRENT = SYN_OFFSET(weight_current), |
502 |
SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS = SYN_OFFSET(weight_previous), |
503 |
SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA = SYN_OFFSET(weight_previous_na), |
504 |
SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED = SYN_OFFSET(weight_len_squared), |
505 |
SYNAPTICS_SYSCTL_DIV_MIN = SYN_OFFSET(div_min), |
506 |
SYNAPTICS_SYSCTL_DIV_MAX = SYN_OFFSET(div_max), |
507 |
SYNAPTICS_SYSCTL_DIV_MAX_NA = SYN_OFFSET(div_max_na), |
508 |
SYNAPTICS_SYSCTL_DIV_LEN = SYN_OFFSET(div_len), |
509 |
SYNAPTICS_SYSCTL_TAP_MAX_DELTA = SYN_OFFSET(tap_max_delta), |
510 |
SYNAPTICS_SYSCTL_TAP_MIN_QUEUE = SYN_OFFSET(tap_min_queue), |
511 |
SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT = SYN_OFFSET(taphold_timeout), |
512 |
SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA = SYN_OFFSET(vscroll_hor_area), |
513 |
SYNAPTICS_SYSCTL_VSCROLL_VER_AREA = SYN_OFFSET(vscroll_ver_area), |
514 |
SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA = SYN_OFFSET(vscroll_min_delta), |
515 |
SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN = SYN_OFFSET(vscroll_div_min), |
516 |
SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX = SYN_OFFSET(vscroll_div_max), |
517 |
SYNAPTICS_SYSCTL_TOUCHPAD_OFF = SYN_OFFSET(touchpad_off), |
518 |
SYNAPTICS_SYSCTL_SOFTBUTTONS_Y = SYN_OFFSET(softbuttons_y), |
519 |
SYNAPTICS_SYSCTL_SOFTBUTTON2_X = SYN_OFFSET(softbutton2_x), |
520 |
SYNAPTICS_SYSCTL_SOFTBUTTON3_X = SYN_OFFSET(softbutton3_x), |
521 |
}; |
522 |
|
414 |
/* packet formatting function */ |
523 |
/* packet formatting function */ |
415 |
typedef int packetfunc_t(struct psm_softc *, u_char *, int *, int, |
524 |
typedef int packetfunc_t(struct psm_softc *, u_char *, int *, int, |
416 |
mousestatus_t *); |
525 |
mousestatus_t *); |
Lines 446-451
static int doopen(struct psm_softc *, int);
Link Here
|
446 |
static int reinitialize(struct psm_softc *, int); |
555 |
static int reinitialize(struct psm_softc *, int); |
447 |
static char *model_name(int); |
556 |
static char *model_name(int); |
448 |
static void psmsoftintr(void *); |
557 |
static void psmsoftintr(void *); |
|
|
558 |
static void psmsoftintridle(void *); |
449 |
static void psmintr(void *); |
559 |
static void psmintr(void *); |
450 |
static void psmtimeout(void *); |
560 |
static void psmtimeout(void *); |
451 |
static int timeelapsed(const struct timeval *, int, int, |
561 |
static int timeelapsed(const struct timeval *, int, int, |
Lines 458-463
static int proc_synaptics(struct psm_softc *, packetbuf_t *,
Link Here
|
458 |
mousestatus_t *, int *, int *, int *); |
568 |
mousestatus_t *, int *, int *, int *); |
459 |
static void proc_versapad(struct psm_softc *, packetbuf_t *, |
569 |
static void proc_versapad(struct psm_softc *, packetbuf_t *, |
460 |
mousestatus_t *, int *, int *, int *); |
570 |
mousestatus_t *, int *, int *, int *); |
|
|
571 |
static int proc_elantech(struct psm_softc *, packetbuf_t *, |
572 |
mousestatus_t *, int *, int *, int *); |
573 |
static void psmgestures(struct psm_softc *, finger_t*, int, |
574 |
mousestatus_t *, int *, int *); |
575 |
static int psmsoftbuttons(struct psm_softc *, finger_t *, int); |
461 |
static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, |
576 |
static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, |
462 |
u_char *); |
577 |
u_char *); |
463 |
|
578 |
|
Lines 480-485
static probefunc_t enable_mmanplus;
Link Here
|
480 |
static probefunc_t enable_synaptics; |
595 |
static probefunc_t enable_synaptics; |
481 |
static probefunc_t enable_trackpoint; |
596 |
static probefunc_t enable_trackpoint; |
482 |
static probefunc_t enable_versapad; |
597 |
static probefunc_t enable_versapad; |
|
|
598 |
static probefunc_t enable_elantech; |
483 |
|
599 |
|
484 |
static void set_trackpoint_parameters(struct psm_softc *sc); |
600 |
static void set_trackpoint_parameters(struct psm_softc *sc); |
485 |
static void synaptics_passthrough_on(struct psm_softc *sc); |
601 |
static void synaptics_passthrough_on(struct psm_softc *sc); |
Lines 511-516
static struct {
Link Here
|
511 |
0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus }, |
627 |
0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus }, |
512 |
{ MOUSE_MODEL_SYNAPTICS, /* Synaptics Touchpad */ |
628 |
{ MOUSE_MODEL_SYNAPTICS, /* Synaptics Touchpad */ |
513 |
0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics }, |
629 |
0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics }, |
|
|
630 |
{ MOUSE_MODEL_ELANTECH, /* Elantech Touchpad */ |
631 |
0x04, MOUSE_ELANTECH_PACKETSIZE, enable_elantech }, |
514 |
{ MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ |
632 |
{ MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ |
515 |
0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli }, |
633 |
0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli }, |
516 |
{ MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ |
634 |
{ MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ |
Lines 762-767
model_name(int model)
Link Here
|
762 |
{ MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, |
880 |
{ MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, |
763 |
{ MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, |
881 |
{ MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, |
764 |
{ MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, |
882 |
{ MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, |
|
|
883 |
{ MOUSE_MODEL_ELANTECH, "Elantech Touchpad" }, |
765 |
{ MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, |
884 |
{ MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, |
766 |
{ MOUSE_MODEL_UNKNOWN, "Unknown" }, |
885 |
{ MOUSE_MODEL_UNKNOWN, "Unknown" }, |
767 |
}; |
886 |
}; |
Lines 1504-1509
psmattach(device_t dev)
Link Here
|
1504 |
case MOUSE_MODEL_SYNAPTICS: |
1623 |
case MOUSE_MODEL_SYNAPTICS: |
1505 |
case MOUSE_MODEL_GLIDEPOINT: |
1624 |
case MOUSE_MODEL_GLIDEPOINT: |
1506 |
case MOUSE_MODEL_VERSAPAD: |
1625 |
case MOUSE_MODEL_VERSAPAD: |
|
|
1626 |
case MOUSE_MODEL_ELANTECH: |
1507 |
sc->config |= PSM_CONFIG_INITAFTERSUSPEND; |
1627 |
sc->config |= PSM_CONFIG_INITAFTERSUSPEND; |
1508 |
break; |
1628 |
break; |
1509 |
default: |
1629 |
default: |
Lines 1512-1517
psmattach(device_t dev)
Link Here
|
1512 |
break; |
1632 |
break; |
1513 |
} |
1633 |
} |
1514 |
|
1634 |
|
|
|
1635 |
/* Elantech trackpad`s sync bit differs from touchpad`s one */ |
1636 |
if (sc->hw.model == MOUSE_MODEL_ELANTECH && |
1637 |
(sc->elanhw.hascrc || sc->elanhw.hastrackpad)) |
1638 |
sc->config |= PSM_CONFIG_NOCHECKSYNC; |
1639 |
|
1515 |
if (!verbose) |
1640 |
if (!verbose) |
1516 |
printf("psm%d: model %s, device ID %d\n", |
1641 |
printf("psm%d: model %s, device ID %d\n", |
1517 |
unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff); |
1642 |
unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff); |
Lines 2627-2633
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
2627 |
{ |
2752 |
{ |
2628 |
static int touchpad_buttons; |
2753 |
static int touchpad_buttons; |
2629 |
static int guest_buttons; |
2754 |
static int guest_buttons; |
2630 |
int w, x0, y0; |
2755 |
finger_t f; |
|
|
2756 |
int w, nfingers; |
2631 |
|
2757 |
|
2632 |
/* TouchPad PS/2 absolute mode message format with capFourButtons: |
2758 |
/* TouchPad PS/2 absolute mode message format with capFourButtons: |
2633 |
* |
2759 |
* |
Lines 2814-2832
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
2814 |
touchpad_buttons |= sc->extended_buttons; |
2940 |
touchpad_buttons |= sc->extended_buttons; |
2815 |
} |
2941 |
} |
2816 |
} |
2942 |
} |
|
|
2943 |
|
2944 |
f.x = ((pb->ipacket[3] & 0x10) << 8) | |
2945 |
((pb->ipacket[1] & 0x0f) << 8) | |
2946 |
pb->ipacket[4]; |
2947 |
f.y = ((pb->ipacket[3] & 0x20) << 7) | |
2948 |
((pb->ipacket[1] & 0xf0) << 4) | |
2949 |
pb->ipacket[5]; |
2950 |
f.p = *z; |
2951 |
f.w = w; |
2952 |
f.flags = w == 2 ? PSM_FINGER_IS_PEN : 0; |
2953 |
f.flags |= w < 2 ? PSM_FINGER_FUZZY : 0; |
2954 |
nfingers = w < 2 ? w + 2 : 1; |
2955 |
|
2817 |
/* Handle ClickPad. */ |
2956 |
/* Handle ClickPad. */ |
2818 |
if (sc->synhw.capClickPad && |
2957 |
if (sc->synhw.capClickPad) |
2819 |
((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) |
2958 |
touchpad_buttons |= psmsoftbuttons(sc, &f, |
2820 |
touchpad_buttons |= MOUSE_BUTTON1DOWN; |
2959 |
(pb->ipacket[0] ^ pb->ipacket[3]) & 0x01); |
2821 |
|
2960 |
|
2822 |
ms->button = touchpad_buttons | guest_buttons; |
2961 |
ms->button = touchpad_buttons | guest_buttons; |
2823 |
|
2962 |
|
|
|
2963 |
psmgestures(sc, &f, nfingers, ms, x, y); |
2964 |
|
2965 |
SYNAPTICS_END: |
2966 |
/* |
2967 |
* Use the extra buttons as a scrollwheel |
2968 |
* |
2969 |
* XXX X.Org uses the Z axis for vertical wheel only, |
2970 |
* whereas moused(8) understands special values to differ |
2971 |
* vertical and horizontal wheels. |
2972 |
* |
2973 |
* xf86-input-mouse needs therefore a small patch to |
2974 |
* understand these special values. Without it, the |
2975 |
* horizontal wheel acts as a vertical wheel in X.Org. |
2976 |
* |
2977 |
* That's why the horizontal wheel is disabled by |
2978 |
* default for now. |
2979 |
*/ |
2980 |
if (ms->button & MOUSE_BUTTON4DOWN) { |
2981 |
*z = -1; |
2982 |
ms->button &= ~MOUSE_BUTTON4DOWN; |
2983 |
} else if (ms->button & MOUSE_BUTTON5DOWN) { |
2984 |
*z = 1; |
2985 |
ms->button &= ~MOUSE_BUTTON5DOWN; |
2986 |
} else if (ms->button & MOUSE_BUTTON6DOWN) { |
2987 |
*z = -2; |
2988 |
ms->button &= ~MOUSE_BUTTON6DOWN; |
2989 |
} else if (ms->button & MOUSE_BUTTON7DOWN) { |
2990 |
*z = 2; |
2991 |
ms->button &= ~MOUSE_BUTTON7DOWN; |
2992 |
} else |
2993 |
*z = 0; |
2994 |
|
2995 |
return (0); |
2996 |
} |
2997 |
|
2998 |
static void |
2999 |
psmgestures(struct psm_softc *sc, finger_t *f, int nfingers, mousestatus_t *ms, |
3000 |
int *x, int *y) |
3001 |
{ |
3002 |
*x = *y = 0; |
3003 |
|
2824 |
/* |
3004 |
/* |
2825 |
* Check pressure to detect a real wanted action on the |
3005 |
* Check pressure to detect a real wanted action on the |
2826 |
* touchpad. |
3006 |
* touchpad. |
2827 |
*/ |
3007 |
*/ |
2828 |
if (*z >= sc->syninfo.min_pressure) { |
3008 |
if (f->p >= sc->syninfo.min_pressure) { |
2829 |
synapticsaction_t *synaction; |
3009 |
synapticsaction_t *synaction; |
|
|
3010 |
int x0, y0; |
2830 |
int cursor, peer, window; |
3011 |
int cursor, peer, window; |
2831 |
int dx, dy, dxp, dyp; |
3012 |
int dx, dy, dxp, dyp; |
2832 |
int max_width, max_pressure; |
3013 |
int max_width, max_pressure; |
Lines 2838-2846
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
2838 |
int div_min, div_max, div_len; |
3019 |
int div_min, div_max, div_len; |
2839 |
int vscroll_hor_area, vscroll_ver_area; |
3020 |
int vscroll_hor_area, vscroll_ver_area; |
2840 |
int two_finger_scroll; |
3021 |
int two_finger_scroll; |
|
|
3022 |
int max_x, max_y; |
2841 |
int len, weight_prev_x, weight_prev_y; |
3023 |
int len, weight_prev_x, weight_prev_y; |
2842 |
int div_max_x, div_max_y, div_x, div_y; |
3024 |
int div_max_x, div_max_y, div_x, div_y; |
2843 |
int exiting_scroll; |
3025 |
int is_fuzzy; |
2844 |
|
3026 |
|
2845 |
/* Read sysctl. */ |
3027 |
/* Read sysctl. */ |
2846 |
/* XXX Verify values? */ |
3028 |
/* XXX Verify values? */ |
Lines 2866-2904
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
2866 |
vscroll_hor_area = sc->syninfo.vscroll_hor_area; |
3048 |
vscroll_hor_area = sc->syninfo.vscroll_hor_area; |
2867 |
vscroll_ver_area = sc->syninfo.vscroll_ver_area; |
3049 |
vscroll_ver_area = sc->syninfo.vscroll_ver_area; |
2868 |
two_finger_scroll = sc->syninfo.two_finger_scroll; |
3050 |
two_finger_scroll = sc->syninfo.two_finger_scroll; |
|
|
3051 |
max_x = sc->synhw.maximumXCoord; |
3052 |
max_y = sc->synhw.maximumYCoord; |
2869 |
|
3053 |
|
2870 |
exiting_scroll = 0; |
3054 |
is_fuzzy = (f->flags & PSM_FINGER_FUZZY) != 0; |
2871 |
|
3055 |
|
2872 |
/* Palm detection. */ |
3056 |
/* Palm detection. */ |
2873 |
if (!( |
3057 |
if (!( |
2874 |
((sc->synhw.capMultiFinger || |
3058 |
((sc->synhw.capMultiFinger || |
2875 |
sc->synhw.capAdvancedGestures) && (w == 0 || w == 1)) || |
3059 |
sc->synhw.capAdvancedGestures) && nfingers > 1) || |
2876 |
(sc->synhw.capPalmDetect && w >= 4 && w <= max_width) || |
3060 |
(sc->synhw.capPalmDetect && f->w <= max_width) || |
2877 |
(!sc->synhw.capPalmDetect && *z <= max_pressure) || |
3061 |
(!sc->synhw.capPalmDetect && f->p <= max_pressure) || |
2878 |
(sc->synhw.capPen && w == 2))) { |
3062 |
(sc->synhw.capPen && f->flags & PSM_FINGER_IS_PEN) || |
|
|
3063 |
is_fuzzy)) { |
2879 |
/* |
3064 |
/* |
2880 |
* We consider the packet irrelevant for the current |
3065 |
* We consider the packet irrelevant for the current |
2881 |
* action when: |
3066 |
* action when: |
2882 |
* - the width isn't comprised in: |
3067 |
* - the width isn't comprised in: |
2883 |
* [4; max_width] |
3068 |
* [1; max_width] |
2884 |
* - the pressure isn't comprised in: |
3069 |
* - the pressure isn't comprised in: |
2885 |
* [min_pressure; max_pressure] |
3070 |
* [min_pressure; max_pressure] |
2886 |
* - pen aren't supported but w is 2 |
3071 |
* - pen aren't supported but PSM_FINGER_IS_PEN is set |
2887 |
* |
3072 |
* |
2888 |
* Note that this doesn't terminate the current action. |
3073 |
* Note that this doesn't terminate the current action. |
2889 |
*/ |
3074 |
*/ |
2890 |
VLOG(2, (LOG_DEBUG, |
3075 |
VLOG(2, (LOG_DEBUG, |
2891 |
"synaptics: palm detected! (%d)\n", w)); |
3076 |
"synaptics: palm detected! (%d)\n", f->w)); |
2892 |
goto SYNAPTICS_END; |
3077 |
return; |
2893 |
} |
3078 |
} |
2894 |
|
3079 |
|
2895 |
/* Read current absolute position. */ |
3080 |
/* Read current absolute position. */ |
2896 |
x0 = ((pb->ipacket[3] & 0x10) << 8) | |
3081 |
x0 = f->x; |
2897 |
((pb->ipacket[1] & 0x0f) << 8) | |
3082 |
y0 = f->y; |
2898 |
pb->ipacket[4]; |
3083 |
|
2899 |
y0 = ((pb->ipacket[3] & 0x20) << 7) | |
3084 |
/* |
2900 |
((pb->ipacket[1] & 0xf0) << 4) | |
3085 |
* Limit the coordinates to the specified margins because |
2901 |
pb->ipacket[5]; |
3086 |
* this area isn't very reliable. |
|
|
3087 |
*/ |
3088 |
if (x0 <= margin_left) |
3089 |
x0 = margin_left; |
3090 |
else if (x0 >= max_x - margin_right) |
3091 |
x0 = max_x - margin_right; |
3092 |
if (y0 <= margin_bottom) |
3093 |
y0 = margin_bottom; |
3094 |
else if (y0 >= max_y - margin_top) |
3095 |
y0 = max_y - margin_top; |
2902 |
|
3096 |
|
2903 |
synaction = &(sc->synaction); |
3097 |
synaction = &(sc->synaction); |
2904 |
|
3098 |
|
Lines 2958-2978
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
2958 |
* the current packet. |
3152 |
* the current packet. |
2959 |
*/ |
3153 |
*/ |
2960 |
|
3154 |
|
2961 |
/* |
|
|
2962 |
* Limit the coordinates to the specified margins because |
2963 |
* this area isn't very reliable. |
2964 |
*/ |
2965 |
if (x0 <= margin_left) |
2966 |
x0 = margin_left; |
2967 |
else if (x0 >= 6143 - margin_right) |
2968 |
x0 = 6143 - margin_right; |
2969 |
if (y0 <= margin_bottom) |
2970 |
y0 = margin_bottom; |
2971 |
else if (y0 >= 6143 - margin_top) |
2972 |
y0 = 6143 - margin_top; |
2973 |
|
2974 |
VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", |
3155 |
VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", |
2975 |
x0, y0, *z, w)); |
3156 |
x0, y0, f->p, f->w)); |
2976 |
|
3157 |
|
2977 |
/* Queue this new packet. */ |
3158 |
/* Queue this new packet. */ |
2978 |
cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1); |
3159 |
cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1); |
Lines 2990-3015
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
2990 |
* pressure peak. Also with multiple fingers, we increase |
3171 |
* pressure peak. Also with multiple fingers, we increase |
2991 |
* the minimum window. |
3172 |
* the minimum window. |
2992 |
*/ |
3173 |
*/ |
2993 |
switch (w) { |
3174 |
if (nfingers > 1) |
2994 |
case 1: /* Three or more fingers. */ |
|
|
2995 |
synaction->fingers_nb = imax(3, synaction->fingers_nb); |
2996 |
synaction->window_min = window_max; |
2997 |
break; |
2998 |
case 0: /* Two fingers. */ |
2999 |
synaction->fingers_nb = imax(2, synaction->fingers_nb); |
3000 |
synaction->window_min = window_max; |
3175 |
synaction->window_min = window_max; |
3001 |
break; |
3176 |
synaction->fingers_nb = imax(nfingers, synaction->fingers_nb); |
3002 |
default: /* One finger or undetectable. */ |
3177 |
sc->zmax = imax(f->p, sc->zmax); |
3003 |
synaction->fingers_nb = imax(1, synaction->fingers_nb); |
|
|
3004 |
} |
3005 |
sc->zmax = imax(*z, sc->zmax); |
3006 |
|
3178 |
|
3007 |
/* Do we have enough packets to consider this a movement? */ |
3179 |
/* Do we have enough packets to consider this a movement? */ |
3008 |
if (synaction->queue_len < synaction->window_min) |
3180 |
if (synaction->queue_len < synaction->window_min) |
3009 |
goto SYNAPTICS_END; |
3181 |
return; |
3010 |
|
3182 |
|
3011 |
/* Is a scrolling action occurring? */ |
3183 |
/* Is a scrolling action occurring? */ |
3012 |
if (!synaction->in_taphold && !synaction->in_vscroll) { |
3184 |
if (!synaction->in_taphold && !ms->button && |
|
|
3185 |
(!synaction->in_vscroll || two_finger_scroll)) { |
3013 |
/* |
3186 |
/* |
3014 |
* A scrolling action must not conflict with a tap |
3187 |
* A scrolling action must not conflict with a tap |
3015 |
* action. Here are the conditions to consider a |
3188 |
* action. Here are the conditions to consider a |
Lines 3034-3040
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3034 |
* as that keeps the maximum number of fingers. |
3207 |
* as that keeps the maximum number of fingers. |
3035 |
*/ |
3208 |
*/ |
3036 |
if (two_finger_scroll) { |
3209 |
if (two_finger_scroll) { |
3037 |
if (w == 0) { |
3210 |
if (nfingers == 2) { |
3038 |
synaction->in_vscroll += |
3211 |
synaction->in_vscroll += |
3039 |
dyp ? 2 : 0; |
3212 |
dyp ? 2 : 0; |
3040 |
synaction->in_vscroll += |
3213 |
synaction->in_vscroll += |
Lines 3047-3053
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3047 |
vscroll_hor_area) || |
3220 |
vscroll_hor_area) || |
3048 |
(vscroll_hor_area < 0 && |
3221 |
(vscroll_hor_area < 0 && |
3049 |
synaction->start_y >= |
3222 |
synaction->start_y >= |
3050 |
6143 + vscroll_hor_area)) |
3223 |
max_y + vscroll_hor_area)) |
3051 |
synaction->in_vscroll += 2; |
3224 |
synaction->in_vscroll += 2; |
3052 |
|
3225 |
|
3053 |
/* Check for vertical scrolling. */ |
3226 |
/* Check for vertical scrolling. */ |
Lines 3056-3062
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3056 |
vscroll_ver_area) || |
3229 |
vscroll_ver_area) || |
3057 |
(vscroll_ver_area < 0 && |
3230 |
(vscroll_ver_area < 0 && |
3058 |
synaction->start_x >= |
3231 |
synaction->start_x >= |
3059 |
6143 + vscroll_ver_area)) |
3232 |
max_x + vscroll_ver_area)) |
3060 |
synaction->in_vscroll += 1; |
3233 |
synaction->in_vscroll += 1; |
3061 |
} |
3234 |
} |
3062 |
|
3235 |
|
Lines 3068-3079
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3068 |
} |
3241 |
} |
3069 |
/* |
3242 |
/* |
3070 |
* Reset two finger scrolling when the number of fingers |
3243 |
* Reset two finger scrolling when the number of fingers |
3071 |
* is different from two. |
3244 |
* is different from two or any button is pressed. |
3072 |
*/ |
3245 |
*/ |
3073 |
if (two_finger_scroll && w != 0 && synaction->in_vscroll != 0) { |
3246 |
if (two_finger_scroll && (nfingers != 2 || ms->button) && |
|
|
3247 |
synaction->in_vscroll != 0) |
3074 |
synaction->in_vscroll = 0; |
3248 |
synaction->in_vscroll = 0; |
3075 |
exiting_scroll = 1; |
|
|
3076 |
} |
3077 |
|
3249 |
|
3078 |
VLOG(5, (LOG_DEBUG, |
3250 |
VLOG(5, (LOG_DEBUG, |
3079 |
"synaptics: virtual scrolling: %s " |
3251 |
"synaptics: virtual scrolling: %s " |
Lines 3096-3107
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3096 |
* using this area, we apply a special weight and |
3268 |
* using this area, we apply a special weight and |
3097 |
* div. |
3269 |
* div. |
3098 |
*/ |
3270 |
*/ |
3099 |
if (x0 <= na_left || x0 >= 6143 - na_right) { |
3271 |
if (x0 <= na_left || x0 >= max_x - na_right) { |
3100 |
weight_prev_x = sc->syninfo.weight_previous_na; |
3272 |
weight_prev_x = sc->syninfo.weight_previous_na; |
3101 |
div_max_x = sc->syninfo.div_max_na; |
3273 |
div_max_x = sc->syninfo.div_max_na; |
3102 |
} |
3274 |
} |
3103 |
|
3275 |
|
3104 |
if (y0 <= na_bottom || y0 >= 6143 - na_top) { |
3276 |
if (y0 <= na_bottom || y0 >= max_y - na_top) { |
3105 |
weight_prev_y = sc->syninfo.weight_previous_na; |
3277 |
weight_prev_y = sc->syninfo.weight_previous_na; |
3106 |
div_max_y = sc->syninfo.div_max_na; |
3278 |
div_max_y = sc->syninfo.div_max_na; |
3107 |
} |
3279 |
} |
Lines 3181-3193
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3181 |
/* The pointer is not moved. */ |
3353 |
/* The pointer is not moved. */ |
3182 |
*x = *y = 0; |
3354 |
*x = *y = 0; |
3183 |
} else { |
3355 |
} else { |
3184 |
/* On exit the x/y pos may jump, ignore this */ |
3356 |
/* On real<->fuzzy finger switch the x/y pos jumps */ |
3185 |
if (exiting_scroll) |
3357 |
if (is_fuzzy != synaction->is_fuzzy) |
3186 |
*x = *y = 0; |
3358 |
*x = *y = 0; |
3187 |
|
3359 |
|
3188 |
VLOG(3, (LOG_DEBUG, "synaptics: [%d, %d] -> [%d, %d]\n", |
3360 |
VLOG(3, (LOG_DEBUG, "synaptics: [%d, %d] -> [%d, %d]\n", |
3189 |
dx, dy, *x, *y)); |
3361 |
dx, dy, *x, *y)); |
3190 |
} |
3362 |
} |
|
|
3363 |
|
3364 |
synaction->is_fuzzy = is_fuzzy; |
3365 |
|
3191 |
} else if (sc->flags & PSM_FLAGS_FINGERDOWN) { |
3366 |
} else if (sc->flags & PSM_FLAGS_FINGERDOWN) { |
3192 |
/* |
3367 |
/* |
3193 |
* An action is currently taking place but the pressure |
3368 |
* An action is currently taking place but the pressure |
Lines 3247-3252
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3247 |
"synaptics: button RELEASE: %d\n", |
3422 |
"synaptics: button RELEASE: %d\n", |
3248 |
synaction->tap_button)); |
3423 |
synaction->tap_button)); |
3249 |
sc->flags |= PSM_FLAGS_FINGERDOWN; |
3424 |
sc->flags |= PSM_FLAGS_FINGERDOWN; |
|
|
3425 |
|
3426 |
/* Schedule button press on next interrupt */ |
3427 |
sc->idletimeout.tv_sec = psmhz > 1 ? |
3428 |
0 : 1; |
3429 |
sc->idletimeout.tv_usec = psmhz > 1 ? |
3430 |
1000000 / psmhz : 0; |
3250 |
} else { |
3431 |
} else { |
3251 |
/* |
3432 |
/* |
3252 |
* This is the first tap: we set the |
3433 |
* This is the first tap: we set the |
Lines 3259-3264
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3259 |
1000000; |
3440 |
1000000; |
3260 |
sc->taptimeout.tv_usec = taphold_timeout % |
3441 |
sc->taptimeout.tv_usec = taphold_timeout % |
3261 |
1000000; |
3442 |
1000000; |
|
|
3443 |
sc->idletimeout = sc->taptimeout; |
3262 |
timevaladd(&sc->taptimeout, &sc->lastsoftintr); |
3444 |
timevaladd(&sc->taptimeout, &sc->lastsoftintr); |
3263 |
|
3445 |
|
3264 |
switch (synaction->fingers_nb) { |
3446 |
switch (synaction->fingers_nb) { |
Lines 3311-3346
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3311 |
} |
3493 |
} |
3312 |
} |
3494 |
} |
3313 |
|
3495 |
|
3314 |
SYNAPTICS_END: |
3496 |
return; |
|
|
3497 |
} |
3498 |
|
3499 |
static int |
3500 |
psmsoftbuttons(struct psm_softc *sc, finger_t *f, int pressed) |
3501 |
{ |
3502 |
static int button = 0; |
3503 |
int y_ok, center_button, center_x, right_button, right_x; |
3504 |
|
3505 |
/* Dont change clickpad softbutton after pressing */ |
3506 |
if (pressed && !button) { |
3507 |
y_ok = sc->syninfo.softbuttons_y >= 0 ? |
3508 |
f->y < sc->syninfo.softbuttons_y : |
3509 |
f->y > sc->synhw.maximumYCoord - sc->syninfo.softbuttons_y; |
3510 |
|
3511 |
center_button = MOUSE_BUTTON2DOWN; |
3512 |
center_x = sc->syninfo.softbutton2_x; |
3513 |
right_button = MOUSE_BUTTON3DOWN; |
3514 |
right_x = sc->syninfo.softbutton3_x; |
3515 |
|
3516 |
if (center_x > 0 && right_x > 0 && center_x > right_x) { |
3517 |
center_button = MOUSE_BUTTON3DOWN; |
3518 |
center_x = sc->syninfo.softbutton3_x; |
3519 |
right_button = MOUSE_BUTTON2DOWN; |
3520 |
right_x = sc->syninfo.softbutton2_x; |
3521 |
} |
3522 |
|
3523 |
if (right_x > 0 && f->x > right_x && y_ok) |
3524 |
button = right_button; |
3525 |
else if (center_x > 0 && f->x > center_x && y_ok) |
3526 |
button = center_button; |
3527 |
else |
3528 |
button = MOUSE_BUTTON1DOWN; |
3529 |
VLOG(2, (LOG_DEBUG, "softbutton: PRESS: %d\n", button)); |
3530 |
} |
3531 |
|
3532 |
/* Clickpad releases */ |
3533 |
if (!pressed && button) { |
3534 |
VLOG(2, (LOG_DEBUG, "softbutton: RELEASE: %d\n", button)); |
3535 |
button = 0; |
3536 |
} |
3537 |
|
3538 |
return (button); |
3539 |
} |
3540 |
|
3541 |
static int |
3542 |
proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, |
3543 |
int *x, int *y, int *z) |
3544 |
{ |
3545 |
static int touchpad_button, trackpoint_button; |
3546 |
static int v4nfingers = 0; |
3547 |
finger_t fn, fgest, f[ELANTECH_MAX_FINGERS]; |
3548 |
int pkt, id, scale, i, nfingers; |
3549 |
|
3550 |
if (!elantech_support) |
3551 |
return (0); |
3552 |
|
3553 |
/* Determine packet format and do a sanity check for out of sync packets. */ |
3554 |
if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion)) |
3555 |
pkt = ELANTECH_PKT_NOP; |
3556 |
else if (ELANTECH_PKT_IS_TRACKPOINT(pb)) |
3557 |
pkt = ELANTECH_PKT_TRACKPOINT; |
3558 |
else |
3559 |
switch (sc->elanhw.hwversion) { |
3560 |
case 2: |
3561 |
if (!ELANTECH_PKT_IS_V2(pb)) |
3562 |
return (-1); |
3563 |
|
3564 |
pkt = (pb->ipacket[0] & 0xc0) == 0x80 ? |
3565 |
ELANTECH_PKT_V2_2FINGER : ELANTECH_PKT_V2_COMMON; |
3566 |
break; |
3567 |
case 3: |
3568 |
if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) && |
3569 |
!ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc)) |
3570 |
return (-1); |
3571 |
|
3572 |
pkt = ELANTECH_PKT_V3; |
3573 |
break; |
3574 |
case 4: |
3575 |
if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc)) |
3576 |
return (-1); |
3577 |
|
3578 |
switch (pb->ipacket[3] & 0x03) { |
3579 |
case 0x00: |
3580 |
pkt = ELANTECH_PKT_V4_STATUS; |
3581 |
break; |
3582 |
case 0x01: |
3583 |
pkt = ELANTECH_PKT_V4_HEAD; |
3584 |
break; |
3585 |
case 0x02: |
3586 |
pkt = ELANTECH_PKT_V4_MOTION; |
3587 |
break; |
3588 |
default: |
3589 |
return (-1); |
3590 |
} |
3591 |
break; |
3592 |
default: |
3593 |
return (-1); |
3594 |
} |
3595 |
|
3596 |
VLOG(5, (LOG_DEBUG, "elantech: ipacket format: %d\n", pkt)); |
3597 |
|
3598 |
for (id = 0; id < ELANTECH_MAX_FINGERS; id++) |
3599 |
PSM_FINGER_RESET(f[id]); |
3600 |
|
3601 |
*x = *y = *z = 0; |
3602 |
ms->button = ms->obutton; |
3603 |
|
3604 |
if (sc->syninfo.touchpad_off) |
3605 |
return (0); |
3606 |
|
3607 |
/* Common legend |
3608 |
* L: Left mouse button pressed |
3609 |
* R: Right mouse button pressed |
3610 |
* N: number of fingers on touchpad |
3611 |
* X: absolute x value (horizontal) |
3612 |
* Y: absolute y value (vertical) |
3613 |
* W; width of the finger touch |
3614 |
* P: pressure |
3615 |
*/ |
3616 |
switch (pkt) { |
3617 |
case ELANTECH_PKT_V2_COMMON: /* HW V2. One/Three finger touch */ |
3618 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3619 |
* ------------------------------------------- |
3620 |
* ipacket[0]: N1 N0 W3 W2 . . R L |
3621 |
* ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 |
3622 |
* ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 |
3623 |
* ipacket[3]: N4 VF W1 W0 . . . B2 |
3624 |
* ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 |
3625 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3626 |
* ------------------------------------------- |
3627 |
* N4: set if more than 3 fingers (only in 3 fingers mode) |
3628 |
* VF: a kind of flag? (only on EF123, 0 when finger |
3629 |
* is over one of the buttons, 1 otherwise) |
3630 |
* B2: (on EF113 only, 0 otherwise), one button pressed |
3631 |
* P & W is not reported on EF113 touchpads |
3632 |
*/ |
3633 |
nfingers = (pb->ipacket[0] & 0xc0) >> 6; |
3634 |
|
3635 |
fn = ELANTECH_FINGER_SET_XYP(pb); |
3636 |
if (sc->elanhw.haspressure) { |
3637 |
fn.w = ((pb->ipacket[0] & 0x30) >> 2) | |
3638 |
((pb->ipacket[3] & 0x30) >> 4); |
3639 |
} else { |
3640 |
fn.p = ELANTECH_FINGER_DEFAULT_P; |
3641 |
fn.w = ELANTECH_FINGER_DEFAULT_W; |
3642 |
} |
3643 |
|
3644 |
/* |
3645 |
* HW v2 dont report exact finger positions when 3 or more |
3646 |
* fingers are on touchpad. Use reported value as fingers |
3647 |
* position as it is required for tap detection |
3648 |
*/ |
3649 |
if (nfingers > 2) { |
3650 |
if (pb->ipacket[3] & 0x80) |
3651 |
nfingers = 4; |
3652 |
fn.flags = PSM_FINGER_FUZZY; |
3653 |
} |
3654 |
|
3655 |
for (id = 0; id < imin(nfingers, ELANTECH_MAX_FINGERS); id++) |
3656 |
f[id] = fn; |
3657 |
break; |
3658 |
|
3659 |
case ELANTECH_PKT_V2_2FINGER: /*HW V2. Two finger touch */ |
3660 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3661 |
* ------------------------------------------- |
3662 |
* ipacket[0]: N1 N0 AY8 AX8 . . R L |
3663 |
* ipacket[1]: AX7 AX6 AX5 AX4 AX3 AX2 AX1 AX0 |
3664 |
* ipacket[2]: AY7 AY6 AY5 AY4 AY3 AY2 AY1 AY0 |
3665 |
* ipacket[3]: . . BY8 BX8 . . . . |
3666 |
* ipacket[4]: BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0 |
3667 |
* ipacket[5]: BY7 BY6 BY5 BY4 BY3 BY2 BY1 BY0 |
3668 |
* ------------------------------------------- |
3669 |
* AX: lower-left finger absolute x value |
3670 |
* AY: lower-left finger absolute y value |
3671 |
* BX: upper-right finger absolute x value |
3672 |
* BY: upper-right finger absolute y value |
3673 |
*/ |
3674 |
nfingers = 2; |
3675 |
|
3676 |
for (id = 0; id < imin(2, ELANTECH_MAX_FINGERS); id ++) |
3677 |
f[id] = (finger_t) { |
3678 |
.x = (((pb->ipacket[id * 3] & 0x10) << 4) | |
3679 |
pb->ipacket[id * 3 + 1]) << 2, |
3680 |
.y = (((pb->ipacket[id * 3] & 0x20) << 3) | |
3681 |
pb->ipacket[id * 3 + 2]) << 2, |
3682 |
.p = ELANTECH_FINGER_DEFAULT_P, |
3683 |
.w = ELANTECH_FINGER_DEFAULT_W, |
3684 |
/* HW ver.2 sends bounding box */ |
3685 |
.flags = PSM_FINGER_FUZZY |
3686 |
}; |
3687 |
break; |
3688 |
|
3689 |
case ELANTECH_PKT_V3: /* HW Version 3 */ |
3690 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3691 |
* ------------------------------------------- |
3692 |
* ipacket[0]: N1 N0 W3 W2 0 1 R L |
3693 |
* ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 |
3694 |
* ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 |
3695 |
* ipacket[3]: 0 0 W1 W0 0 0 1 0 |
3696 |
* ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 |
3697 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3698 |
* ------------------------------------------- |
3699 |
*/ |
3700 |
nfingers = (pb->ipacket[0] & 0xc0) >> 6; |
3701 |
id = nfingers - 1; |
3702 |
|
3703 |
fn = ELANTECH_FINGER_SET_XYP(pb); |
3704 |
fn.w = ((pb->ipacket[0] & 0x30) >> 2) | |
3705 |
((pb->ipacket[3] & 0x30) >> 4); |
3706 |
|
3707 |
/* |
3708 |
* HW v3 dont report exact finger positions when 3 or more |
3709 |
* fingers are on touchpad. Use reported value as fingers |
3710 |
* position as it is required for tap detection |
3711 |
*/ |
3712 |
if (nfingers > 2) |
3713 |
fn.flags = PSM_FINGER_FUZZY; |
3714 |
|
3715 |
for (id = 0; id < imin(nfingers, ELANTECH_MAX_FINGERS); id++) |
3716 |
f[id] = fn; |
3717 |
|
3718 |
if (nfingers == 2) { |
3719 |
if (ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc)) { |
3720 |
sc->elanaction.fingers[0] = fn; |
3721 |
return (0); |
3722 |
} else |
3723 |
f[0] = sc->elanaction.fingers[0]; |
3724 |
} |
3725 |
break; |
3726 |
|
3727 |
case ELANTECH_PKT_V4_STATUS: /* HW Version 4. Status packet */ |
3728 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3729 |
* ------------------------------------------- |
3730 |
* ipacket[0]: . . . . 0 1 R L |
3731 |
* ipacket[1]: . . . F4 F3 F2 F1 F0 |
3732 |
* ipacket[2]: . . . . . . . . |
3733 |
* ipacket[3]: . . . 1 0 0 0 0 |
3734 |
* ipacket[4]: PL . . . . . . . |
3735 |
* ipacket[5]: . . . . . . . . |
3736 |
* ------------------------------------------- |
3737 |
* Fn: finger n is on touchpad |
3738 |
* PL: palm |
3739 |
* HV ver4 sends a status packet to indicate that the numbers |
3740 |
* or identities of the fingers has been changed |
3741 |
*/ |
3742 |
|
3743 |
v4nfingers = fls(pb->ipacket[1] & 0x1f); |
3744 |
|
3745 |
if (v4nfingers > sc->elanaction.nfingers) |
3746 |
return (0); |
3747 |
|
3748 |
nfingers = v4nfingers; |
3749 |
|
3750 |
break; |
3751 |
|
3752 |
case ELANTECH_PKT_V4_HEAD: /* HW Version 4. Head packet */ |
3753 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3754 |
* ------------------------------------------- |
3755 |
* ipacket[0]: W3 W2 W1 W0 0 1 R L |
3756 |
* ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 |
3757 |
* ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 |
3758 |
* ipacket[3]: ID2 ID1 ID0 1 0 0 0 1 |
3759 |
* ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 |
3760 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3761 |
* ------------------------------------------- |
3762 |
* ID: finger id |
3763 |
* HW ver 4 sends head packets in two cases: |
3764 |
* 1. One finger touch and movement. |
3765 |
* 2. Next after status packet to tell new finger positions. |
3766 |
*/ |
3767 |
nfingers = v4nfingers; |
3768 |
id = ((pb->ipacket[3] & 0xe0) >> 5) - 1; |
3769 |
|
3770 |
if (id >= 0 && id < ELANTECH_MAX_FINGERS) { |
3771 |
f[id] = ELANTECH_FINGER_SET_XYP(pb); |
3772 |
f[id].w = (pb->ipacket[0] & 0xf0) >> 4; |
3773 |
} |
3774 |
break; |
3775 |
|
3776 |
case ELANTECH_PKT_V4_MOTION: /* HW Version 4. Motion packet */ |
3777 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3778 |
* ------------------------------------------- |
3779 |
* ipacket[0]: ID2 ID1 ID0 OF 0 1 R L |
3780 |
* ipacket[1]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 |
3781 |
* ipacket[2]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 |
3782 |
* ipacket[3]: ID2 ID1 ID0 1 0 0 1 0 |
3783 |
* ipacket[4]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 |
3784 |
* ipacket[5]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 |
3785 |
* ------------------------------------------- |
3786 |
* OF: delta overflows (> 127 or < -128), in this case |
3787 |
* firmware sends us (delta x / 5) and (delta y / 5) |
3788 |
* ID: finger id |
3789 |
* DX: delta x (two's complement) |
3790 |
* XY: delta y (two's complement) |
3791 |
* byte 0 ~ 2 for one finger |
3792 |
* byte 3 ~ 5 for another finger |
3793 |
*/ |
3794 |
nfingers = v4nfingers; |
3795 |
|
3796 |
scale = (pb->ipacket[0] & 0x10) ? 5 : 1; |
3797 |
for (i = 0; i <= 3; i += 3) { |
3798 |
id = ((pb->ipacket[i] & 0xe0) >> 5) - 1; |
3799 |
if (id < 0 || id >= ELANTECH_MAX_FINGERS) |
3800 |
continue; |
3801 |
|
3802 |
if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) { |
3803 |
f[id] = sc->elanaction.fingers[id]; |
3804 |
f[id].x += imax(-f[id].x, |
3805 |
(signed char)pb->ipacket[i+1] * scale); |
3806 |
f[id].y += imax(-f[id].y, |
3807 |
(signed char)pb->ipacket[i+2] * scale); |
3808 |
} else { |
3809 |
VLOG(3, (LOG_DEBUG, "elantech: " |
3810 |
"HW v4 motion packet skipped\n")); |
3811 |
} |
3812 |
} |
3813 |
|
3814 |
break; |
3815 |
|
3816 |
case ELANTECH_PKT_TRACKPOINT: |
3817 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3818 |
* ------------------------------------------- |
3819 |
* ipacket[0]: 0 0 SX SY 0 M R L |
3820 |
* ipacket[1]: ~SX 0 0 0 0 0 0 0 |
3821 |
* ipacket[2]: ~SY 0 0 0 0 0 0 0 |
3822 |
* ipacket[3]: 0 0 ~SY ~SX 0 1 1 0 |
3823 |
* ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 |
3824 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3825 |
* ------------------------------------------- |
3826 |
* X and Y are written in two's complement spread |
3827 |
* over 9 bits with SX/SY the relative top bit and |
3828 |
* X7..X0 and Y7..Y0 the lower bits. |
3829 |
*/ |
3830 |
*x = (pb->ipacket[0] & 0x20) ? |
3831 |
pb->ipacket[4] - 256 : pb->ipacket[4]; |
3832 |
*y = (pb->ipacket[0] & 0x10) ? |
3833 |
pb->ipacket[5] - 256 : pb->ipacket[5]; |
3834 |
|
3835 |
trackpoint_button = |
3836 |
((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | |
3837 |
((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | |
3838 |
((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); |
3839 |
|
3840 |
ms->button = touchpad_button | trackpoint_button; |
3841 |
return (0); |
3842 |
|
3843 |
case ELANTECH_PKT_NOP: |
3844 |
return (0); |
3845 |
|
3846 |
default: |
3847 |
return (-1); |
3848 |
} |
3849 |
|
3850 |
for (id = 0; id < ELANTECH_MAX_FINGERS; id++) |
3851 |
if (PSM_FINGER_IS_SET(f[id])) |
3852 |
VLOG(2, (LOG_DEBUG, "elantech: " |
3853 |
"finger %d: down [%d, %d], %d, %d, %d\n", id + 1, |
3854 |
f[id].x, f[id].y, f[id].p, f[id].w, f[id].flags)); |
3855 |
|
3856 |
/* Touchpad button presses */ |
3857 |
if (sc->elanhw.isclickpad) { |
3858 |
touchpad_button = |
3859 |
psmsoftbuttons(sc, &f[0], pb->ipacket[0] & 0x03); |
3860 |
} else { |
3861 |
touchpad_button = |
3862 |
((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | |
3863 |
((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); |
3864 |
} |
3865 |
|
3866 |
ms->button = touchpad_button | trackpoint_button; |
3867 |
|
3315 |
/* |
3868 |
/* |
3316 |
* Use the extra buttons as a scrollwheel |
3869 |
* Use 2-nd finger positon for gesture processing on 2 finger actions |
3317 |
* |
3870 |
* so "click with first and drag with second finger" gesture can be |
3318 |
* XXX X.Org uses the Z axis for vertical wheel only, |
3871 |
* used on clickpads. Set FUZZY flag to avoid cursor jump on second |
3319 |
* whereas moused(8) understands special values to differ |
3872 |
* finger touch and release events. |
3320 |
* vertical and horizontal wheels. |
|
|
3321 |
* |
3322 |
* xf86-input-mouse needs therefore a small patch to |
3323 |
* understand these special values. Without it, the |
3324 |
* horizontal wheel acts as a vertical wheel in X.Org. |
3325 |
* |
3326 |
* That's why the horizontal wheel is disabled by |
3327 |
* default for now. |
3328 |
*/ |
3873 |
*/ |
|
|
3874 |
if (nfingers == 2) { |
3875 |
fgest = f[1]; |
3876 |
fgest.flags = PSM_FINGER_FUZZY; |
3877 |
} else { |
3878 |
fgest = f[0]; |
3879 |
} |
3329 |
|
3880 |
|
3330 |
if (ms->button & MOUSE_BUTTON4DOWN) { |
3881 |
/* Send gesture finger position to movement smoother */ |
|
|
3882 |
if (PSM_FINGER_IS_SET(f[0]) || nfingers == 0) |
3883 |
psmgestures(sc, &fgest, imin(nfingers, 3), ms, x, y); |
3884 |
|
3885 |
/* Store current finger positions in action context */ |
3886 |
sc->elanaction.nfingers = nfingers; |
3887 |
for (id = 0; id < ELANTECH_MAX_FINGERS; id++) { |
3888 |
if (PSM_FINGER_IS_SET(f[id])) |
3889 |
sc->elanaction.fingers[id] = f[id]; |
3890 |
if (id >= nfingers) |
3891 |
PSM_FINGER_RESET(sc->elanaction.fingers[id]); |
3892 |
} |
3893 |
|
3894 |
/* Use the extra buttons as a scrollwheel */ |
3895 |
if (ms->button & MOUSE_BUTTON4DOWN) |
3331 |
*z = -1; |
3896 |
*z = -1; |
3332 |
ms->button &= ~MOUSE_BUTTON4DOWN; |
3897 |
else if (ms->button & MOUSE_BUTTON5DOWN) |
3333 |
} else if (ms->button & MOUSE_BUTTON5DOWN) { |
|
|
3334 |
*z = 1; |
3898 |
*z = 1; |
3335 |
ms->button &= ~MOUSE_BUTTON5DOWN; |
3899 |
else if (ms->button & MOUSE_BUTTON6DOWN) |
3336 |
} else if (ms->button & MOUSE_BUTTON6DOWN) { |
|
|
3337 |
*z = -2; |
3900 |
*z = -2; |
3338 |
ms->button &= ~MOUSE_BUTTON6DOWN; |
3901 |
else if (ms->button & MOUSE_BUTTON7DOWN) |
3339 |
} else if (ms->button & MOUSE_BUTTON7DOWN) { |
|
|
3340 |
*z = 2; |
3902 |
*z = 2; |
3341 |
ms->button &= ~MOUSE_BUTTON7DOWN; |
3903 |
else |
3342 |
} else |
|
|
3343 |
*z = 0; |
3904 |
*z = 0; |
|
|
3905 |
ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN | |
3906 |
MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN); |
3344 |
|
3907 |
|
3345 |
return (0); |
3908 |
return (0); |
3346 |
} |
3909 |
} |
Lines 3413-3418
proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3413 |
} |
3976 |
} |
3414 |
|
3977 |
|
3415 |
static void |
3978 |
static void |
|
|
3979 |
psmsoftintridle(void *arg) |
3980 |
{ |
3981 |
struct psm_softc *sc = arg; |
3982 |
packetbuf_t *pb; |
3983 |
|
3984 |
/* Invoke soft handler only when pqueue is empty. Otherwise it will be |
3985 |
* invoked from psmintr soon with pqueue filled with real data */ |
3986 |
if (sc->pqueue_start == sc->pqueue_end && |
3987 |
sc->idlepacket.inputbytes > 0) { |
3988 |
/* Grow circular queue backwards to avoid race with psmintr */ |
3989 |
if (--sc->pqueue_start < 0) |
3990 |
sc->pqueue_start = PSM_PACKETQUEUE - 1; |
3991 |
|
3992 |
pb = &sc->pqueue[sc->pqueue_start]; |
3993 |
memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t)); |
3994 |
VLOG(4, (LOG_DEBUG, |
3995 |
"psmsoftintridle: %02x %02x %02x %02x %02x %02x\n", |
3996 |
pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], |
3997 |
pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); |
3998 |
|
3999 |
psmsoftintr(arg); |
4000 |
} |
4001 |
} |
4002 |
|
4003 |
static void |
3416 |
psmsoftintr(void *arg) |
4004 |
psmsoftintr(void *arg) |
3417 |
{ |
4005 |
{ |
3418 |
/* |
4006 |
/* |
Lines 3465-3470
psmsoftintr(void *arg)
Link Here
|
3465 |
if (sc->config & PSM_CONFIG_FORCETAP) |
4053 |
if (sc->config & PSM_CONFIG_FORCETAP) |
3466 |
ms.button |= ((c & MOUSE_PS2_TAP)) ? |
4054 |
ms.button |= ((c & MOUSE_PS2_TAP)) ? |
3467 |
0 : MOUSE_BUTTON4DOWN; |
4055 |
0 : MOUSE_BUTTON4DOWN; |
|
|
4056 |
timevalclear(&sc->idletimeout); |
4057 |
sc->idlepacket.inputbytes = 0; |
3468 |
|
4058 |
|
3469 |
switch (sc->hw.model) { |
4059 |
switch (sc->hw.model) { |
3470 |
|
4060 |
|
Lines 3603-3608
psmsoftintr(void *arg)
Link Here
|
3603 |
goto next; |
4193 |
goto next; |
3604 |
break; |
4194 |
break; |
3605 |
|
4195 |
|
|
|
4196 |
case MOUSE_MODEL_ELANTECH: |
4197 |
if (proc_elantech(sc, pb, &ms, &x, &y, &z) != 0) |
4198 |
goto next; |
4199 |
break; |
4200 |
|
3606 |
case MOUSE_MODEL_TRACKPOINT: |
4201 |
case MOUSE_MODEL_TRACKPOINT: |
3607 |
case MOUSE_MODEL_GENERIC: |
4202 |
case MOUSE_MODEL_GENERIC: |
3608 |
default: |
4203 |
default: |
Lines 3627-3632
psmsoftintr(void *arg)
Link Here
|
3627 |
} |
4222 |
} |
3628 |
} |
4223 |
} |
3629 |
|
4224 |
|
|
|
4225 |
/* Store last packet for reinjection if it has not been set already */ |
4226 |
if (timevalisset(&sc->idletimeout) && sc->idlepacket.inputbytes == 0) |
4227 |
sc->idlepacket = *pb; |
4228 |
|
3630 |
ms.dx = x; |
4229 |
ms.dx = x; |
3631 |
ms.dy = y; |
4230 |
ms.dy = y; |
3632 |
ms.dz = z; |
4231 |
ms.dz = z; |
Lines 3673-3678
next:
Link Here
|
3673 |
pgsigio(&sc->async, SIGIO, 0); |
4272 |
pgsigio(&sc->async, SIGIO, 0); |
3674 |
} |
4273 |
} |
3675 |
sc->state &= ~PSM_SOFTARMED; |
4274 |
sc->state &= ~PSM_SOFTARMED; |
|
|
4275 |
|
4276 |
/* schedule injection of predefined packet after idletimeout |
4277 |
* if no data packets have been received from psmintr */ |
4278 |
if (timevalisset(&sc->idletimeout)) { |
4279 |
sc->state |= PSM_SOFTARMED; |
4280 |
callout_reset(&sc->softcallout, tvtohz(&sc->idletimeout), |
4281 |
psmsoftintridle, sc); |
4282 |
VLOG(2, (LOG_DEBUG, "softintr: callout set: %d ticks\n", |
4283 |
tvtohz(&sc->idletimeout))); |
4284 |
} |
3676 |
splx(s); |
4285 |
splx(s); |
3677 |
} |
4286 |
} |
3678 |
|
4287 |
|
Lines 4106-4115
enable_4dplus(struct psm_softc *sc, enum probearg arg)
Link Here
|
4106 |
static int |
4715 |
static int |
4107 |
synaptics_sysctl(SYSCTL_HANDLER_ARGS) |
4716 |
synaptics_sysctl(SYSCTL_HANDLER_ARGS) |
4108 |
{ |
4717 |
{ |
|
|
4718 |
struct psm_softc *sc; |
4109 |
int error, arg; |
4719 |
int error, arg; |
4110 |
|
4720 |
|
|
|
4721 |
if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || |
4722 |
oidp->oid_arg2 > SYNAPTICS_SYSCTL_SOFTBUTTON3_X) |
4723 |
return (EINVAL); |
4724 |
|
4725 |
sc = oidp->oid_arg1; |
4726 |
|
4111 |
/* Read the current value. */ |
4727 |
/* Read the current value. */ |
4112 |
arg = *(int *)oidp->oid_arg1; |
4728 |
arg = *(int *)((char *)sc + oidp->oid_arg2); |
4113 |
error = sysctl_handle_int(oidp, &arg, 0, req); |
4729 |
error = sysctl_handle_int(oidp, &arg, 0, req); |
4114 |
|
4730 |
|
4115 |
/* Sanity check. */ |
4731 |
/* Sanity check. */ |
Lines 4131-4144
synaptics_sysctl(SYSCTL_HANDLER_ARGS)
Link Here
|
4131 |
return (EINVAL); |
4747 |
return (EINVAL); |
4132 |
break; |
4748 |
break; |
4133 |
case SYNAPTICS_SYSCTL_MARGIN_TOP: |
4749 |
case SYNAPTICS_SYSCTL_MARGIN_TOP: |
4134 |
case SYNAPTICS_SYSCTL_MARGIN_RIGHT: |
|
|
4135 |
case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: |
4750 |
case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: |
4136 |
case SYNAPTICS_SYSCTL_MARGIN_LEFT: |
|
|
4137 |
case SYNAPTICS_SYSCTL_NA_TOP: |
4751 |
case SYNAPTICS_SYSCTL_NA_TOP: |
4138 |
case SYNAPTICS_SYSCTL_NA_RIGHT: |
|
|
4139 |
case SYNAPTICS_SYSCTL_NA_BOTTOM: |
4752 |
case SYNAPTICS_SYSCTL_NA_BOTTOM: |
|
|
4753 |
if (arg < 0 || arg > sc->synhw.maximumYCoord) |
4754 |
return (EINVAL); |
4755 |
break; |
4756 |
case SYNAPTICS_SYSCTL_SOFTBUTTON2_X: |
4757 |
case SYNAPTICS_SYSCTL_SOFTBUTTON3_X: |
4758 |
/* Softbuttons is clickpad only feature */ |
4759 |
if (!sc->synhw.capClickPad && arg != 0) |
4760 |
return (EINVAL); |
4761 |
/* FALLTHROUGH */ |
4762 |
case SYNAPTICS_SYSCTL_MARGIN_RIGHT: |
4763 |
case SYNAPTICS_SYSCTL_MARGIN_LEFT: |
4764 |
case SYNAPTICS_SYSCTL_NA_RIGHT: |
4140 |
case SYNAPTICS_SYSCTL_NA_LEFT: |
4765 |
case SYNAPTICS_SYSCTL_NA_LEFT: |
4141 |
if (arg < 0 || arg > 6143) |
4766 |
if (arg < 0 || arg > sc->synhw.maximumXCoord) |
4142 |
return (EINVAL); |
4767 |
return (EINVAL); |
4143 |
break; |
4768 |
break; |
4144 |
case SYNAPTICS_SYSCTL_WINDOW_MIN: |
4769 |
case SYNAPTICS_SYSCTL_WINDOW_MIN: |
Lines 4168-4175
synaptics_sysctl(SYSCTL_HANDLER_ARGS)
Link Here
|
4168 |
return (EINVAL); |
4793 |
return (EINVAL); |
4169 |
break; |
4794 |
break; |
4170 |
case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: |
4795 |
case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: |
|
|
4796 |
if (arg < -sc->synhw.maximumXCoord || |
4797 |
arg > sc->synhw.maximumXCoord) |
4798 |
return (EINVAL); |
4799 |
break; |
4800 |
case SYNAPTICS_SYSCTL_SOFTBUTTONS_Y: |
4801 |
/* Softbuttons is clickpad only feature */ |
4802 |
if (!sc->synhw.capClickPad && arg != 0) |
4803 |
return (EINVAL); |
4804 |
/* FALLTHROUGH */ |
4171 |
case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: |
4805 |
case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: |
4172 |
if (arg < -6143 || arg > 6143) |
4806 |
if (arg < -sc->synhw.maximumYCoord || |
|
|
4807 |
arg > sc->synhw.maximumYCoord) |
4173 |
return (EINVAL); |
4808 |
return (EINVAL); |
4174 |
break; |
4809 |
break; |
4175 |
case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: |
4810 |
case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: |
Lines 4181-4193
synaptics_sysctl(SYSCTL_HANDLER_ARGS)
Link Here
|
4181 |
} |
4816 |
} |
4182 |
|
4817 |
|
4183 |
/* Update. */ |
4818 |
/* Update. */ |
4184 |
*(int *)oidp->oid_arg1 = arg; |
4819 |
*(int *)((char *)sc + oidp->oid_arg2) = arg; |
4185 |
|
4820 |
|
4186 |
return (error); |
4821 |
return (error); |
4187 |
} |
4822 |
} |
4188 |
|
4823 |
|
4189 |
static void |
4824 |
static void |
4190 |
synaptics_sysctl_create_tree(struct psm_softc *sc) |
4825 |
synaptics_sysctl_create_softbuttons_tree(struct psm_softc *sc) |
|
|
4826 |
{ |
4827 |
/* |
4828 |
* Set predefined sizes for softbuttons. |
4829 |
* Values are taken to match HP Pavilion dv6 clickpad drawings |
4830 |
* with right button divided on middle and right softbuttons |
4831 |
*/ |
4832 |
|
4833 |
/* hw.psm.synaptics.softbuttons_y */ |
4834 |
sc->syninfo.softbuttons_y = 1700; |
4835 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4836 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4837 |
"softbuttons_y", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4838 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTONS_Y, |
4839 |
synaptics_sysctl, "I", |
4840 |
"Vertical size of softbuttons area"); |
4841 |
|
4842 |
/* hw.psm.synaptics.softbutton2_x */ |
4843 |
sc->syninfo.softbutton2_x = 3600; |
4844 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4845 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4846 |
"softbutton2_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4847 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTON2_X, |
4848 |
synaptics_sysctl, "I", |
4849 |
"Horisontal position of 2-nd softbutton left edge (0-disable)"); |
4850 |
|
4851 |
/* hw.psm.synaptics.softbutton3_x */ |
4852 |
sc->syninfo.softbutton3_x = 4700; |
4853 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4854 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4855 |
"softbutton3_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4856 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTON3_X, |
4857 |
synaptics_sysctl, "I", |
4858 |
"Horisontal position of 3-rd softbutton left edge (0-disable)"); |
4859 |
} |
4860 |
|
4861 |
static void |
4862 |
synaptics_sysctl_create_tree(struct psm_softc *sc, const char *name, |
4863 |
const char *descr) |
4191 |
{ |
4864 |
{ |
4192 |
|
4865 |
|
4193 |
if (sc->syninfo.sysctl_tree != NULL) |
4866 |
if (sc->syninfo.sysctl_tree != NULL) |
Lines 4196-4203
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4196 |
/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ |
4869 |
/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ |
4197 |
sysctl_ctx_init(&sc->syninfo.sysctl_ctx); |
4870 |
sysctl_ctx_init(&sc->syninfo.sysctl_ctx); |
4198 |
sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, |
4871 |
sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, |
4199 |
SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "synaptics", CTLFLAG_RD, |
4872 |
SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, name, CTLFLAG_RD, |
4200 |
0, "Synaptics TouchPad"); |
4873 |
0, descr); |
4201 |
|
4874 |
|
4202 |
/* hw.psm.synaptics.directional_scrolls. */ |
4875 |
/* hw.psm.synaptics.directional_scrolls. */ |
4203 |
sc->syninfo.directional_scrolls = 0; |
4876 |
sc->syninfo.directional_scrolls = 0; |
Lines 4230-4236
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4230 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4903 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4231 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4904 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4232 |
"min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4905 |
"min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4233 |
&sc->syninfo.min_pressure, SYNAPTICS_SYSCTL_MIN_PRESSURE, |
4906 |
sc, SYNAPTICS_SYSCTL_MIN_PRESSURE, |
4234 |
synaptics_sysctl, "I", |
4907 |
synaptics_sysctl, "I", |
4235 |
"Minimum pressure required to start an action"); |
4908 |
"Minimum pressure required to start an action"); |
4236 |
|
4909 |
|
Lines 4239-4245
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4239 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4912 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4240 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4913 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4241 |
"max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4914 |
"max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4242 |
&sc->syninfo.max_pressure, SYNAPTICS_SYSCTL_MAX_PRESSURE, |
4915 |
sc, SYNAPTICS_SYSCTL_MAX_PRESSURE, |
4243 |
synaptics_sysctl, "I", |
4916 |
synaptics_sysctl, "I", |
4244 |
"Maximum pressure to detect palm"); |
4917 |
"Maximum pressure to detect palm"); |
4245 |
|
4918 |
|
Lines 4248-4272
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4248 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4921 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4249 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4922 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4250 |
"max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4923 |
"max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4251 |
&sc->syninfo.max_width, SYNAPTICS_SYSCTL_MAX_WIDTH, |
4924 |
sc, SYNAPTICS_SYSCTL_MAX_WIDTH, |
4252 |
synaptics_sysctl, "I", |
4925 |
synaptics_sysctl, "I", |
4253 |
"Maximum finger width to detect palm"); |
4926 |
"Maximum finger width to detect palm"); |
4254 |
|
4927 |
|
4255 |
/* hw.psm.synaptics.top_margin. */ |
4928 |
/* hw.psm.synaptics.top_margin. */ |
4256 |
sc->syninfo.margin_top = 200; |
4929 |
sc->syninfo.margin_top = |
|
|
4930 |
imax(sc->synhw.maximumYCoord - 6143 + 200, 0); |
4257 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4931 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4258 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4932 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4259 |
"margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4933 |
"margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4260 |
&sc->syninfo.margin_top, SYNAPTICS_SYSCTL_MARGIN_TOP, |
4934 |
sc, SYNAPTICS_SYSCTL_MARGIN_TOP, |
4261 |
synaptics_sysctl, "I", |
4935 |
synaptics_sysctl, "I", |
4262 |
"Top margin"); |
4936 |
"Top margin"); |
4263 |
|
4937 |
|
4264 |
/* hw.psm.synaptics.right_margin. */ |
4938 |
/* hw.psm.synaptics.right_margin. */ |
4265 |
sc->syninfo.margin_right = 200; |
4939 |
sc->syninfo.margin_right = |
|
|
4940 |
imax(sc->synhw.maximumXCoord - 6143 + 200, 0); |
4266 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4941 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4267 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4942 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4268 |
"margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4943 |
"margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4269 |
&sc->syninfo.margin_right, SYNAPTICS_SYSCTL_MARGIN_RIGHT, |
4944 |
sc, SYNAPTICS_SYSCTL_MARGIN_RIGHT, |
4270 |
synaptics_sysctl, "I", |
4945 |
synaptics_sysctl, "I", |
4271 |
"Right margin"); |
4946 |
"Right margin"); |
4272 |
|
4947 |
|
Lines 4275-4281
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4275 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4950 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4276 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4951 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4277 |
"margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4952 |
"margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4278 |
&sc->syninfo.margin_bottom, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, |
4953 |
sc, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, |
4279 |
synaptics_sysctl, "I", |
4954 |
synaptics_sysctl, "I", |
4280 |
"Bottom margin"); |
4955 |
"Bottom margin"); |
4281 |
|
4956 |
|
Lines 4284-4309
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4284 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4959 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4285 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4960 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4286 |
"margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4961 |
"margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4287 |
&sc->syninfo.margin_left, SYNAPTICS_SYSCTL_MARGIN_LEFT, |
4962 |
sc, SYNAPTICS_SYSCTL_MARGIN_LEFT, |
4288 |
synaptics_sysctl, "I", |
4963 |
synaptics_sysctl, "I", |
4289 |
"Left margin"); |
4964 |
"Left margin"); |
4290 |
|
4965 |
|
4291 |
/* hw.psm.synaptics.na_top. */ |
4966 |
/* hw.psm.synaptics.na_top. */ |
4292 |
sc->syninfo.na_top = 1783; |
4967 |
sc->syninfo.na_top = imax(sc->synhw.maximumXCoord - 6143 + 1783, 0); |
4293 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4968 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4294 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4969 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4295 |
"na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4970 |
"na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4296 |
&sc->syninfo.na_top, SYNAPTICS_SYSCTL_NA_TOP, |
4971 |
sc, SYNAPTICS_SYSCTL_NA_TOP, |
4297 |
synaptics_sysctl, "I", |
4972 |
synaptics_sysctl, "I", |
4298 |
"Top noisy area, where weight_previous_na is used instead " |
4973 |
"Top noisy area, where weight_previous_na is used instead " |
4299 |
"of weight_previous"); |
4974 |
"of weight_previous"); |
4300 |
|
4975 |
|
4301 |
/* hw.psm.synaptics.na_right. */ |
4976 |
/* hw.psm.synaptics.na_right. */ |
4302 |
sc->syninfo.na_right = 563; |
4977 |
sc->syninfo.na_right = imax(sc->synhw.maximumYCoord - 6143 + 563, 0); |
4303 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4978 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4304 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4979 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4305 |
"na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4980 |
"na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4306 |
&sc->syninfo.na_right, SYNAPTICS_SYSCTL_NA_RIGHT, |
4981 |
sc, SYNAPTICS_SYSCTL_NA_RIGHT, |
4307 |
synaptics_sysctl, "I", |
4982 |
synaptics_sysctl, "I", |
4308 |
"Right noisy area, where weight_previous_na is used instead " |
4983 |
"Right noisy area, where weight_previous_na is used instead " |
4309 |
"of weight_previous"); |
4984 |
"of weight_previous"); |
Lines 4313-4319
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4313 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4988 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4314 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4989 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4315 |
"na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4990 |
"na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4316 |
&sc->syninfo.na_bottom, SYNAPTICS_SYSCTL_NA_BOTTOM, |
4991 |
sc, SYNAPTICS_SYSCTL_NA_BOTTOM, |
4317 |
synaptics_sysctl, "I", |
4992 |
synaptics_sysctl, "I", |
4318 |
"Bottom noisy area, where weight_previous_na is used instead " |
4993 |
"Bottom noisy area, where weight_previous_na is used instead " |
4319 |
"of weight_previous"); |
4994 |
"of weight_previous"); |
Lines 4323-4329
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4323 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4998 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4324 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4999 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4325 |
"na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5000 |
"na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4326 |
&sc->syninfo.na_left, SYNAPTICS_SYSCTL_NA_LEFT, |
5001 |
sc, SYNAPTICS_SYSCTL_NA_LEFT, |
4327 |
synaptics_sysctl, "I", |
5002 |
synaptics_sysctl, "I", |
4328 |
"Left noisy area, where weight_previous_na is used instead " |
5003 |
"Left noisy area, where weight_previous_na is used instead " |
4329 |
"of weight_previous"); |
5004 |
"of weight_previous"); |
Lines 4333-4339
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4333 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5008 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4334 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5009 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4335 |
"window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5010 |
"window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4336 |
&sc->syninfo.window_min, SYNAPTICS_SYSCTL_WINDOW_MIN, |
5011 |
sc, SYNAPTICS_SYSCTL_WINDOW_MIN, |
4337 |
synaptics_sysctl, "I", |
5012 |
synaptics_sysctl, "I", |
4338 |
"Minimum window size to start an action"); |
5013 |
"Minimum window size to start an action"); |
4339 |
|
5014 |
|
Lines 4342-4348
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4342 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5017 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4343 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5018 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4344 |
"window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5019 |
"window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4345 |
&sc->syninfo.window_max, SYNAPTICS_SYSCTL_WINDOW_MAX, |
5020 |
sc, SYNAPTICS_SYSCTL_WINDOW_MAX, |
4346 |
synaptics_sysctl, "I", |
5021 |
synaptics_sysctl, "I", |
4347 |
"Maximum window size"); |
5022 |
"Maximum window size"); |
4348 |
|
5023 |
|
Lines 4351-4357
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4351 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5026 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4352 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5027 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4353 |
"multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5028 |
"multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4354 |
&sc->syninfo.multiplicator, SYNAPTICS_SYSCTL_MULTIPLICATOR, |
5029 |
sc, SYNAPTICS_SYSCTL_MULTIPLICATOR, |
4355 |
synaptics_sysctl, "I", |
5030 |
synaptics_sysctl, "I", |
4356 |
"Multiplicator to increase precision in averages and divisions"); |
5031 |
"Multiplicator to increase precision in averages and divisions"); |
4357 |
|
5032 |
|
Lines 4360-4366
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4360 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5035 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4361 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5036 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4362 |
"weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5037 |
"weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4363 |
&sc->syninfo.weight_current, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, |
5038 |
sc, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, |
4364 |
synaptics_sysctl, "I", |
5039 |
synaptics_sysctl, "I", |
4365 |
"Weight of the current movement in the new average"); |
5040 |
"Weight of the current movement in the new average"); |
4366 |
|
5041 |
|
Lines 4369-4375
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4369 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5044 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4370 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5045 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4371 |
"weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5046 |
"weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4372 |
&sc->syninfo.weight_previous, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, |
5047 |
sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, |
4373 |
synaptics_sysctl, "I", |
5048 |
synaptics_sysctl, "I", |
4374 |
"Weight of the previous average"); |
5049 |
"Weight of the previous average"); |
4375 |
|
5050 |
|
Lines 4378-4385
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4378 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5053 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4379 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5054 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4380 |
"weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5055 |
"weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4381 |
&sc->syninfo.weight_previous_na, |
5056 |
sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, |
4382 |
SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, |
|
|
4383 |
synaptics_sysctl, "I", |
5057 |
synaptics_sysctl, "I", |
4384 |
"Weight of the previous average (inside the noisy area)"); |
5058 |
"Weight of the previous average (inside the noisy area)"); |
4385 |
|
5059 |
|
Lines 4388-4395
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4388 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5062 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4389 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5063 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4390 |
"weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5064 |
"weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4391 |
&sc->syninfo.weight_len_squared, |
5065 |
sc, SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, |
4392 |
SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, |
|
|
4393 |
synaptics_sysctl, "I", |
5066 |
synaptics_sysctl, "I", |
4394 |
"Length (squared) of segments where weight_previous " |
5067 |
"Length (squared) of segments where weight_previous " |
4395 |
"starts to decrease"); |
5068 |
"starts to decrease"); |
Lines 4399-4405
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4399 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5072 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4400 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5073 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4401 |
"div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5074 |
"div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4402 |
&sc->syninfo.div_min, SYNAPTICS_SYSCTL_DIV_MIN, |
5075 |
sc, SYNAPTICS_SYSCTL_DIV_MIN, |
4403 |
synaptics_sysctl, "I", |
5076 |
synaptics_sysctl, "I", |
4404 |
"Divisor for fast movements"); |
5077 |
"Divisor for fast movements"); |
4405 |
|
5078 |
|
Lines 4408-4414
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4408 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5081 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4409 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5082 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4410 |
"div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5083 |
"div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4411 |
&sc->syninfo.div_max, SYNAPTICS_SYSCTL_DIV_MAX, |
5084 |
sc, SYNAPTICS_SYSCTL_DIV_MAX, |
4412 |
synaptics_sysctl, "I", |
5085 |
synaptics_sysctl, "I", |
4413 |
"Divisor for slow movements"); |
5086 |
"Divisor for slow movements"); |
4414 |
|
5087 |
|
Lines 4417-4423
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4417 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5090 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4418 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5091 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4419 |
"div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5092 |
"div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4420 |
&sc->syninfo.div_max_na, SYNAPTICS_SYSCTL_DIV_MAX_NA, |
5093 |
sc, SYNAPTICS_SYSCTL_DIV_MAX_NA, |
4421 |
synaptics_sysctl, "I", |
5094 |
synaptics_sysctl, "I", |
4422 |
"Divisor with slow movements (inside the noisy area)"); |
5095 |
"Divisor with slow movements (inside the noisy area)"); |
4423 |
|
5096 |
|
Lines 4426-4432
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4426 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5099 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4427 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5100 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4428 |
"div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5101 |
"div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4429 |
&sc->syninfo.div_len, SYNAPTICS_SYSCTL_DIV_LEN, |
5102 |
sc, SYNAPTICS_SYSCTL_DIV_LEN, |
4430 |
synaptics_sysctl, "I", |
5103 |
synaptics_sysctl, "I", |
4431 |
"Length of segments where div_max starts to decrease"); |
5104 |
"Length of segments where div_max starts to decrease"); |
4432 |
|
5105 |
|
Lines 4435-4441
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4435 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5108 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4436 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5109 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4437 |
"tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5110 |
"tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4438 |
&sc->syninfo.tap_max_delta, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, |
5111 |
sc, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, |
4439 |
synaptics_sysctl, "I", |
5112 |
synaptics_sysctl, "I", |
4440 |
"Length of segments above which a tap is ignored"); |
5113 |
"Length of segments above which a tap is ignored"); |
4441 |
|
5114 |
|
Lines 4444-4450
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4444 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5117 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4445 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5118 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4446 |
"tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5119 |
"tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4447 |
&sc->syninfo.tap_min_queue, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, |
5120 |
sc, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, |
4448 |
synaptics_sysctl, "I", |
5121 |
synaptics_sysctl, "I", |
4449 |
"Number of packets required to consider a tap"); |
5122 |
"Number of packets required to consider a tap"); |
4450 |
|
5123 |
|
Lines 4454-4460
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4454 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5127 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4455 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5128 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4456 |
"taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5129 |
"taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4457 |
&sc->syninfo.taphold_timeout, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, |
5130 |
sc, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, |
4458 |
synaptics_sysctl, "I", |
5131 |
synaptics_sysctl, "I", |
4459 |
"Maximum elapsed time between two taps to consider a tap-hold " |
5132 |
"Maximum elapsed time between two taps to consider a tap-hold " |
4460 |
"action"); |
5133 |
"action"); |
Lines 4464-4479
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4464 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5137 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4465 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5138 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4466 |
"vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5139 |
"vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4467 |
&sc->syninfo.vscroll_hor_area, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, |
5140 |
sc, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, |
4468 |
synaptics_sysctl, "I", |
5141 |
synaptics_sysctl, "I", |
4469 |
"Area reserved for horizontal virtual scrolling"); |
5142 |
"Area reserved for horizontal virtual scrolling"); |
4470 |
|
5143 |
|
4471 |
/* hw.psm.synaptics.vscroll_ver_area. */ |
5144 |
/* hw.psm.synaptics.vscroll_ver_area. */ |
4472 |
sc->syninfo.vscroll_ver_area = -600; |
5145 |
sc->syninfo.vscroll_ver_area = -400 - sc->syninfo.margin_right; |
4473 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5146 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4474 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5147 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4475 |
"vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5148 |
"vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4476 |
&sc->syninfo.vscroll_ver_area, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, |
5149 |
sc, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, |
4477 |
synaptics_sysctl, "I", |
5150 |
synaptics_sysctl, "I", |
4478 |
"Area reserved for vertical virtual scrolling"); |
5151 |
"Area reserved for vertical virtual scrolling"); |
4479 |
|
5152 |
|
Lines 4482-4489
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4482 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5155 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4483 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5156 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4484 |
"vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5157 |
"vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4485 |
&sc->syninfo.vscroll_min_delta, |
5158 |
sc, SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, |
4486 |
SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, |
|
|
4487 |
synaptics_sysctl, "I", |
5159 |
synaptics_sysctl, "I", |
4488 |
"Minimum movement to consider virtual scrolling"); |
5160 |
"Minimum movement to consider virtual scrolling"); |
4489 |
|
5161 |
|
Lines 4492-4498
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4492 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5164 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4493 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5165 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4494 |
"vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5166 |
"vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4495 |
&sc->syninfo.vscroll_div_min, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, |
5167 |
sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, |
4496 |
synaptics_sysctl, "I", |
5168 |
synaptics_sysctl, "I", |
4497 |
"Divisor for fast scrolling"); |
5169 |
"Divisor for fast scrolling"); |
4498 |
|
5170 |
|
Lines 4501-4507
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4501 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5173 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4502 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5174 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4503 |
"vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5175 |
"vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4504 |
&sc->syninfo.vscroll_div_max, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, |
5176 |
sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, |
4505 |
synaptics_sysctl, "I", |
5177 |
synaptics_sysctl, "I", |
4506 |
"Divisor for slow scrolling"); |
5178 |
"Divisor for slow scrolling"); |
4507 |
|
5179 |
|
Lines 4510-4518
synaptics_sysctl_create_tree(struct psm_softc *sc)
Link Here
|
4510 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5182 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4511 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5183 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4512 |
"touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5184 |
"touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4513 |
&sc->syninfo.touchpad_off, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, |
5185 |
sc, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, |
4514 |
synaptics_sysctl, "I", |
5186 |
synaptics_sysctl, "I", |
4515 |
"Turn off touchpad"); |
5187 |
"Turn off touchpad"); |
|
|
5188 |
|
5189 |
sc->syninfo.softbuttons_y = 0; |
5190 |
sc->syninfo.softbutton2_x = 0; |
5191 |
sc->syninfo.softbutton3_x = 0; |
5192 |
|
5193 |
/* skip softbuttons sysctl on not clickpads */ |
5194 |
if (sc->synhw.capClickPad) |
5195 |
synaptics_sysctl_create_softbuttons_tree(sc); |
4516 |
} |
5196 |
} |
4517 |
|
5197 |
|
4518 |
static int |
5198 |
static int |
Lines 4754-4760
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
4754 |
((status[1] & 0x0f) << 1); |
5434 |
((status[1] & 0x0f) << 1); |
4755 |
synhw.maximumYCoord = (status[2] << 5) | |
5435 |
synhw.maximumYCoord = (status[2] << 5) | |
4756 |
((status[1] & 0xf0) >> 3); |
5436 |
((status[1] & 0xf0) >> 3); |
4757 |
} |
5437 |
} else |
|
|
5438 |
synhw.maximumXCoord = synhw.maximumYCoord = |
5439 |
6143; |
5440 |
|
4758 |
if (synhw.capReportsMin) { |
5441 |
if (synhw.capReportsMin) { |
4759 |
if (!set_mouse_scaling(kbdc, 1)) |
5442 |
if (!set_mouse_scaling(kbdc, 1)) |
4760 |
return (FALSE); |
5443 |
return (FALSE); |
Lines 4767-4773
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
4767 |
((status[1] & 0x0f) << 1); |
5450 |
((status[1] & 0x0f) << 1); |
4768 |
synhw.minimumYCoord = (status[2] << 5) | |
5451 |
synhw.minimumYCoord = (status[2] << 5) | |
4769 |
((status[1] & 0xf0) >> 3); |
5452 |
((status[1] & 0xf0) >> 3); |
4770 |
} |
5453 |
} else |
|
|
5454 |
synhw.minimumXCoord = synhw.minimumYCoord = 0; |
4771 |
|
5455 |
|
4772 |
if (verbose >= 2) { |
5456 |
if (verbose >= 2) { |
4773 |
printf(" Continued capabilities:\n"); |
5457 |
printf(" Continued capabilities:\n"); |
Lines 4854-4860
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
4854 |
|
5538 |
|
4855 |
if (arg == PROBE) { |
5539 |
if (arg == PROBE) { |
4856 |
/* Create sysctl tree. */ |
5540 |
/* Create sysctl tree. */ |
4857 |
synaptics_sysctl_create_tree(sc); |
5541 |
synaptics_sysctl_create_tree(sc, "synaptics", |
|
|
5542 |
"Synaptics TouchPad"); |
4858 |
sc->hw.buttons = buttons; |
5543 |
sc->hw.buttons = buttons; |
4859 |
} |
5544 |
} |
4860 |
|
5545 |
|
Lines 5171-5176
enable_versapad(struct psm_softc *sc, enum probearg arg)
Link Here
|
5171 |
return (TRUE); /* PS/2 absolute mode */ |
5856 |
return (TRUE); /* PS/2 absolute mode */ |
5172 |
} |
5857 |
} |
5173 |
|
5858 |
|
|
|
5859 |
/* Elantech Touchpad */ |
5860 |
static int |
5861 |
elantech_read_1(KBDC kbdc, int hwversion, int reg, int *val) |
5862 |
{ |
5863 |
int res, readcmd, retidx; |
5864 |
int resp[3]; |
5865 |
|
5866 |
readcmd = hwversion == 2 ? ELANTECH_REG_READ : ELANTECH_REG_RDWR; |
5867 |
retidx = hwversion == 4 ? 1 : 0; |
5868 |
|
5869 |
res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5870 |
res |= send_aux_command(kbdc, readcmd) != PSM_ACK; |
5871 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5872 |
res |= send_aux_command(kbdc, reg) != PSM_ACK; |
5873 |
res |= get_mouse_status(kbdc, resp, 0, 3) != 3; |
5874 |
|
5875 |
if (res == 0) |
5876 |
*val = resp[retidx]; |
5877 |
|
5878 |
return (res); |
5879 |
} |
5880 |
|
5881 |
static int |
5882 |
elantech_write_1(KBDC kbdc, int hwversion, int reg, int val) |
5883 |
{ |
5884 |
int res, writecmd; |
5885 |
|
5886 |
writecmd = hwversion == 2 ? ELANTECH_REG_WRITE : ELANTECH_REG_RDWR; |
5887 |
|
5888 |
res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5889 |
res |= send_aux_command(kbdc, writecmd) != PSM_ACK; |
5890 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5891 |
res |= send_aux_command(kbdc, reg) != PSM_ACK; |
5892 |
if (hwversion == 4) { |
5893 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5894 |
res |= send_aux_command(kbdc, writecmd) != PSM_ACK; |
5895 |
} |
5896 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5897 |
res |= send_aux_command(kbdc, val) != PSM_ACK; |
5898 |
res |= set_mouse_scaling(kbdc, 1) == 0; |
5899 |
|
5900 |
return (res); |
5901 |
} |
5902 |
|
5903 |
static int |
5904 |
elantech_cmd(KBDC kbdc, int hwversion, int cmd, int *resp) |
5905 |
{ |
5906 |
int res; |
5907 |
|
5908 |
if (hwversion == 2) { |
5909 |
res = set_mouse_scaling(kbdc, 1) == 0; |
5910 |
res |= mouse_ext_command(kbdc, cmd) == 0; |
5911 |
} else { |
5912 |
res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5913 |
res |= send_aux_command(kbdc, cmd) != PSM_ACK; |
5914 |
} |
5915 |
res |= get_mouse_status(kbdc, resp, 0, 3) != 3; |
5916 |
|
5917 |
return (res); |
5918 |
} |
5919 |
|
5920 |
static int |
5921 |
elantech_init(KBDC kbdc, elantechhw_t *elanhw) |
5922 |
{ |
5923 |
int i, val, res, hwversion, reg10; |
5924 |
|
5925 |
/* set absolute mode */ |
5926 |
hwversion = elanhw->hwversion; |
5927 |
reg10 = -1; |
5928 |
switch (hwversion) { |
5929 |
case 2: |
5930 |
reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4; |
5931 |
res = elantech_write_1(kbdc, hwversion, 0x10, reg10); |
5932 |
if (res) |
5933 |
break; |
5934 |
res = elantech_write_1(kbdc, hwversion, 0x11, 0x8A); |
5935 |
break; |
5936 |
case 3: |
5937 |
reg10 = 0x0b; |
5938 |
res = elantech_write_1(kbdc, hwversion, 0x10, reg10); |
5939 |
break; |
5940 |
case 4: |
5941 |
res = elantech_write_1(kbdc, hwversion, 0x07, 0x01); |
5942 |
break; |
5943 |
default: |
5944 |
res = 1; |
5945 |
} |
5946 |
|
5947 |
/* Read back reg 0x10 to ensure hardware is ready. */ |
5948 |
if (res == 0 && reg10 >= 0) { |
5949 |
for (i = 0; i < 5; i++) { |
5950 |
if (elantech_read_1(kbdc, hwversion, 0x10, &val) == 0) |
5951 |
break; |
5952 |
DELAY(2000); |
5953 |
} |
5954 |
if (i == 5) |
5955 |
res = 1; |
5956 |
} |
5957 |
|
5958 |
if (res) |
5959 |
printf("couldn't set absolute mode\n"); |
5960 |
|
5961 |
return (res); |
5962 |
} |
5963 |
|
5964 |
static void |
5965 |
elantech_init_synaptics(struct psm_softc *sc) |
5966 |
{ |
5967 |
|
5968 |
/* Set capabilites required by movement smother */ |
5969 |
sc->synhw.infoMajor = sc->elanhw.hwversion; |
5970 |
sc->synhw.infoMinor = sc->elanhw.fwversion; |
5971 |
sc->synhw.infoXupmm = sc->elanhw.dpmmx; |
5972 |
sc->synhw.infoYupmm = sc->elanhw.dpmmy; |
5973 |
sc->synhw.verticalScroll = 0; |
5974 |
sc->synhw.nExtendedQueries = 4; |
5975 |
sc->synhw.capExtended = 1; |
5976 |
sc->synhw.capPassthrough = sc->elanhw.hastrackpad; |
5977 |
sc->synhw.capClickPad = sc->elanhw.isclickpad; |
5978 |
sc->synhw.capMultiFinger = 1; |
5979 |
sc->synhw.capAdvancedGestures = 1; |
5980 |
sc->synhw.capPalmDetect = 1; |
5981 |
sc->synhw.capPen = 0; |
5982 |
sc->synhw.capReportsMax = 1; |
5983 |
sc->synhw.maximumXCoord = sc->elanhw.sizex; |
5984 |
sc->synhw.maximumYCoord = sc->elanhw.sizey; |
5985 |
sc->synhw.capReportsMin = 1; |
5986 |
sc->synhw.minimumXCoord = 0; |
5987 |
sc->synhw.minimumYCoord = 0; |
5988 |
|
5989 |
if (sc->syninfo.sysctl_tree == NULL) { |
5990 |
synaptics_sysctl_create_tree(sc, "elantech", |
5991 |
"Elantech Touchpad"); |
5992 |
|
5993 |
/* |
5994 |
* Adjust synaptic smoother tunables |
5995 |
* 1. Disable finger detection pressure threshold. Unlike |
5996 |
* synaptics we assume the finger is acting when packet with |
5997 |
* its X&Y arrives not when pressure exceedes some threshold |
5998 |
* 2. Disable unrelated features like margins and noisy areas |
5999 |
* 3. Disable virtual scroll areas as 2nd finger is preferable |
6000 |
* 4. For clickpads set bottom quarter as 3 equaly sized |
6001 |
* softbuttons |
6002 |
* 5. Scale down divisors and movement lengths by a factor of 3 |
6003 |
* where 3 is Synaptics to Elantech (~2200/800) dpi ratio |
6004 |
*/ |
6005 |
|
6006 |
/* Disable finger detection pressure threshold */ |
6007 |
sc->syninfo.min_pressure = 1; |
6008 |
|
6009 |
/* Use full area of touchpad */ |
6010 |
sc->syninfo.margin_top = 0; |
6011 |
sc->syninfo.margin_right = 0; |
6012 |
sc->syninfo.margin_bottom = 0; |
6013 |
sc->syninfo.margin_left = 0; |
6014 |
/* Disable noisy area */ |
6015 |
sc->syninfo.na_top = 0; |
6016 |
sc->syninfo.na_right = 0; |
6017 |
sc->syninfo.na_bottom = 0; |
6018 |
sc->syninfo.na_left = 0; |
6019 |
|
6020 |
/* Tune divisors and movement lengths */ |
6021 |
sc->syninfo.weight_len_squared = 200; |
6022 |
sc->syninfo.div_min = 3; |
6023 |
sc->syninfo.div_max = 6; |
6024 |
sc->syninfo.div_max_na = 10; |
6025 |
sc->syninfo.div_len = 30; |
6026 |
sc->syninfo.tap_max_delta = 25; |
6027 |
|
6028 |
/* Disable virtual scrolling areas and tune its divisors */ |
6029 |
sc->syninfo.vscroll_hor_area = 0; |
6030 |
sc->syninfo.vscroll_ver_area = 0; |
6031 |
sc->syninfo.vscroll_min_delta = 15; |
6032 |
sc->syninfo.vscroll_div_min = 30; |
6033 |
sc->syninfo.vscroll_div_max = 50; |
6034 |
|
6035 |
/* Set bottom quarter as 3 equaly sized softbuttons */ |
6036 |
if (sc->elanhw.isclickpad) { |
6037 |
sc->syninfo.softbuttons_y = sc->elanhw.sizey / 4; |
6038 |
sc->syninfo.softbutton2_x = sc->elanhw.sizex / 3; |
6039 |
sc->syninfo.softbutton3_x = sc->elanhw.sizex * 2 / 3; |
6040 |
} |
6041 |
} |
6042 |
|
6043 |
return; |
6044 |
} |
6045 |
|
6046 |
static int |
6047 |
enable_elantech(struct psm_softc *sc, enum probearg arg) |
6048 |
{ |
6049 |
static const int ic2hw[] = |
6050 |
/*IC: 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
6051 |
{ 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 0, 0, 4, 4, 0 }; |
6052 |
elantechhw_t elanhw; |
6053 |
int icversion, hwversion, dptracex, dptracey, id, resp[3], dpix, dpiy; |
6054 |
KBDC kbdc = sc->kbdc; |
6055 |
|
6056 |
VLOG(3, (LOG_DEBUG, "elantech: BEGIN init\n")); |
6057 |
|
6058 |
set_mouse_scaling(kbdc, 1); |
6059 |
set_mouse_scaling(kbdc, 1); |
6060 |
set_mouse_scaling(kbdc, 1); |
6061 |
if (get_mouse_status(kbdc, resp, 0, 3) != 3) |
6062 |
return (FALSE); |
6063 |
|
6064 |
if (!ELANTECH_MAGIC(resp)) |
6065 |
return (FALSE); |
6066 |
|
6067 |
/* Identify the Touchpad version. */ |
6068 |
if (elantech_cmd(kbdc, 2, ELANTECH_FW_VERSION, resp)) |
6069 |
return (FALSE); |
6070 |
|
6071 |
bzero(&elanhw, sizeof(elanhw)); |
6072 |
|
6073 |
elanhw.fwversion = (resp[0] << 16) | (resp[1] << 8) | resp[2]; |
6074 |
icversion = resp[0] & 0x0f; |
6075 |
hwversion = ic2hw[icversion]; |
6076 |
|
6077 |
if (verbose >= 2) |
6078 |
printf("Elantech touchpad hardware v.%d firmware v.0x%06x\n", |
6079 |
hwversion, elanhw.fwversion); |
6080 |
|
6081 |
if (ELANTECH_HW_IS_V1(elanhw.fwversion)) { |
6082 |
printf (" Unsupported touchpad hardware (v1)\n"); |
6083 |
return (FALSE); |
6084 |
} |
6085 |
if (hwversion == 0) { |
6086 |
printf (" Unknown touchpad hardware (firmware v.0x%06x)\n", |
6087 |
elanhw.fwversion); |
6088 |
return (FALSE); |
6089 |
} |
6090 |
|
6091 |
/* Get the Touchpad model information. */ |
6092 |
elanhw.hwversion = hwversion; |
6093 |
elanhw.issemimt = hwversion == 2 || hwversion == 3; |
6094 |
elanhw.isclickpad = (resp[1] & 0x10) != 0; |
6095 |
elanhw.hascrc = (resp[1] & 0x40) != 0; |
6096 |
elanhw.haspressure = elanhw.fwversion >= 0x020800; |
6097 |
|
6098 |
/* Read the capability bits. */ |
6099 |
if (elantech_cmd(kbdc, hwversion, ELANTECH_CAPABILITIES, resp) != 0) { |
6100 |
printf(" Failed to read capability bits\n"); |
6101 |
return (FALSE); |
6102 |
} |
6103 |
|
6104 |
elanhw.ntracesx = resp[1] - 1; |
6105 |
elanhw.ntracesy = resp[2] - 1; |
6106 |
elanhw.hastrackpad = (resp[0] & 0x80) != 0; |
6107 |
|
6108 |
/* Get the touchpad resolution */ |
6109 |
switch (hwversion) { |
6110 |
case 2: |
6111 |
elanhw.dpmmx = elanhw.dpmmy = 16; /* 400 dpi */ |
6112 |
break; |
6113 |
case 4: |
6114 |
if (elantech_cmd(kbdc, hwversion, ELANTECH_RESOLUTION, resp) |
6115 |
== 0) { |
6116 |
dpix = (resp[1] & 0x0f) * 10 + 790; |
6117 |
dpiy = ((resp[1] & 0xf0) >> 4) * 10 + 790; |
6118 |
elanhw.dpmmx = (dpix * 10 + 5) / 254; |
6119 |
elanhw.dpmmy = (dpiy * 10 + 5) / 254; |
6120 |
break; |
6121 |
} |
6122 |
/* FALLTHROUGH */ |
6123 |
case 3: |
6124 |
elanhw.dpmmx = elanhw.dpmmy = 32; /* 800 dpi */ |
6125 |
break; |
6126 |
} |
6127 |
|
6128 |
if (!elantech_support) |
6129 |
return (FALSE); |
6130 |
|
6131 |
if (elantech_init(kbdc, &elanhw)) { |
6132 |
printf("couldn't initialize elantech touchpad\n"); |
6133 |
return (FALSE); |
6134 |
} |
6135 |
|
6136 |
/* |
6137 |
* Get the touchpad reporting range. |
6138 |
* On HW v.3 touchpads it should be done after switching hardware |
6139 |
* to real resolution mode (by setting bit 3 of reg10) |
6140 |
*/ |
6141 |
if (elantech_cmd(kbdc, hwversion, ELANTECH_FW_ID, resp) != 0) { |
6142 |
printf(" Failed to read touchpad size\n"); |
6143 |
elanhw.sizex = 10000; /* Arbitrary high values to */ |
6144 |
elanhw.sizey = 10000; /* prevent clipping in smoother */ |
6145 |
} else if (hwversion == 2) { |
6146 |
dptracex = dptracey = 64; |
6147 |
if ((elanhw.fwversion >> 16) == 0x14 && (resp[1] & 0x10) && |
6148 |
!elantech_cmd(kbdc, hwversion, ELANTECH_SAMPLE, resp)) { |
6149 |
dptracex = resp[1] / 2; |
6150 |
dptracey = resp[2] / 2; |
6151 |
} |
6152 |
elanhw.sizex = (elanhw.ntracesx - 1) * dptracex; |
6153 |
elanhw.sizey = (elanhw.ntracesy - 1) * dptracey; |
6154 |
} else { |
6155 |
elanhw.sizex = (resp[0] & 0x0f) << 8 | resp[1]; |
6156 |
elanhw.sizey = (resp[0] & 0xf0) << 4 | resp[2]; |
6157 |
} |
6158 |
|
6159 |
if (verbose >= 2) { |
6160 |
printf(" Model information:\n"); |
6161 |
printf(" MaxX: %d\n", elanhw.sizex); |
6162 |
printf(" MaxY: %d\n", elanhw.sizey); |
6163 |
printf(" DpmmX: %d\n", elanhw.dpmmx); |
6164 |
printf(" DpmmY: %d\n", elanhw.dpmmy); |
6165 |
printf(" TracesX: %d\n", elanhw.ntracesx); |
6166 |
printf(" TracesY: %d\n", elanhw.ntracesy); |
6167 |
printf(" SemiMT: %d\n", elanhw.issemimt); |
6168 |
printf(" Clickpad: %d\n", elanhw.isclickpad); |
6169 |
printf(" Trackpad: %d\n", elanhw.hastrackpad); |
6170 |
printf(" CRC: %d\n", elanhw.hascrc); |
6171 |
printf(" Pressure: %d\n", elanhw.haspressure); |
6172 |
} |
6173 |
|
6174 |
VLOG(3, (LOG_DEBUG, "elantech: END init\n")); |
6175 |
|
6176 |
if (arg == PROBE) { |
6177 |
sc->elanhw = elanhw; |
6178 |
sc->hw.buttons = elanhw.isclickpad ? 1 : 3; |
6179 |
|
6180 |
/* Initialize synaptics movement smoother */ |
6181 |
elantech_init_synaptics(sc); |
6182 |
|
6183 |
for (id = 0; id < ELANTECH_MAX_FINGERS; id++) |
6184 |
PSM_FINGER_RESET(sc->elanaction.fingers[id]); |
6185 |
} |
6186 |
|
6187 |
return (TRUE); |
6188 |
} |
6189 |
|
5174 |
/* |
6190 |
/* |
5175 |
* Return true if 'now' is earlier than (start + (secs.usecs)). |
6191 |
* Return true if 'now' is earlier than (start + (secs.usecs)). |
5176 |
* Now may be NULL and the function will fetch the current time from |
6192 |
* Now may be NULL and the function will fetch the current time from |