Lines 81-86
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
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
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; |
202 |
int softbuttons_y; |
203 |
int softbutton2_x; |
204 |
int softbutton3_x; |
205 |
int softbutton_nomove; |
234 |
} synapticsinfo_t; |
206 |
} synapticsinfo_t; |
235 |
|
207 |
|
236 |
typedef struct synapticspacket { |
208 |
typedef struct synapticspacket { |
Lines 295-300
Link Here
|
295 |
int skipback; |
267 |
int skipback; |
296 |
} trackpointinfo_t; |
268 |
} trackpointinfo_t; |
297 |
|
269 |
|
|
|
270 |
typedef struct finger { |
271 |
int x; |
272 |
int y; |
273 |
int p; |
274 |
int w; |
275 |
int flags; |
276 |
} finger_t; |
277 |
#define PSM_GESTURE_FINGERS 2 |
278 |
#define PSM_FINGER_IS_PEN (1<<0) |
279 |
#define PSM_FINGER_FUZZY (1<<1) |
280 |
#define PSM_FINGER_IS_SET(f) ((f).x != -1 && (f).y != -1 && (f).p != 0) |
281 |
#define PSM_FINGER_RESET(f) do \ |
282 |
(f) = (finger_t) { .x = -1, .y = -1, .p = 0, .w = 0, .flags = 0 }; \ |
283 |
while (0) |
284 |
|
285 |
typedef struct elantechhw { |
286 |
int hwversion; |
287 |
int fwversion; |
288 |
int sizex; |
289 |
int sizey; |
290 |
int dpix; |
291 |
int dpiy; |
292 |
int ntracesx; |
293 |
int ntracesy; |
294 |
int isclickpad; |
295 |
int hascrc; |
296 |
int hastrackpad; |
297 |
int haspressure; |
298 |
} elantechhw_t; |
299 |
|
300 |
/* minimum versions supported by this driver */ |
301 |
#define ELANTECH_HW_IS_V1(fwver) ((fwver) < 0x020030 || (fwver) == 0x020600) |
302 |
|
303 |
#define ELANTECH_MAGIC(magic) \ |
304 |
((magic)[0] == 0x3c && (magic)[1] == 0x03 && \ |
305 |
((magic)[2] == 0xc8 || (magic)[2] == 0x00)) |
306 |
|
307 |
#define ELANTECH_FW_ID 0x00 |
308 |
#define ELANTECH_FW_VERSION 0x01 |
309 |
#define ELANTECH_CAPABILITIES 0x02 |
310 |
#define ELANTECH_SAMPLE 0x03 |
311 |
#define ELANTECH_RESOLUTION 0x04 |
312 |
#define ELANTECH_REG_READ 0x10 |
313 |
#define ELANTECH_REG_WRITE 0x11 |
314 |
#define ELANTECH_REG_RDWR 0x00 |
315 |
#define ELANTECH_CUSTOM_CMD 0xf8 |
316 |
|
317 |
#define ELANTECH_FINGER_DEFAULT_P tap_threshold |
318 |
#define ELANTECH_FINGER_DEFAULT_W 1 |
319 |
#define ELANTECH_FINGER_SET_XYP(pb) (finger_t) { \ |
320 |
.x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \ |
321 |
.y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \ |
322 |
.p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \ |
323 |
.w = ELANTECH_FINGER_DEFAULT_W, \ |
324 |
.flags = 0 \ |
325 |
} |
326 |
|
327 |
enum { |
328 |
ELANTECH_PKT_NOP, |
329 |
ELANTECH_PKT_TRACKPOINT, |
330 |
ELANTECH_PKT_V2_COMMON, |
331 |
ELANTECH_PKT_V2_2FINGER, |
332 |
ELANTECH_PKT_V3, |
333 |
ELANTECH_PKT_V4_STATUS, |
334 |
ELANTECH_PKT_V4_HEAD, |
335 |
ELANTECH_PKT_V4_MOTION |
336 |
}; |
337 |
|
338 |
#define ELANTECH_PKT_IS_TRACKPOINT(pb) (((pb)->ipacket[3] & 0x0f) == 0x06) |
339 |
#define ELANTECH_PKT_IS_DEBOUNCE(pb, hwversion) ((hwversion) == 4 ? 0 : \ |
340 |
(pb)->ipacket[0] == ((hwversion) == 2 ? 0x84 : 0xc4) && \ |
341 |
(pb)->ipacket[1] == 0xff && (pb)->ipacket[2] == 0xff && \ |
342 |
(pb)->ipacket[3] == 0x02 && (pb)->ipacket[4] == 0xff && \ |
343 |
(pb)->ipacket[5] == 0xff) |
344 |
#define ELANTECH_PKT_IS_V2(pb) \ |
345 |
(((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x0f) == 0x02) |
346 |
#define ELANTECH_PKT_IS_V3_HEAD(pb, hascrc) ((hascrc) ? \ |
347 |
((pb)->ipacket[3] & 0x09) == 0x08 : \ |
348 |
((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0xcf) == 0x02) |
349 |
#define ELANTECH_PKT_IS_V3_TAIL(pb, hascrc) ((hascrc) ? \ |
350 |
((pb)->ipacket[3] & 0x09) == 0x09 : \ |
351 |
((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c) |
352 |
#define ELANTECH_PKT_IS_V4(pb, hascrc) ((hascrc) ? \ |
353 |
((pb)->ipacket[3] & 0x08) == 0x00 : \ |
354 |
((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10) |
355 |
|
356 |
typedef struct elantechaction { |
357 |
finger_t fingers[PSM_GESTURE_FINGERS]; |
358 |
int nfingers; |
359 |
} elantechaction_t; |
360 |
|
298 |
/* driver control block */ |
361 |
/* driver control block */ |
299 |
struct psm_softc { /* Driver status information */ |
362 |
struct psm_softc { /* Driver status information */ |
300 |
int unit; |
363 |
int unit; |
Lines 308-314
Link Here
|
308 |
mousehw_t hw; /* hardware information */ |
371 |
mousehw_t hw; /* hardware information */ |
309 |
synapticshw_t synhw; /* Synaptics hardware information */ |
372 |
synapticshw_t synhw; /* Synaptics hardware information */ |
310 |
synapticsinfo_t syninfo; /* Synaptics configuration */ |
373 |
synapticsinfo_t syninfo; /* Synaptics configuration */ |
311 |
synapticsaction_t synaction; /* Synaptics action context */ |
374 |
synapticsaction_t |
|
|
375 |
synaction[PSM_GESTURE_FINGERS]; /* 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
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
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
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 = SYN_OFFSET(softbuttons), |
519 |
SYNAPTICS_SYSCTL_SOFTBUTTONS_Y = SYN_OFFSET(softbuttons_y), |
520 |
SYNAPTICS_SYSCTL_SOFTBUTTON2_X = SYN_OFFSET(softbutton2_x), |
521 |
SYNAPTICS_SYSCTL_SOFTBUTTON3_X = SYN_OFFSET(softbutton3_x), |
522 |
SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE = SYN_OFFSET(softbutton_nomove) |
523 |
}; |
524 |
|
414 |
/* packet formatting function */ |
525 |
/* packet formatting function */ |
415 |
typedef int packetfunc_t(struct psm_softc *, u_char *, int *, int, |
526 |
typedef int packetfunc_t(struct psm_softc *, u_char *, int *, int, |
416 |
mousestatus_t *); |
527 |
mousestatus_t *); |
Lines 446-451
Link Here
|
446 |
static int reinitialize(struct psm_softc *, int); |
557 |
static int reinitialize(struct psm_softc *, int); |
447 |
static char *model_name(int); |
558 |
static char *model_name(int); |
448 |
static void psmsoftintr(void *); |
559 |
static void psmsoftintr(void *); |
|
|
560 |
static void psmsoftintridle(void *); |
449 |
static void psmintr(void *); |
561 |
static void psmintr(void *); |
450 |
static void psmtimeout(void *); |
562 |
static void psmtimeout(void *); |
451 |
static int timeelapsed(const struct timeval *, int, int, |
563 |
static int timeelapsed(const struct timeval *, int, int, |
Lines 458-463
Link Here
|
458 |
mousestatus_t *, int *, int *, int *); |
570 |
mousestatus_t *, int *, int *, int *); |
459 |
static void proc_versapad(struct psm_softc *, packetbuf_t *, |
571 |
static void proc_versapad(struct psm_softc *, packetbuf_t *, |
460 |
mousestatus_t *, int *, int *, int *); |
572 |
mousestatus_t *, int *, int *, int *); |
|
|
573 |
static int proc_elantech(struct psm_softc *, packetbuf_t *, |
574 |
mousestatus_t *, int *, int *, int *); |
575 |
static void psmgestures(struct psm_softc *, synapticsaction_t *, finger_t, |
576 |
int, mousestatus_t *, int *, int *); |
577 |
static int psmsoftbuttons(struct psm_softc *, finger_t, int); |
461 |
static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, |
578 |
static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, |
462 |
u_char *); |
579 |
u_char *); |
463 |
|
580 |
|
Lines 480-485
Link Here
|
480 |
static probefunc_t enable_synaptics; |
597 |
static probefunc_t enable_synaptics; |
481 |
static probefunc_t enable_trackpoint; |
598 |
static probefunc_t enable_trackpoint; |
482 |
static probefunc_t enable_versapad; |
599 |
static probefunc_t enable_versapad; |
|
|
600 |
static probefunc_t enable_elantech; |
483 |
|
601 |
|
484 |
static void set_trackpoint_parameters(struct psm_softc *sc); |
602 |
static void set_trackpoint_parameters(struct psm_softc *sc); |
485 |
static void synaptics_passthrough_on(struct psm_softc *sc); |
603 |
static void synaptics_passthrough_on(struct psm_softc *sc); |
Lines 511-516
Link Here
|
511 |
0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus }, |
629 |
0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus }, |
512 |
{ MOUSE_MODEL_SYNAPTICS, /* Synaptics Touchpad */ |
630 |
{ MOUSE_MODEL_SYNAPTICS, /* Synaptics Touchpad */ |
513 |
0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics }, |
631 |
0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics }, |
|
|
632 |
{ MOUSE_MODEL_ELANTECH, /* Elantech Touchpad */ |
633 |
0x04, MOUSE_ELANTECH_PACKETSIZE, enable_elantech }, |
514 |
{ MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ |
634 |
{ MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ |
515 |
0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli }, |
635 |
0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli }, |
516 |
{ MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ |
636 |
{ MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ |
Lines 762-767
Link Here
|
762 |
{ MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, |
882 |
{ MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, |
763 |
{ MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, |
883 |
{ MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, |
764 |
{ MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, |
884 |
{ MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, |
|
|
885 |
{ MOUSE_MODEL_ELANTECH, "Elantech Touchpad" }, |
765 |
{ MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, |
886 |
{ MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, |
766 |
{ MOUSE_MODEL_UNKNOWN, "Unknown" }, |
887 |
{ MOUSE_MODEL_UNKNOWN, "Unknown" }, |
767 |
}; |
888 |
}; |
Lines 1504-1509
Link Here
|
1504 |
case MOUSE_MODEL_SYNAPTICS: |
1625 |
case MOUSE_MODEL_SYNAPTICS: |
1505 |
case MOUSE_MODEL_GLIDEPOINT: |
1626 |
case MOUSE_MODEL_GLIDEPOINT: |
1506 |
case MOUSE_MODEL_VERSAPAD: |
1627 |
case MOUSE_MODEL_VERSAPAD: |
|
|
1628 |
case MOUSE_MODEL_ELANTECH: |
1507 |
sc->config |= PSM_CONFIG_INITAFTERSUSPEND; |
1629 |
sc->config |= PSM_CONFIG_INITAFTERSUSPEND; |
1508 |
break; |
1630 |
break; |
1509 |
default: |
1631 |
default: |
Lines 2627-2633
Link Here
|
2627 |
{ |
2749 |
{ |
2628 |
static int touchpad_buttons; |
2750 |
static int touchpad_buttons; |
2629 |
static int guest_buttons; |
2751 |
static int guest_buttons; |
2630 |
int w, x0, y0; |
2752 |
finger_t f; |
|
|
2753 |
int w, nfingers; |
2631 |
|
2754 |
|
2632 |
/* TouchPad PS/2 absolute mode message format with capFourButtons: |
2755 |
/* TouchPad PS/2 absolute mode message format with capFourButtons: |
2633 |
* |
2756 |
* |
Lines 2806-2812
Link Here
|
2806 |
pb->ipacket[4] &= ~(mask); |
2929 |
pb->ipacket[4] &= ~(mask); |
2807 |
pb->ipacket[5] &= ~(mask); |
2930 |
pb->ipacket[5] &= ~(mask); |
2808 |
} else if (!sc->syninfo.directional_scrolls && |
2931 |
} else if (!sc->syninfo.directional_scrolls && |
2809 |
!sc->synaction.in_vscroll) { |
2932 |
!sc->synaction[0].in_vscroll) { |
2810 |
/* |
2933 |
/* |
2811 |
* Keep reporting MOUSE DOWN until we get a new packet |
2934 |
* Keep reporting MOUSE DOWN until we get a new packet |
2812 |
* indicating otherwise. |
2935 |
* indicating otherwise. |
Lines 2814-2832
Link Here
|
2814 |
touchpad_buttons |= sc->extended_buttons; |
2937 |
touchpad_buttons |= sc->extended_buttons; |
2815 |
} |
2938 |
} |
2816 |
} |
2939 |
} |
|
|
2940 |
|
2941 |
f.x = ((pb->ipacket[3] & 0x10) << 8) | |
2942 |
((pb->ipacket[1] & 0x0f) << 8) | |
2943 |
pb->ipacket[4]; |
2944 |
f.y = ((pb->ipacket[3] & 0x20) << 7) | |
2945 |
((pb->ipacket[1] & 0xf0) << 4) | |
2946 |
pb->ipacket[5]; |
2947 |
f.p = *z; |
2948 |
f.w = w; |
2949 |
f.flags |= w == 2 ? PSM_FINGER_IS_PEN : 0; |
2950 |
f.flags |= w < 2 ? PSM_FINGER_FUZZY : 0; |
2951 |
nfingers = w < 2 ? w + 2 : 1; |
2952 |
|
2817 |
/* Handle ClickPad. */ |
2953 |
/* Handle ClickPad. */ |
2818 |
if (sc->synhw.capClickPad && |
2954 |
if (sc->synhw.capClickPad) |
2819 |
((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) |
2955 |
touchpad_buttons |= psmsoftbuttons(sc, f, |
2820 |
touchpad_buttons |= MOUSE_BUTTON1DOWN; |
2956 |
(pb->ipacket[0] ^ pb->ipacket[3]) & 0x01); |
2821 |
|
2957 |
|
2822 |
ms->button = touchpad_buttons | guest_buttons; |
2958 |
ms->button = touchpad_buttons | guest_buttons; |
2823 |
|
2959 |
|
|
|
2960 |
psmgestures(sc, &sc->synaction[0], f, nfingers, ms, x, y); |
2961 |
|
2962 |
SYNAPTICS_END: |
2824 |
/* |
2963 |
/* |
|
|
2964 |
* Use the extra buttons as a scrollwheel |
2965 |
* |
2966 |
* XXX X.Org uses the Z axis for vertical wheel only, |
2967 |
* whereas moused(8) understands special values to differ |
2968 |
* vertical and horizontal wheels. |
2969 |
* |
2970 |
* xf86-input-mouse needs therefore a small patch to |
2971 |
* understand these special values. Without it, the |
2972 |
* horizontal wheel acts as a vertical wheel in X.Org. |
2973 |
* |
2974 |
* That's why the horizontal wheel is disabled by |
2975 |
* default for now. |
2976 |
*/ |
2977 |
if (ms->button & MOUSE_BUTTON4DOWN) { |
2978 |
*z = -1; |
2979 |
ms->button &= ~MOUSE_BUTTON4DOWN; |
2980 |
} else if (ms->button & MOUSE_BUTTON5DOWN) { |
2981 |
*z = 1; |
2982 |
ms->button &= ~MOUSE_BUTTON5DOWN; |
2983 |
} else if (ms->button & MOUSE_BUTTON6DOWN) { |
2984 |
*z = -2; |
2985 |
ms->button &= ~MOUSE_BUTTON6DOWN; |
2986 |
} else if (ms->button & MOUSE_BUTTON7DOWN) { |
2987 |
*z = 2; |
2988 |
ms->button &= ~MOUSE_BUTTON7DOWN; |
2989 |
} else |
2990 |
*z = 0; |
2991 |
|
2992 |
return (0); |
2993 |
} |
2994 |
|
2995 |
static void |
2996 |
psmgestures(struct psm_softc *sc, synapticsaction_t *synaction, finger_t f, |
2997 |
int nfingers, mousestatus_t *ms, int *x, int *y) |
2998 |
{ |
2999 |
*x = *y = 0; |
3000 |
|
3001 |
/* |
2825 |
* Check pressure to detect a real wanted action on the |
3002 |
* Check pressure to detect a real wanted action on the |
2826 |
* touchpad. |
3003 |
* touchpad. |
2827 |
*/ |
3004 |
*/ |
2828 |
if (*z >= sc->syninfo.min_pressure) { |
3005 |
if (f.p >= sc->syninfo.min_pressure) { |
2829 |
synapticsaction_t *synaction; |
3006 |
int x0, y0; |
2830 |
int cursor, peer, window; |
3007 |
int cursor, peer, window; |
2831 |
int dx, dy, dxp, dyp; |
3008 |
int dx, dy, dxp, dyp; |
2832 |
int max_width, max_pressure; |
3009 |
int max_width, max_pressure; |
Lines 2838-2843
Link Here
|
2838 |
int div_min, div_max, div_len; |
3015 |
int div_min, div_max, div_len; |
2839 |
int vscroll_hor_area, vscroll_ver_area; |
3016 |
int vscroll_hor_area, vscroll_ver_area; |
2840 |
int two_finger_scroll; |
3017 |
int two_finger_scroll; |
|
|
3018 |
int max_x, max_y; |
2841 |
int len, weight_prev_x, weight_prev_y; |
3019 |
int len, weight_prev_x, weight_prev_y; |
2842 |
int div_max_x, div_max_y, div_x, div_y; |
3020 |
int div_max_x, div_max_y, div_x, div_y; |
2843 |
int exiting_scroll; |
3021 |
int exiting_scroll; |
Lines 2866-2871
Link Here
|
2866 |
vscroll_hor_area = sc->syninfo.vscroll_hor_area; |
3044 |
vscroll_hor_area = sc->syninfo.vscroll_hor_area; |
2867 |
vscroll_ver_area = sc->syninfo.vscroll_ver_area; |
3045 |
vscroll_ver_area = sc->syninfo.vscroll_ver_area; |
2868 |
two_finger_scroll = sc->syninfo.two_finger_scroll; |
3046 |
two_finger_scroll = sc->syninfo.two_finger_scroll; |
|
|
3047 |
max_x = sc->synhw.maximumXCoord; |
3048 |
max_y = sc->synhw.maximumYCoord; |
2869 |
|
3049 |
|
2870 |
exiting_scroll = 0; |
3050 |
exiting_scroll = 0; |
2871 |
|
3051 |
|
Lines 2872-2907
Link Here
|
2872 |
/* Palm detection. */ |
3052 |
/* Palm detection. */ |
2873 |
if (!( |
3053 |
if (!( |
2874 |
((sc->synhw.capMultiFinger || |
3054 |
((sc->synhw.capMultiFinger || |
2875 |
sc->synhw.capAdvancedGestures) && (w == 0 || w == 1)) || |
3055 |
sc->synhw.capAdvancedGestures) && nfingers > 1) || |
2876 |
(sc->synhw.capPalmDetect && w >= 4 && w <= max_width) || |
3056 |
(sc->synhw.capPalmDetect && f.w <= max_width) || |
2877 |
(!sc->synhw.capPalmDetect && *z <= max_pressure) || |
3057 |
(!sc->synhw.capPalmDetect && f.p <= max_pressure) || |
2878 |
(sc->synhw.capPen && w == 2))) { |
3058 |
(sc->synhw.capPen && f.flags & PSM_FINGER_IS_PEN))) { |
2879 |
/* |
3059 |
/* |
2880 |
* We consider the packet irrelevant for the current |
3060 |
* We consider the packet irrelevant for the current |
2881 |
* action when: |
3061 |
* action when: |
2882 |
* - the width isn't comprised in: |
3062 |
* - the width isn't comprised in: |
2883 |
* [4; max_width] |
3063 |
* [1; max_width] |
2884 |
* - the pressure isn't comprised in: |
3064 |
* - the pressure isn't comprised in: |
2885 |
* [min_pressure; max_pressure] |
3065 |
* [min_pressure; max_pressure] |
2886 |
* - pen aren't supported but w is 2 |
3066 |
* - pen aren't supported but PSM_FiNGER_IS_PEN is set |
2887 |
* |
3067 |
* |
2888 |
* Note that this doesn't terminate the current action. |
3068 |
* Note that this doesn't terminate the current action. |
2889 |
*/ |
3069 |
*/ |
2890 |
VLOG(2, (LOG_DEBUG, |
3070 |
VLOG(2, (LOG_DEBUG, |
2891 |
"synaptics: palm detected! (%d)\n", w)); |
3071 |
"synaptics: palm detected! (%d)\n", f.w)); |
2892 |
goto SYNAPTICS_END; |
3072 |
return; |
2893 |
} |
3073 |
} |
2894 |
|
3074 |
|
2895 |
/* Read current absolute position. */ |
3075 |
/* Read current absolute position. */ |
2896 |
x0 = ((pb->ipacket[3] & 0x10) << 8) | |
3076 |
x0 = f.x; |
2897 |
((pb->ipacket[1] & 0x0f) << 8) | |
3077 |
y0 = f.y; |
2898 |
pb->ipacket[4]; |
|
|
2899 |
y0 = ((pb->ipacket[3] & 0x20) << 7) | |
2900 |
((pb->ipacket[1] & 0xf0) << 4) | |
2901 |
pb->ipacket[5]; |
2902 |
|
3078 |
|
2903 |
synaction = &(sc->synaction); |
|
|
2904 |
|
2905 |
/* |
3079 |
/* |
2906 |
* If the action is just beginning, init the structure and |
3080 |
* If the action is just beginning, init the structure and |
2907 |
* compute tap timeout. |
3081 |
* compute tap timeout. |
Lines 2964-2978
Link Here
|
2964 |
*/ |
3138 |
*/ |
2965 |
if (x0 <= margin_left) |
3139 |
if (x0 <= margin_left) |
2966 |
x0 = margin_left; |
3140 |
x0 = margin_left; |
2967 |
else if (x0 >= 6143 - margin_right) |
3141 |
else if (x0 >= max_x - margin_right) |
2968 |
x0 = 6143 - margin_right; |
3142 |
x0 = max_x - margin_right; |
2969 |
if (y0 <= margin_bottom) |
3143 |
if (y0 <= margin_bottom) |
2970 |
y0 = margin_bottom; |
3144 |
y0 = margin_bottom; |
2971 |
else if (y0 >= 6143 - margin_top) |
3145 |
else if (y0 >= max_y - margin_top) |
2972 |
y0 = 6143 - margin_top; |
3146 |
y0 = max_y - margin_top; |
2973 |
|
3147 |
|
2974 |
VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", |
3148 |
VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", |
2975 |
x0, y0, *z, w)); |
3149 |
x0, y0, f.p, f.w)); |
2976 |
|
3150 |
|
2977 |
/* Queue this new packet. */ |
3151 |
/* Queue this new packet. */ |
2978 |
cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1); |
3152 |
cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1); |
Lines 2990-3015
Link Here
|
2990 |
* pressure peak. Also with multiple fingers, we increase |
3164 |
* pressure peak. Also with multiple fingers, we increase |
2991 |
* the minimum window. |
3165 |
* the minimum window. |
2992 |
*/ |
3166 |
*/ |
2993 |
switch (w) { |
3167 |
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; |
3168 |
synaction->window_min = window_max; |
2997 |
break; |
3169 |
synaction->fingers_nb = imax(nfingers, synaction->fingers_nb); |
2998 |
case 0: /* Two fingers. */ |
3170 |
sc->zmax = imax(f.p, sc->zmax); |
2999 |
synaction->fingers_nb = imax(2, synaction->fingers_nb); |
|
|
3000 |
synaction->window_min = window_max; |
3001 |
break; |
3002 |
default: /* One finger or undetectable. */ |
3003 |
synaction->fingers_nb = imax(1, synaction->fingers_nb); |
3004 |
} |
3005 |
sc->zmax = imax(*z, sc->zmax); |
3006 |
|
3171 |
|
3007 |
/* Do we have enough packets to consider this a movement? */ |
3172 |
/* Do we have enough packets to consider this a movement? */ |
3008 |
if (synaction->queue_len < synaction->window_min) |
3173 |
if (synaction->queue_len < synaction->window_min) |
3009 |
goto SYNAPTICS_END; |
3174 |
return; |
3010 |
|
3175 |
|
3011 |
/* Is a scrolling action occurring? */ |
3176 |
/* Is a scrolling action occurring? */ |
3012 |
if (!synaction->in_taphold && !synaction->in_vscroll) { |
3177 |
if (!synaction->in_taphold && |
|
|
3178 |
(!synaction->in_vscroll || two_finger_scroll)) { |
3013 |
/* |
3179 |
/* |
3014 |
* A scrolling action must not conflict with a tap |
3180 |
* A scrolling action must not conflict with a tap |
3015 |
* action. Here are the conditions to consider a |
3181 |
* action. Here are the conditions to consider a |
Lines 3034-3040
Link Here
|
3034 |
* as that keeps the maximum number of fingers. |
3200 |
* as that keeps the maximum number of fingers. |
3035 |
*/ |
3201 |
*/ |
3036 |
if (two_finger_scroll) { |
3202 |
if (two_finger_scroll) { |
3037 |
if (w == 0) { |
3203 |
if (nfingers == 2) { |
3038 |
synaction->in_vscroll += |
3204 |
synaction->in_vscroll += |
3039 |
dyp ? 2 : 0; |
3205 |
dyp ? 2 : 0; |
3040 |
synaction->in_vscroll += |
3206 |
synaction->in_vscroll += |
Lines 3047-3053
Link Here
|
3047 |
vscroll_hor_area) || |
3213 |
vscroll_hor_area) || |
3048 |
(vscroll_hor_area < 0 && |
3214 |
(vscroll_hor_area < 0 && |
3049 |
synaction->start_y >= |
3215 |
synaction->start_y >= |
3050 |
6143 + vscroll_hor_area)) |
3216 |
max_y + vscroll_hor_area)) |
3051 |
synaction->in_vscroll += 2; |
3217 |
synaction->in_vscroll += 2; |
3052 |
|
3218 |
|
3053 |
/* Check for vertical scrolling. */ |
3219 |
/* Check for vertical scrolling. */ |
Lines 3056-3062
Link Here
|
3056 |
vscroll_ver_area) || |
3222 |
vscroll_ver_area) || |
3057 |
(vscroll_ver_area < 0 && |
3223 |
(vscroll_ver_area < 0 && |
3058 |
synaction->start_x >= |
3224 |
synaction->start_x >= |
3059 |
6143 + vscroll_ver_area)) |
3225 |
max_x + vscroll_ver_area)) |
3060 |
synaction->in_vscroll += 1; |
3226 |
synaction->in_vscroll += 1; |
3061 |
} |
3227 |
} |
3062 |
|
3228 |
|
Lines 3070-3077
Link Here
|
3070 |
* Reset two finger scrolling when the number of fingers |
3236 |
* Reset two finger scrolling when the number of fingers |
3071 |
* is different from two. |
3237 |
* is different from two. |
3072 |
*/ |
3238 |
*/ |
3073 |
if (two_finger_scroll && w != 0 && synaction->in_vscroll != 0) { |
3239 |
if (two_finger_scroll && nfingers != 2 && synaction->in_vscroll != 0) { |
3074 |
synaction->in_vscroll = 0; |
3240 |
synaction->in_vscroll = 0; |
3075 |
exiting_scroll = 1; |
3241 |
exiting_scroll = 1; |
3076 |
} |
3242 |
} |
3077 |
|
3243 |
|
Lines 3096-3107
Link Here
|
3096 |
* using this area, we apply a special weight and |
3262 |
* using this area, we apply a special weight and |
3097 |
* div. |
3263 |
* div. |
3098 |
*/ |
3264 |
*/ |
3099 |
if (x0 <= na_left || x0 >= 6143 - na_right) { |
3265 |
if (x0 <= na_left || x0 >= max_x - na_right) { |
3100 |
weight_prev_x = sc->syninfo.weight_previous_na; |
3266 |
weight_prev_x = sc->syninfo.weight_previous_na; |
3101 |
div_max_x = sc->syninfo.div_max_na; |
3267 |
div_max_x = sc->syninfo.div_max_na; |
3102 |
} |
3268 |
} |
3103 |
|
3269 |
|
3104 |
if (y0 <= na_bottom || y0 >= 6143 - na_top) { |
3270 |
if (y0 <= na_bottom || y0 >= max_y - na_top) { |
3105 |
weight_prev_y = sc->syninfo.weight_previous_na; |
3271 |
weight_prev_y = sc->syninfo.weight_previous_na; |
3106 |
div_max_y = sc->syninfo.div_max_na; |
3272 |
div_max_y = sc->syninfo.div_max_na; |
3107 |
} |
3273 |
} |
Lines 3193-3202
Link Here
|
3193 |
* An action is currently taking place but the pressure |
3359 |
* An action is currently taking place but the pressure |
3194 |
* dropped under the minimum, putting an end to it. |
3360 |
* dropped under the minimum, putting an end to it. |
3195 |
*/ |
3361 |
*/ |
3196 |
synapticsaction_t *synaction; |
|
|
3197 |
int taphold_timeout, dx, dy, tap_max_delta; |
3362 |
int taphold_timeout, dx, dy, tap_max_delta; |
3198 |
|
3363 |
|
3199 |
synaction = &(sc->synaction); |
|
|
3200 |
dx = abs(synaction->queue[synaction->queue_cursor].x - |
3364 |
dx = abs(synaction->queue[synaction->queue_cursor].x - |
3201 |
synaction->start_x); |
3365 |
synaction->start_x); |
3202 |
dy = abs(synaction->queue[synaction->queue_cursor].y - |
3366 |
dy = abs(synaction->queue[synaction->queue_cursor].y - |
Lines 3247-3252
Link Here
|
3247 |
"synaptics: button RELEASE: %d\n", |
3411 |
"synaptics: button RELEASE: %d\n", |
3248 |
synaction->tap_button)); |
3412 |
synaction->tap_button)); |
3249 |
sc->flags |= PSM_FLAGS_FINGERDOWN; |
3413 |
sc->flags |= PSM_FLAGS_FINGERDOWN; |
|
|
3414 |
|
3415 |
/* Schedule button press on next interrupt */ |
3416 |
sc->idletimeout.tv_sec = psmhz > 1 ? |
3417 |
0 : 1; |
3418 |
sc->idletimeout.tv_usec = psmhz > 1 ? |
3419 |
1000000 / psmhz : 0; |
3250 |
} else { |
3420 |
} else { |
3251 |
/* |
3421 |
/* |
3252 |
* This is the first tap: we set the |
3422 |
* This is the first tap: we set the |
Lines 3259-3264
Link Here
|
3259 |
1000000; |
3429 |
1000000; |
3260 |
sc->taptimeout.tv_usec = taphold_timeout % |
3430 |
sc->taptimeout.tv_usec = taphold_timeout % |
3261 |
1000000; |
3431 |
1000000; |
|
|
3432 |
sc->idletimeout = sc->taptimeout; |
3262 |
timevaladd(&sc->taptimeout, &sc->lastsoftintr); |
3433 |
timevaladd(&sc->taptimeout, &sc->lastsoftintr); |
3263 |
|
3434 |
|
3264 |
switch (synaction->fingers_nb) { |
3435 |
switch (synaction->fingers_nb) { |
Lines 3295-3301
Link Here
|
3295 |
} |
3466 |
} |
3296 |
} |
3467 |
} |
3297 |
} else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && |
3468 |
} else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && |
3298 |
sc->synaction.in_taphold) { |
3469 |
synaction->in_taphold) { |
3299 |
/* |
3470 |
/* |
3300 |
* For a tap-hold to work, the button must remain down at |
3471 |
* For a tap-hold to work, the button must remain down at |
3301 |
* least until timeout (where the in_taphold flags will be |
3472 |
* least until timeout (where the in_taphold flags will be |
Lines 3302-3346
Link Here
|
3302 |
* cleared) or during the next action. |
3473 |
* cleared) or during the next action. |
3303 |
*/ |
3474 |
*/ |
3304 |
if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) { |
3475 |
if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) { |
3305 |
ms->button |= sc->synaction.tap_button; |
3476 |
ms->button |= synaction->tap_button; |
3306 |
} else { |
3477 |
} else { |
3307 |
VLOG(2, (LOG_DEBUG, |
3478 |
VLOG(2, (LOG_DEBUG, |
3308 |
"synaptics: button RELEASE: %d\n", |
3479 |
"synaptics: button RELEASE: %d\n", |
3309 |
sc->synaction.tap_button)); |
3480 |
synaction->tap_button)); |
3310 |
sc->synaction.in_taphold = 0; |
3481 |
synaction->in_taphold = 0; |
3311 |
} |
3482 |
} |
3312 |
} |
3483 |
} |
3313 |
|
3484 |
|
3314 |
SYNAPTICS_END: |
3485 |
return; |
|
|
3486 |
} |
3487 |
|
3488 |
static int |
3489 |
psmsoftbuttons(struct psm_softc *sc, finger_t f, int pressed) |
3490 |
{ |
3491 |
static int button = 0; |
3492 |
int y_ok, center_button, center_x, right_button, right_x; |
3493 |
|
3494 |
/* Dont change clickpad softbutton after pressing */ |
3495 |
if (pressed && !button) { |
3496 |
y_ok = sc->syninfo.softbuttons_y >= 0 ? |
3497 |
f.y < sc->syninfo.softbuttons_y : |
3498 |
f.y > sc->synhw.maximumYCoord - sc->syninfo.softbuttons_y; |
3499 |
|
3500 |
center_button = MOUSE_BUTTON2DOWN; |
3501 |
center_x = sc->syninfo.softbutton2_x; |
3502 |
right_button = MOUSE_BUTTON3DOWN; |
3503 |
right_x = sc->syninfo.softbutton3_x; |
3504 |
|
3505 |
if (center_x > 0 && right_x > 0 && center_x > right_x) { |
3506 |
center_button = MOUSE_BUTTON3DOWN; |
3507 |
center_x = sc->syninfo.softbutton3_x; |
3508 |
right_button = MOUSE_BUTTON2DOWN; |
3509 |
right_x = sc->syninfo.softbutton2_x; |
3510 |
} |
3511 |
|
3512 |
if (right_x > 0 && f.x > right_x && y_ok) |
3513 |
button = right_button; |
3514 |
else if (center_x > 0 && f.x > center_x && y_ok) |
3515 |
button = center_button; |
3516 |
else |
3517 |
button = MOUSE_BUTTON1DOWN; |
3518 |
VLOG(2, (LOG_DEBUG, "softbutton: PRESS: %d\n", button)); |
3519 |
} |
3520 |
|
3521 |
/* Clickpad releases */ |
3522 |
if (!pressed && button) { |
3523 |
VLOG(2, (LOG_DEBUG, "softbutton: RELEASE: %d\n", button)); |
3524 |
button = 0; |
3525 |
} |
3526 |
|
3527 |
return (button); |
3528 |
} |
3529 |
|
3530 |
static int |
3531 |
proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, |
3532 |
int *x, int *y, int *z) |
3533 |
{ |
3534 |
static int touchpad_button, trackpoint_button; |
3535 |
static int v4nfingers = 0; |
3536 |
finger_t fn, f[PSM_GESTURE_FINGERS]; |
3537 |
int pkt, id, scale, i, nfingers, reset_queue; |
3538 |
|
3539 |
if (!elantech_support) |
3540 |
return (0); |
3541 |
|
3542 |
/* Determine packet format and do a sanity check for out of sync packets. */ |
3543 |
if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion)) |
3544 |
pkt = ELANTECH_PKT_NOP; |
3545 |
else if (ELANTECH_PKT_IS_TRACKPOINT(pb)) |
3546 |
pkt = ELANTECH_PKT_TRACKPOINT; |
3547 |
else |
3548 |
switch (sc->elanhw.hwversion) { |
3549 |
case 2: |
3550 |
if (!ELANTECH_PKT_IS_V2(pb)) |
3551 |
return (-1); |
3552 |
|
3553 |
pkt = (pb->ipacket[0] & 0xc0) == 0x80 ? |
3554 |
ELANTECH_PKT_V2_2FINGER : ELANTECH_PKT_V2_COMMON; |
3555 |
break; |
3556 |
case 3: |
3557 |
if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) && |
3558 |
!ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc)) |
3559 |
return (-1); |
3560 |
|
3561 |
pkt = ELANTECH_PKT_V3; |
3562 |
break; |
3563 |
case 4: |
3564 |
if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc)) |
3565 |
return (-1); |
3566 |
|
3567 |
switch (pb->ipacket[3] & 0x03) { |
3568 |
case 0x00: |
3569 |
pkt = ELANTECH_PKT_V4_STATUS; |
3570 |
break; |
3571 |
case 0x01: |
3572 |
pkt = ELANTECH_PKT_V4_HEAD; |
3573 |
break; |
3574 |
case 0x02: |
3575 |
pkt = ELANTECH_PKT_V4_MOTION; |
3576 |
break; |
3577 |
default: |
3578 |
return (-1); |
3579 |
} |
3580 |
break; |
3581 |
default: |
3582 |
return (-1); |
3583 |
} |
3584 |
|
3585 |
VLOG(5, (LOG_DEBUG, "elantech: ipacket format: %d\n", pkt)); |
3586 |
|
3587 |
for (id = 0; id < PSM_GESTURE_FINGERS; id++) |
3588 |
PSM_FINGER_RESET(f[id]); |
3589 |
|
3590 |
*x = *y = *z = 0; |
3591 |
ms->button = ms->obutton; |
3592 |
|
3593 |
if (sc->syninfo.touchpad_off) |
3594 |
return (0); |
3595 |
|
3596 |
/* Common legend |
3597 |
* L: Left mouse button pressed |
3598 |
* R: Right mouse button pressed |
3599 |
* N: number of fingers on touchpad |
3600 |
* X: absolute x value (horizontal) |
3601 |
* Y: absolute y value (vertical) |
3602 |
* W; width of the finger touch |
3603 |
* P: pressure |
3604 |
*/ |
3605 |
switch (pkt) { |
3606 |
case ELANTECH_PKT_V2_COMMON: /* HW V2. One/Three finger touch */ |
3607 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3608 |
* ------------------------------------------- |
3609 |
* ipacket[0]: N1 N0 W3 W2 . . R L |
3610 |
* ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 |
3611 |
* ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 |
3612 |
* ipacket[3]: N4 VF W1 W0 . . . B2 |
3613 |
* ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 |
3614 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3615 |
* ------------------------------------------- |
3616 |
* N4: set if more than 3 fingers (only in 3 fingers mode) |
3617 |
* VF: a kind of flag? (only on EF123, 0 when finger |
3618 |
* is over one of the buttons, 1 otherwise) |
3619 |
* B2: (on EF113 only, 0 otherwise), one button pressed |
3620 |
* P & W is not reported on EF113 touchpads |
3621 |
*/ |
3622 |
nfingers = (pb->ipacket[0] & 0xc0) >> 6; |
3623 |
|
3624 |
fn = ELANTECH_FINGER_SET_XYP(pb); |
3625 |
if (sc->elanhw.haspressure) { |
3626 |
fn.w = ((pb->ipacket[0] & 0x30) >> 2) | |
3627 |
((pb->ipacket[3] & 0x30) >> 4); |
3628 |
} else { |
3629 |
fn.p = ELANTECH_FINGER_DEFAULT_P; |
3630 |
fn.w = ELANTECH_FINGER_DEFAULT_W; |
3631 |
} |
3632 |
|
3633 |
/* |
3634 |
* HW v2 dont report exact finger positions when 3 or more |
3635 |
* fingers are on touchpad. Use reported value as fingers |
3636 |
* position as it is required for tap detection |
3637 |
*/ |
3638 |
if (nfingers > 2) { |
3639 |
fn.flags = PSM_FINGER_FUZZY; |
3640 |
f[0] = f[1] = fn; |
3641 |
} |
3642 |
|
3643 |
id = nfingers - 1; |
3644 |
if (id >= 0 && id < PSM_GESTURE_FINGERS) |
3645 |
f[id] = fn; |
3646 |
break; |
3647 |
|
3648 |
case ELANTECH_PKT_V2_2FINGER: /*HW V2. Two finger touch */ |
3649 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3650 |
* ------------------------------------------- |
3651 |
* ipacket[0]: N1 N0 AY8 AX8 . . R L |
3652 |
* ipacket[1]: AX7 AX6 AX5 AX4 AX3 AX2 AX1 AX0 |
3653 |
* ipacket[2]: AY7 AY6 AY5 AY4 AY3 AY2 AY1 AY0 |
3654 |
* ipacket[3]: . . BY8 BX8 . . . . |
3655 |
* ipacket[4]: BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0 |
3656 |
* ipacket[5]: BY7 BY6 BY5 BY4 BY3 BY2 BY1 BY0 |
3657 |
* ------------------------------------------- |
3658 |
* AX: lower-left finger absolute x value |
3659 |
* AY: lower-left finger absolute y value |
3660 |
* BX: upper-right finger absolute x value |
3661 |
* BY: upper-right finger absolute y value |
3662 |
*/ |
3663 |
nfingers = 2; |
3664 |
|
3665 |
VLOG(5, (LOG_DEBUG, "elantech: v2 BBX: [%d, %d] [%d, %d]\n", |
3666 |
((pb->ipacket[0] & 0x10) << 4) | pb->ipacket[1], |
3667 |
((pb->ipacket[0] & 0x20) << 3) | pb->ipacket[2], |
3668 |
((pb->ipacket[3] & 0x10) << 4) | pb->ipacket[4], |
3669 |
((pb->ipacket[3] & 0x20) << 3) | pb->ipacket[5] |
3670 |
)); |
3671 |
for (id = 0; id < imin(2, PSM_GESTURE_FINGERS); id ++) |
3672 |
f[id] = (finger_t) { |
3673 |
.x = (((pb->ipacket[id * 3] & 0x10) << 4) | |
3674 |
pb->ipacket[id * 3 + 1]) << 2, |
3675 |
.y = (((pb->ipacket[id * 3] & 0x20) << 3) | |
3676 |
pb->ipacket[id * 3 + 2]) << 2, |
3677 |
.p = ELANTECH_FINGER_DEFAULT_P, |
3678 |
.w = ELANTECH_FINGER_DEFAULT_W, |
3679 |
/* HW ver.2 sends bounding box */ |
3680 |
.flags = PSM_FINGER_FUZZY |
3681 |
}; |
3682 |
break; |
3683 |
|
3684 |
case ELANTECH_PKT_V3: /* HW Version 3 */ |
3685 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3686 |
* ------------------------------------------- |
3687 |
* ipacket[0]: N1 N0 W3 W2 0 1 R L |
3688 |
* ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 |
3689 |
* ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 |
3690 |
* ipacket[3]: 0 0 W1 W0 0 0 1 0 |
3691 |
* ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 |
3692 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3693 |
* ------------------------------------------- |
3694 |
*/ |
3695 |
nfingers = (pb->ipacket[0] & 0xc0) >> 6; |
3696 |
id = nfingers - 1; |
3697 |
|
3698 |
fn = ELANTECH_FINGER_SET_XYP(pb); |
3699 |
fn.w = ((pb->ipacket[0] & 0x30) >> 2) | |
3700 |
((pb->ipacket[3] & 0x30) >> 4); |
3701 |
|
3702 |
/* |
3703 |
* HW v3 dont report exact finger positions when 3 or more |
3704 |
* fingers are on touchpad. Use reported value as fingers |
3705 |
* position as it is required for tap detection |
3706 |
*/ |
3707 |
if (nfingers > 2) { |
3708 |
fn.flags = PSM_FINGER_FUZZY; |
3709 |
f[0] = f[1] = fn; |
3710 |
} |
3711 |
|
3712 |
if (nfingers == 2 && |
3713 |
ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc)) |
3714 |
id = 0; |
3715 |
|
3716 |
if (id >= 0 && id < PSM_GESTURE_FINGERS) { |
3717 |
f[id] = fn; |
3718 |
} |
3719 |
break; |
3720 |
|
3721 |
case ELANTECH_PKT_V4_STATUS: /* HW Version 4. Status packet */ |
3722 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3723 |
* ------------------------------------------- |
3724 |
* ipacket[0]: . . . . 0 1 R L |
3725 |
* ipacket[1]: . . . F4 F3 F2 F1 F0 |
3726 |
* ipacket[2]: . . . . . . . . |
3727 |
* ipacket[3]: . . . 1 0 0 0 0 |
3728 |
* ipacket[4]: PL . . . . . . . |
3729 |
* ipacket[5]: . . . . . . . . |
3730 |
* ------------------------------------------- |
3731 |
* Fn: finger n is on touchpad |
3732 |
* PL: palm |
3733 |
* HV ver4 sends a status packet to indicate that the numbers |
3734 |
* or identities of the fingers has been changed |
3735 |
*/ |
3736 |
|
3737 |
v4nfingers = fls(pb->ipacket[1] & 0x1f); |
3738 |
|
3739 |
if (v4nfingers > sc->elanaction.nfingers) |
3740 |
return (0); |
3741 |
|
3742 |
nfingers = v4nfingers; |
3743 |
|
3744 |
break; |
3745 |
|
3746 |
case ELANTECH_PKT_V4_HEAD: /* HW Version 4. Head packet */ |
3747 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3748 |
* ------------------------------------------- |
3749 |
* ipacket[0]: W3 W2 W1 W0 0 1 R L |
3750 |
* ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 |
3751 |
* ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 |
3752 |
* ipacket[3]: ID2 ID1 ID0 1 0 0 0 1 |
3753 |
* ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 |
3754 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3755 |
* ------------------------------------------- |
3756 |
* ID: finger id |
3757 |
* HW ver 4 sends head packets in two cases: |
3758 |
* 1. One finger touch and movement. |
3759 |
* 2. Next after status packet to tell new finger positions. |
3760 |
*/ |
3761 |
nfingers = v4nfingers; |
3762 |
id = ((pb->ipacket[3] & 0xe0) >> 5) - 1; |
3763 |
|
3764 |
if (id >= 0 && id < PSM_GESTURE_FINGERS) { |
3765 |
f[id] = ELANTECH_FINGER_SET_XYP(pb); |
3766 |
f[id].w = (pb->ipacket[0] & 0xf0) >> 4; |
3767 |
} |
3768 |
break; |
3769 |
|
3770 |
case ELANTECH_PKT_V4_MOTION: /* HW Version 4. Motion packet */ |
3771 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3772 |
* ------------------------------------------- |
3773 |
* ipacket[0]: ID2 ID1 ID0 OF 0 1 R L |
3774 |
* ipacket[1]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 |
3775 |
* ipacket[2]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 |
3776 |
* ipacket[3]: ID2 ID1 ID0 1 0 0 1 0 |
3777 |
* ipacket[4]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 |
3778 |
* ipacket[5]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 |
3779 |
* ------------------------------------------- |
3780 |
* OF: delta overflows (> 127 or < -128), in this case |
3781 |
* firmware sends us (delta x / 5) and (delta y / 5) |
3782 |
* ID: finger id |
3783 |
* DX: delta x (two's complement) |
3784 |
* XY: delta y (two's complement) |
3785 |
* byte 0 ~ 2 for one finger |
3786 |
* byte 3 ~ 5 for another finger |
3787 |
*/ |
3788 |
nfingers = v4nfingers; |
3789 |
|
3790 |
scale = (pb->ipacket[0] & 0x10) ? 5 : 1; |
3791 |
for (i = 0; i <= 3; i += 3) { |
3792 |
id = ((pb->ipacket[i] & 0xe0) >> 5) - 1; |
3793 |
if (id < 0 || id >= PSM_GESTURE_FINGERS) |
3794 |
continue; |
3795 |
|
3796 |
if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) { |
3797 |
f[id] = sc->elanaction.fingers[id]; |
3798 |
f[id].x += imax(-f[id].x, |
3799 |
(signed char)pb->ipacket[i+1] * scale); |
3800 |
f[id].y += imax(-f[id].y, |
3801 |
(signed char)pb->ipacket[i+2] * scale); |
3802 |
} else { |
3803 |
VLOG(3, (LOG_DEBUG, "elantech: " |
3804 |
"HW v4 motion packet skipped\n")); |
3805 |
} |
3806 |
} |
3807 |
|
3808 |
break; |
3809 |
|
3810 |
case ELANTECH_PKT_TRACKPOINT: |
3811 |
/* 7 6 5 4 3 2 1 0 (LSB) |
3812 |
* ------------------------------------------- |
3813 |
* ipacket[0]: 0 0 SX SY 0 M R L |
3814 |
* ipacket[1]: ~SX 0 0 0 0 0 0 0 |
3815 |
* ipacket[2]: ~SY 0 0 0 0 0 0 0 |
3816 |
* ipacket[3]: 0 0 ~SY ~SX 0 1 1 0 |
3817 |
* ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 |
3818 |
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
3819 |
* ------------------------------------------- |
3820 |
* X and Y are written in two's complement spread |
3821 |
* over 9 bits with SX/SY the relative top bit and |
3822 |
* X7..X0 and Y7..Y0 the lower bits. |
3823 |
*/ |
3824 |
*x = (pb->ipacket[0] & 0x20) ? |
3825 |
pb->ipacket[4] - 256 : pb->ipacket[4]; |
3826 |
*y = (pb->ipacket[0] & 0x10) ? |
3827 |
pb->ipacket[5] - 256 : pb->ipacket[5]; |
3828 |
|
3829 |
trackpoint_button = |
3830 |
((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | |
3831 |
((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | |
3832 |
((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); |
3833 |
|
3834 |
ms->button = touchpad_button | trackpoint_button; |
3835 |
return (0); |
3836 |
|
3837 |
case ELANTECH_PKT_NOP: |
3838 |
return (0); |
3839 |
|
3840 |
default: |
3841 |
return (-1); |
3842 |
} |
3843 |
|
3844 |
for (id = 0; id < PSM_GESTURE_FINGERS; id++) |
3845 |
if (PSM_FINGER_IS_SET(f[id])) |
3846 |
VLOG(2, (LOG_DEBUG, "elantech: " |
3847 |
"finger %d: down [%d, %d], %d, %d, %d\n", id + 1, |
3848 |
f[id].x, f[id].y, f[id].p, f[id].w, f[id].flags)); |
3849 |
|
3850 |
/* Touchpad button presses */ |
3851 |
if (sc->elanhw.isclickpad) { |
3852 |
touchpad_button = |
3853 |
psmsoftbuttons(sc, f[0], pb->ipacket[0] & 0x03); |
3854 |
} else { |
3855 |
touchpad_button = |
3856 |
((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | |
3857 |
((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); |
3858 |
} |
3859 |
|
3860 |
ms->button = touchpad_button | trackpoint_button; |
3861 |
|
3315 |
/* |
3862 |
/* |
3316 |
* Use the extra buttons as a scrollwheel |
3863 |
* Send finger positions to movement smoother. |
3317 |
* |
3864 |
* Try to avoid nonreenterable code paths of movement smoother |
3318 |
* XXX X.Org uses the Z axis for vertical wheel only, |
3865 |
* like initialization and tap processing for 2nd finger. |
3319 |
* whereas moused(8) understands special values to differ |
|
|
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 |
*/ |
3866 |
*/ |
|
|
3867 |
for (id = 0; id < PSM_GESTURE_FINGERS; id++) { |
3329 |
|
3868 |
|
3330 |
if (ms->button & MOUSE_BUTTON4DOWN) { |
3869 |
if (!(PSM_FINGER_IS_SET(f[id]) || (id == 0 && nfingers == 0))) |
|
|
3870 |
continue; |
3871 |
if (id == 1 && sc->syninfo.two_finger_scroll == 0) |
3872 |
continue; |
3873 |
|
3874 |
reset_queue = 0; |
3875 |
|
3876 |
/* Avoid cursor jumping on switching real<->fuzzy position */ |
3877 |
if (PSM_FINGER_IS_SET(f[id]) && |
3878 |
((f[id].flags & PSM_FINGER_FUZZY) != |
3879 |
(sc->elanaction.fingers[id].flags & PSM_FINGER_FUZZY))) |
3880 |
reset_queue = 1; |
3881 |
|
3882 |
/* Reset 2-nd finger synaction queue on action start */ |
3883 |
if (id > 0 && !PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) { |
3884 |
reset_queue = 1; |
3885 |
} |
3886 |
|
3887 |
if (reset_queue) { |
3888 |
VLOG(3, (LOG_DEBUG, "elantech: " |
3889 |
"finger %d: reset synaptics queue\n", id + 1)); |
3890 |
sc->synaction[id].queue_cursor = 0; |
3891 |
sc->synaction[id].queue_len = 0; |
3892 |
sc->synaction[id].queue[0].x = f[id].x; |
3893 |
sc->synaction[id].queue[0].y = f[id].y; |
3894 |
sc->synaction[id].start_x = f[id].x; |
3895 |
sc->synaction[id].start_y = f[id].y; |
3896 |
sc->synaction[id].window_min = sc->syninfo.window_min; |
3897 |
sc->synaction[id].squelch_x = 0; |
3898 |
sc->synaction[id].squelch_y = 0; |
3899 |
sc->synaction[id].avg_dx = 0; |
3900 |
sc->synaction[id].avg_dy = 0; |
3901 |
sc->synaction[id].fingers_nb = 0; |
3902 |
sc->synaction[id].in_vscroll = 0; |
3903 |
} |
3904 |
|
3905 |
/* prevent palm detection for fuzzy finger touches */ |
3906 |
if (f[id].flags & PSM_FINGER_FUZZY) { |
3907 |
f[id].p = ELANTECH_FINGER_DEFAULT_P; |
3908 |
f[id].w = ELANTECH_FINGER_DEFAULT_W; |
3909 |
} |
3910 |
|
3911 |
psmgestures(sc, &sc->synaction[id], f[id], imin(nfingers, 3), |
3912 |
ms, x, y); |
3913 |
} |
3914 |
|
3915 |
/* Store current finger positions in action context */ |
3916 |
sc->elanaction.nfingers = nfingers; |
3917 |
for (id = 0; id < PSM_GESTURE_FINGERS; id++) { |
3918 |
if (PSM_FINGER_IS_SET(f[id])) |
3919 |
sc->elanaction.fingers[id] = f[id]; |
3920 |
if (id >= nfingers) |
3921 |
PSM_FINGER_RESET(sc->elanaction.fingers[id]); |
3922 |
} |
3923 |
|
3924 |
/* Use the extra buttons as a scrollwheel */ |
3925 |
if (ms->button & MOUSE_BUTTON4DOWN) |
3331 |
*z = -1; |
3926 |
*z = -1; |
3332 |
ms->button &= ~MOUSE_BUTTON4DOWN; |
3927 |
else if (ms->button & MOUSE_BUTTON5DOWN) |
3333 |
} else if (ms->button & MOUSE_BUTTON5DOWN) { |
|
|
3334 |
*z = 1; |
3928 |
*z = 1; |
3335 |
ms->button &= ~MOUSE_BUTTON5DOWN; |
3929 |
else if (ms->button & MOUSE_BUTTON6DOWN) |
3336 |
} else if (ms->button & MOUSE_BUTTON6DOWN) { |
|
|
3337 |
*z = -2; |
3930 |
*z = -2; |
3338 |
ms->button &= ~MOUSE_BUTTON6DOWN; |
3931 |
else if (ms->button & MOUSE_BUTTON7DOWN) |
3339 |
} else if (ms->button & MOUSE_BUTTON7DOWN) { |
|
|
3340 |
*z = 2; |
3932 |
*z = 2; |
3341 |
ms->button &= ~MOUSE_BUTTON7DOWN; |
3933 |
else |
3342 |
} else |
|
|
3343 |
*z = 0; |
3934 |
*z = 0; |
|
|
3935 |
ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN | |
3936 |
MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN); |
3344 |
|
3937 |
|
3345 |
return (0); |
3938 |
return (0); |
3346 |
} |
3939 |
} |
Lines 3413-3418
Link Here
|
3413 |
} |
4006 |
} |
3414 |
|
4007 |
|
3415 |
static void |
4008 |
static void |
|
|
4009 |
psmsoftintridle(void *arg) |
4010 |
{ |
4011 |
struct psm_softc *sc = arg; |
4012 |
packetbuf_t *pb; |
4013 |
|
4014 |
/* Invoke soft handler only when pqueue is empty. Otherwise it will be |
4015 |
* invoked from psmintr soon with pqueue filled with real data */ |
4016 |
if (sc->pqueue_start == sc->pqueue_end && |
4017 |
sc->idlepacket.inputbytes > 0) { |
4018 |
/* Grow circular queue backwards to avoid race with psmintr */ |
4019 |
if (--sc->pqueue_start < 0) |
4020 |
sc->pqueue_start = PSM_PACKETQUEUE - 1; |
4021 |
|
4022 |
pb = &sc->pqueue[sc->pqueue_start]; |
4023 |
memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t)); |
4024 |
VLOG(4, (LOG_DEBUG, |
4025 |
"psmsoftintridle: %02x %02x %02x %02x %02x %02x\n", |
4026 |
pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], |
4027 |
pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); |
4028 |
|
4029 |
psmsoftintr(arg); |
4030 |
} |
4031 |
} |
4032 |
|
4033 |
static void |
3416 |
psmsoftintr(void *arg) |
4034 |
psmsoftintr(void *arg) |
3417 |
{ |
4035 |
{ |
3418 |
/* |
4036 |
/* |
Lines 3465-3470
Link Here
|
3465 |
if (sc->config & PSM_CONFIG_FORCETAP) |
4083 |
if (sc->config & PSM_CONFIG_FORCETAP) |
3466 |
ms.button |= ((c & MOUSE_PS2_TAP)) ? |
4084 |
ms.button |= ((c & MOUSE_PS2_TAP)) ? |
3467 |
0 : MOUSE_BUTTON4DOWN; |
4085 |
0 : MOUSE_BUTTON4DOWN; |
|
|
4086 |
timevalclear(&sc->idletimeout); |
4087 |
sc->idlepacket.inputbytes = 0; |
3468 |
|
4088 |
|
3469 |
switch (sc->hw.model) { |
4089 |
switch (sc->hw.model) { |
3470 |
|
4090 |
|
Lines 3603-3608
Link Here
|
3603 |
goto next; |
4223 |
goto next; |
3604 |
break; |
4224 |
break; |
3605 |
|
4225 |
|
|
|
4226 |
case MOUSE_MODEL_ELANTECH: |
4227 |
if (proc_elantech(sc, pb, &ms, &x, &y, &z) != 0) |
4228 |
goto next; |
4229 |
break; |
4230 |
|
3606 |
case MOUSE_MODEL_TRACKPOINT: |
4231 |
case MOUSE_MODEL_TRACKPOINT: |
3607 |
case MOUSE_MODEL_GENERIC: |
4232 |
case MOUSE_MODEL_GENERIC: |
3608 |
default: |
4233 |
default: |
Lines 3627-3632
Link Here
|
3627 |
} |
4252 |
} |
3628 |
} |
4253 |
} |
3629 |
|
4254 |
|
|
|
4255 |
/* Store last packet for reinjection if it has not been set already */ |
4256 |
if (timevalisset(&sc->idletimeout) && sc->idlepacket.inputbytes == 0) |
4257 |
sc->idlepacket = *pb; |
4258 |
|
3630 |
ms.dx = x; |
4259 |
ms.dx = x; |
3631 |
ms.dy = y; |
4260 |
ms.dy = y; |
3632 |
ms.dz = z; |
4261 |
ms.dz = z; |
Lines 3673-3678
Link Here
|
3673 |
pgsigio(&sc->async, SIGIO, 0); |
4302 |
pgsigio(&sc->async, SIGIO, 0); |
3674 |
} |
4303 |
} |
3675 |
sc->state &= ~PSM_SOFTARMED; |
4304 |
sc->state &= ~PSM_SOFTARMED; |
|
|
4305 |
|
4306 |
/* schedule injection of predefined packet after idletimeout |
4307 |
* if no data packets have been received from psmintr */ |
4308 |
if (timevalisset(&sc->idletimeout)) { |
4309 |
sc->state |= PSM_SOFTARMED; |
4310 |
callout_reset(&sc->softcallout, tvtohz(&sc->idletimeout), |
4311 |
psmsoftintridle, sc); |
4312 |
VLOG(2, (LOG_DEBUG, "softintr: callout set: %d ticks\n", |
4313 |
tvtohz(&sc->idletimeout))); |
4314 |
} |
3676 |
splx(s); |
4315 |
splx(s); |
3677 |
} |
4316 |
} |
3678 |
|
4317 |
|
Lines 4106-4115
Link Here
|
4106 |
static int |
4745 |
static int |
4107 |
synaptics_sysctl(SYSCTL_HANDLER_ARGS) |
4746 |
synaptics_sysctl(SYSCTL_HANDLER_ARGS) |
4108 |
{ |
4747 |
{ |
|
|
4748 |
struct psm_softc *sc; |
4109 |
int error, arg; |
4749 |
int error, arg; |
4110 |
|
4750 |
|
|
|
4751 |
if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || |
4752 |
oidp->oid_arg2 > SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE) |
4753 |
return (EINVAL); |
4754 |
|
4755 |
sc = oidp->oid_arg1; |
4756 |
|
4111 |
/* Read the current value. */ |
4757 |
/* Read the current value. */ |
4112 |
arg = *(int *)oidp->oid_arg1; |
4758 |
arg = *(int *)((char *)sc + oidp->oid_arg2); |
4113 |
error = sysctl_handle_int(oidp, &arg, 0, req); |
4759 |
error = sysctl_handle_int(oidp, &arg, 0, req); |
4114 |
|
4760 |
|
4115 |
/* Sanity check. */ |
4761 |
/* Sanity check. */ |
Lines 4131-4144
Link Here
|
4131 |
return (EINVAL); |
4777 |
return (EINVAL); |
4132 |
break; |
4778 |
break; |
4133 |
case SYNAPTICS_SYSCTL_MARGIN_TOP: |
4779 |
case SYNAPTICS_SYSCTL_MARGIN_TOP: |
|
|
4780 |
case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: |
4781 |
case SYNAPTICS_SYSCTL_NA_TOP: |
4782 |
case SYNAPTICS_SYSCTL_NA_BOTTOM: |
4783 |
if (arg < 0 || arg > sc->synhw.maximumYCoord) |
4784 |
return (EINVAL); |
4785 |
break; |
4134 |
case SYNAPTICS_SYSCTL_MARGIN_RIGHT: |
4786 |
case SYNAPTICS_SYSCTL_MARGIN_RIGHT: |
4135 |
case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: |
|
|
4136 |
case SYNAPTICS_SYSCTL_MARGIN_LEFT: |
4787 |
case SYNAPTICS_SYSCTL_MARGIN_LEFT: |
4137 |
case SYNAPTICS_SYSCTL_NA_TOP: |
|
|
4138 |
case SYNAPTICS_SYSCTL_NA_RIGHT: |
4788 |
case SYNAPTICS_SYSCTL_NA_RIGHT: |
4139 |
case SYNAPTICS_SYSCTL_NA_BOTTOM: |
|
|
4140 |
case SYNAPTICS_SYSCTL_NA_LEFT: |
4789 |
case SYNAPTICS_SYSCTL_NA_LEFT: |
4141 |
if (arg < 0 || arg > 6143) |
4790 |
case SYNAPTICS_SYSCTL_SOFTBUTTON2_X: |
|
|
4791 |
case SYNAPTICS_SYSCTL_SOFTBUTTON3_X: |
4792 |
if (arg < 0 || arg > sc->synhw.maximumXCoord) |
4142 |
return (EINVAL); |
4793 |
return (EINVAL); |
4143 |
break; |
4794 |
break; |
4144 |
case SYNAPTICS_SYSCTL_WINDOW_MIN: |
4795 |
case SYNAPTICS_SYSCTL_WINDOW_MIN: |
Lines 4168-4193
Link Here
|
4168 |
return (EINVAL); |
4819 |
return (EINVAL); |
4169 |
break; |
4820 |
break; |
4170 |
case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: |
4821 |
case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: |
|
|
4822 |
if (arg < -sc->synhw.maximumXCoord || |
4823 |
arg > sc->synhw.maximumXCoord) |
4824 |
return (EINVAL); |
4825 |
break; |
4171 |
case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: |
4826 |
case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: |
4172 |
if (arg < -6143 || arg > 6143) |
4827 |
case SYNAPTICS_SYSCTL_SOFTBUTTONS_Y: |
|
|
4828 |
if (arg < -sc->synhw.maximumYCoord || |
4829 |
arg > sc->synhw.maximumYCoord) |
4173 |
return (EINVAL); |
4830 |
return (EINVAL); |
4174 |
break; |
4831 |
break; |
4175 |
case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: |
4832 |
case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: |
|
|
4833 |
case SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE: |
4176 |
if (arg < 0 || arg > 1) |
4834 |
if (arg < 0 || arg > 1) |
4177 |
return (EINVAL); |
4835 |
return (EINVAL); |
4178 |
break; |
4836 |
break; |
|
|
4837 |
case SYNAPTICS_SYSCTL_SOFTBUTTONS: |
4838 |
/* Softbuttons is clickpad only feature */ |
4839 |
if (!sc->synhw.capClickPad && arg != 0) |
4840 |
return (EINVAL); |
4841 |
/* Set predefined sizes for softbuttons */ |
4842 |
switch (arg) { |
4843 |
case 3: |
4844 |
sc->syninfo.softbutton3_x = |
4845 |
sc->synhw.maximumXCoord * 2 / 3; |
4846 |
sc->syninfo.softbutton2_x = |
4847 |
sc->synhw.maximumXCoord / 3; |
4848 |
sc->syninfo.softbuttons_y = |
4849 |
sc->synhw.maximumYCoord / 4; |
4850 |
break; |
4851 |
case 2: |
4852 |
sc->syninfo.softbutton3_x = |
4853 |
sc->synhw.maximumXCoord / 2; |
4854 |
sc->syninfo.softbutton2_x = 0; |
4855 |
sc->syninfo.softbuttons_y = |
4856 |
sc->synhw.maximumYCoord / 4; |
4857 |
break; |
4858 |
case 1: |
4859 |
case 0: |
4860 |
sc->syninfo.softbutton3_x = 0; |
4861 |
sc->syninfo.softbutton2_x = 0; |
4862 |
sc->syninfo.softbuttons_y = 0; |
4863 |
break; |
4864 |
default: |
4865 |
return (EINVAL); |
4866 |
} |
4867 |
break; |
4179 |
default: |
4868 |
default: |
4180 |
return (EINVAL); |
4869 |
return (EINVAL); |
4181 |
} |
4870 |
} |
4182 |
|
4871 |
|
4183 |
/* Update. */ |
4872 |
/* Update. */ |
4184 |
*(int *)oidp->oid_arg1 = arg; |
4873 |
*(int *)((char *)sc + oidp->oid_arg2) = arg; |
4185 |
|
4874 |
|
4186 |
return (error); |
4875 |
return (error); |
4187 |
} |
4876 |
} |
4188 |
|
4877 |
|
4189 |
static void |
4878 |
static void |
4190 |
synaptics_sysctl_create_tree(struct psm_softc *sc) |
4879 |
synaptics_sysctl_create_tree(struct psm_softc *sc, const char *name, |
|
|
4880 |
const char *descr) |
4191 |
{ |
4881 |
{ |
4192 |
|
4882 |
|
4193 |
if (sc->syninfo.sysctl_tree != NULL) |
4883 |
if (sc->syninfo.sysctl_tree != NULL) |
Lines 4196-4203
Link Here
|
4196 |
/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ |
4886 |
/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ |
4197 |
sysctl_ctx_init(&sc->syninfo.sysctl_ctx); |
4887 |
sysctl_ctx_init(&sc->syninfo.sysctl_ctx); |
4198 |
sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, |
4888 |
sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, |
4199 |
SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "synaptics", CTLFLAG_RD, |
4889 |
SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, name, CTLFLAG_RD, |
4200 |
0, "Synaptics TouchPad"); |
4890 |
0, descr); |
4201 |
|
4891 |
|
4202 |
/* hw.psm.synaptics.directional_scrolls. */ |
4892 |
/* hw.psm.synaptics.directional_scrolls. */ |
4203 |
sc->syninfo.directional_scrolls = 0; |
4893 |
sc->syninfo.directional_scrolls = 0; |
Lines 4230-4236
Link Here
|
4230 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4920 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4231 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4921 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4232 |
"min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4922 |
"min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4233 |
&sc->syninfo.min_pressure, SYNAPTICS_SYSCTL_MIN_PRESSURE, |
4923 |
sc, SYNAPTICS_SYSCTL_MIN_PRESSURE, |
4234 |
synaptics_sysctl, "I", |
4924 |
synaptics_sysctl, "I", |
4235 |
"Minimum pressure required to start an action"); |
4925 |
"Minimum pressure required to start an action"); |
4236 |
|
4926 |
|
Lines 4239-4245
Link Here
|
4239 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4929 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4240 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4930 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4241 |
"max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4931 |
"max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4242 |
&sc->syninfo.max_pressure, SYNAPTICS_SYSCTL_MAX_PRESSURE, |
4932 |
sc, SYNAPTICS_SYSCTL_MAX_PRESSURE, |
4243 |
synaptics_sysctl, "I", |
4933 |
synaptics_sysctl, "I", |
4244 |
"Maximum pressure to detect palm"); |
4934 |
"Maximum pressure to detect palm"); |
4245 |
|
4935 |
|
Lines 4248-4254
Link Here
|
4248 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4938 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4249 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4939 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4250 |
"max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4940 |
"max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4251 |
&sc->syninfo.max_width, SYNAPTICS_SYSCTL_MAX_WIDTH, |
4941 |
sc, SYNAPTICS_SYSCTL_MAX_WIDTH, |
4252 |
synaptics_sysctl, "I", |
4942 |
synaptics_sysctl, "I", |
4253 |
"Maximum finger width to detect palm"); |
4943 |
"Maximum finger width to detect palm"); |
4254 |
|
4944 |
|
Lines 4257-4263
Link Here
|
4257 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4947 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4258 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4948 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4259 |
"margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4949 |
"margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4260 |
&sc->syninfo.margin_top, SYNAPTICS_SYSCTL_MARGIN_TOP, |
4950 |
sc, SYNAPTICS_SYSCTL_MARGIN_TOP, |
4261 |
synaptics_sysctl, "I", |
4951 |
synaptics_sysctl, "I", |
4262 |
"Top margin"); |
4952 |
"Top margin"); |
4263 |
|
4953 |
|
Lines 4266-4272
Link Here
|
4266 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4956 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4267 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4957 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4268 |
"margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4958 |
"margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4269 |
&sc->syninfo.margin_right, SYNAPTICS_SYSCTL_MARGIN_RIGHT, |
4959 |
sc, SYNAPTICS_SYSCTL_MARGIN_RIGHT, |
4270 |
synaptics_sysctl, "I", |
4960 |
synaptics_sysctl, "I", |
4271 |
"Right margin"); |
4961 |
"Right margin"); |
4272 |
|
4962 |
|
Lines 4275-4281
Link Here
|
4275 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4965 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4276 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4966 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4277 |
"margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4967 |
"margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4278 |
&sc->syninfo.margin_bottom, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, |
4968 |
sc, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, |
4279 |
synaptics_sysctl, "I", |
4969 |
synaptics_sysctl, "I", |
4280 |
"Bottom margin"); |
4970 |
"Bottom margin"); |
4281 |
|
4971 |
|
Lines 4284-4290
Link Here
|
4284 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4974 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4285 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4975 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4286 |
"margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4976 |
"margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4287 |
&sc->syninfo.margin_left, SYNAPTICS_SYSCTL_MARGIN_LEFT, |
4977 |
sc, SYNAPTICS_SYSCTL_MARGIN_LEFT, |
4288 |
synaptics_sysctl, "I", |
4978 |
synaptics_sysctl, "I", |
4289 |
"Left margin"); |
4979 |
"Left margin"); |
4290 |
|
4980 |
|
Lines 4293-4299
Link Here
|
4293 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4983 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4294 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4984 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4295 |
"na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4985 |
"na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4296 |
&sc->syninfo.na_top, SYNAPTICS_SYSCTL_NA_TOP, |
4986 |
sc, SYNAPTICS_SYSCTL_NA_TOP, |
4297 |
synaptics_sysctl, "I", |
4987 |
synaptics_sysctl, "I", |
4298 |
"Top noisy area, where weight_previous_na is used instead " |
4988 |
"Top noisy area, where weight_previous_na is used instead " |
4299 |
"of weight_previous"); |
4989 |
"of weight_previous"); |
Lines 4303-4309
Link Here
|
4303 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4993 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4304 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4994 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4305 |
"na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4995 |
"na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4306 |
&sc->syninfo.na_right, SYNAPTICS_SYSCTL_NA_RIGHT, |
4996 |
sc, SYNAPTICS_SYSCTL_NA_RIGHT, |
4307 |
synaptics_sysctl, "I", |
4997 |
synaptics_sysctl, "I", |
4308 |
"Right noisy area, where weight_previous_na is used instead " |
4998 |
"Right noisy area, where weight_previous_na is used instead " |
4309 |
"of weight_previous"); |
4999 |
"of weight_previous"); |
Lines 4313-4319
Link Here
|
4313 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5003 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4314 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5004 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4315 |
"na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5005 |
"na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4316 |
&sc->syninfo.na_bottom, SYNAPTICS_SYSCTL_NA_BOTTOM, |
5006 |
sc, SYNAPTICS_SYSCTL_NA_BOTTOM, |
4317 |
synaptics_sysctl, "I", |
5007 |
synaptics_sysctl, "I", |
4318 |
"Bottom noisy area, where weight_previous_na is used instead " |
5008 |
"Bottom noisy area, where weight_previous_na is used instead " |
4319 |
"of weight_previous"); |
5009 |
"of weight_previous"); |
Lines 4323-4329
Link Here
|
4323 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5013 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4324 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5014 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4325 |
"na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5015 |
"na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4326 |
&sc->syninfo.na_left, SYNAPTICS_SYSCTL_NA_LEFT, |
5016 |
sc, SYNAPTICS_SYSCTL_NA_LEFT, |
4327 |
synaptics_sysctl, "I", |
5017 |
synaptics_sysctl, "I", |
4328 |
"Left noisy area, where weight_previous_na is used instead " |
5018 |
"Left noisy area, where weight_previous_na is used instead " |
4329 |
"of weight_previous"); |
5019 |
"of weight_previous"); |
Lines 4333-4339
Link Here
|
4333 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5023 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4334 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5024 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4335 |
"window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5025 |
"window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4336 |
&sc->syninfo.window_min, SYNAPTICS_SYSCTL_WINDOW_MIN, |
5026 |
sc, SYNAPTICS_SYSCTL_WINDOW_MIN, |
4337 |
synaptics_sysctl, "I", |
5027 |
synaptics_sysctl, "I", |
4338 |
"Minimum window size to start an action"); |
5028 |
"Minimum window size to start an action"); |
4339 |
|
5029 |
|
Lines 4342-4348
Link Here
|
4342 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5032 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4343 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5033 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4344 |
"window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5034 |
"window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4345 |
&sc->syninfo.window_max, SYNAPTICS_SYSCTL_WINDOW_MAX, |
5035 |
sc, SYNAPTICS_SYSCTL_WINDOW_MAX, |
4346 |
synaptics_sysctl, "I", |
5036 |
synaptics_sysctl, "I", |
4347 |
"Maximum window size"); |
5037 |
"Maximum window size"); |
4348 |
|
5038 |
|
Lines 4351-4357
Link Here
|
4351 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5041 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4352 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5042 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4353 |
"multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5043 |
"multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4354 |
&sc->syninfo.multiplicator, SYNAPTICS_SYSCTL_MULTIPLICATOR, |
5044 |
sc, SYNAPTICS_SYSCTL_MULTIPLICATOR, |
4355 |
synaptics_sysctl, "I", |
5045 |
synaptics_sysctl, "I", |
4356 |
"Multiplicator to increase precision in averages and divisions"); |
5046 |
"Multiplicator to increase precision in averages and divisions"); |
4357 |
|
5047 |
|
Lines 4360-4366
Link Here
|
4360 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5050 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4361 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5051 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4362 |
"weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5052 |
"weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4363 |
&sc->syninfo.weight_current, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, |
5053 |
sc, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, |
4364 |
synaptics_sysctl, "I", |
5054 |
synaptics_sysctl, "I", |
4365 |
"Weight of the current movement in the new average"); |
5055 |
"Weight of the current movement in the new average"); |
4366 |
|
5056 |
|
Lines 4369-4375
Link Here
|
4369 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5059 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4370 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5060 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4371 |
"weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5061 |
"weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4372 |
&sc->syninfo.weight_previous, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, |
5062 |
sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, |
4373 |
synaptics_sysctl, "I", |
5063 |
synaptics_sysctl, "I", |
4374 |
"Weight of the previous average"); |
5064 |
"Weight of the previous average"); |
4375 |
|
5065 |
|
Lines 4378-4385
Link Here
|
4378 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5068 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4379 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5069 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4380 |
"weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5070 |
"weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4381 |
&sc->syninfo.weight_previous_na, |
5071 |
sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, |
4382 |
SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, |
|
|
4383 |
synaptics_sysctl, "I", |
5072 |
synaptics_sysctl, "I", |
4384 |
"Weight of the previous average (inside the noisy area)"); |
5073 |
"Weight of the previous average (inside the noisy area)"); |
4385 |
|
5074 |
|
Lines 4388-4395
Link Here
|
4388 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5077 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4389 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5078 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4390 |
"weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5079 |
"weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4391 |
&sc->syninfo.weight_len_squared, |
5080 |
sc, SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, |
4392 |
SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, |
|
|
4393 |
synaptics_sysctl, "I", |
5081 |
synaptics_sysctl, "I", |
4394 |
"Length (squared) of segments where weight_previous " |
5082 |
"Length (squared) of segments where weight_previous " |
4395 |
"starts to decrease"); |
5083 |
"starts to decrease"); |
Lines 4399-4405
Link Here
|
4399 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5087 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4400 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5088 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4401 |
"div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5089 |
"div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4402 |
&sc->syninfo.div_min, SYNAPTICS_SYSCTL_DIV_MIN, |
5090 |
sc, SYNAPTICS_SYSCTL_DIV_MIN, |
4403 |
synaptics_sysctl, "I", |
5091 |
synaptics_sysctl, "I", |
4404 |
"Divisor for fast movements"); |
5092 |
"Divisor for fast movements"); |
4405 |
|
5093 |
|
Lines 4408-4414
Link Here
|
4408 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5096 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4409 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5097 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4410 |
"div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5098 |
"div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4411 |
&sc->syninfo.div_max, SYNAPTICS_SYSCTL_DIV_MAX, |
5099 |
sc, SYNAPTICS_SYSCTL_DIV_MAX, |
4412 |
synaptics_sysctl, "I", |
5100 |
synaptics_sysctl, "I", |
4413 |
"Divisor for slow movements"); |
5101 |
"Divisor for slow movements"); |
4414 |
|
5102 |
|
Lines 4417-4423
Link Here
|
4417 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5105 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4418 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5106 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4419 |
"div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5107 |
"div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4420 |
&sc->syninfo.div_max_na, SYNAPTICS_SYSCTL_DIV_MAX_NA, |
5108 |
sc, SYNAPTICS_SYSCTL_DIV_MAX_NA, |
4421 |
synaptics_sysctl, "I", |
5109 |
synaptics_sysctl, "I", |
4422 |
"Divisor with slow movements (inside the noisy area)"); |
5110 |
"Divisor with slow movements (inside the noisy area)"); |
4423 |
|
5111 |
|
Lines 4426-4432
Link Here
|
4426 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5114 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4427 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5115 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4428 |
"div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5116 |
"div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4429 |
&sc->syninfo.div_len, SYNAPTICS_SYSCTL_DIV_LEN, |
5117 |
sc, SYNAPTICS_SYSCTL_DIV_LEN, |
4430 |
synaptics_sysctl, "I", |
5118 |
synaptics_sysctl, "I", |
4431 |
"Length of segments where div_max starts to decrease"); |
5119 |
"Length of segments where div_max starts to decrease"); |
4432 |
|
5120 |
|
Lines 4435-4441
Link Here
|
4435 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5123 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4436 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5124 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4437 |
"tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5125 |
"tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4438 |
&sc->syninfo.tap_max_delta, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, |
5126 |
sc, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, |
4439 |
synaptics_sysctl, "I", |
5127 |
synaptics_sysctl, "I", |
4440 |
"Length of segments above which a tap is ignored"); |
5128 |
"Length of segments above which a tap is ignored"); |
4441 |
|
5129 |
|
Lines 4444-4460
Link Here
|
4444 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5132 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4445 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5133 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4446 |
"tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5134 |
"tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4447 |
&sc->syninfo.tap_min_queue, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, |
5135 |
sc, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, |
4448 |
synaptics_sysctl, "I", |
5136 |
synaptics_sysctl, "I", |
4449 |
"Number of packets required to consider a tap"); |
5137 |
"Number of packets required to consider a tap"); |
4450 |
|
5138 |
|
4451 |
/* hw.psm.synaptics.taphold_timeout. */ |
5139 |
/* hw.psm.synaptics.taphold_timeout. */ |
4452 |
sc->synaction.in_taphold = 0; |
5140 |
sc->synaction[0].in_taphold = 0; |
4453 |
sc->syninfo.taphold_timeout = tap_timeout; |
5141 |
sc->syninfo.taphold_timeout = tap_timeout; |
4454 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5142 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4455 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5143 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4456 |
"taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5144 |
"taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4457 |
&sc->syninfo.taphold_timeout, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, |
5145 |
sc, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, |
4458 |
synaptics_sysctl, "I", |
5146 |
synaptics_sysctl, "I", |
4459 |
"Maximum elapsed time between two taps to consider a tap-hold " |
5147 |
"Maximum elapsed time between two taps to consider a tap-hold " |
4460 |
"action"); |
5148 |
"action"); |
Lines 4464-4470
Link Here
|
4464 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5152 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4465 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5153 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4466 |
"vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5154 |
"vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4467 |
&sc->syninfo.vscroll_hor_area, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, |
5155 |
sc, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, |
4468 |
synaptics_sysctl, "I", |
5156 |
synaptics_sysctl, "I", |
4469 |
"Area reserved for horizontal virtual scrolling"); |
5157 |
"Area reserved for horizontal virtual scrolling"); |
4470 |
|
5158 |
|
Lines 4473-4479
Link Here
|
4473 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5161 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4474 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5162 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4475 |
"vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5163 |
"vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4476 |
&sc->syninfo.vscroll_ver_area, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, |
5164 |
sc, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, |
4477 |
synaptics_sysctl, "I", |
5165 |
synaptics_sysctl, "I", |
4478 |
"Area reserved for vertical virtual scrolling"); |
5166 |
"Area reserved for vertical virtual scrolling"); |
4479 |
|
5167 |
|
Lines 4482-4489
Link Here
|
4482 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5170 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4483 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5171 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4484 |
"vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5172 |
"vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4485 |
&sc->syninfo.vscroll_min_delta, |
5173 |
sc, SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, |
4486 |
SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, |
|
|
4487 |
synaptics_sysctl, "I", |
5174 |
synaptics_sysctl, "I", |
4488 |
"Minimum movement to consider virtual scrolling"); |
5175 |
"Minimum movement to consider virtual scrolling"); |
4489 |
|
5176 |
|
Lines 4492-4498
Link Here
|
4492 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5179 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4493 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5180 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4494 |
"vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5181 |
"vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4495 |
&sc->syninfo.vscroll_div_min, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, |
5182 |
sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, |
4496 |
synaptics_sysctl, "I", |
5183 |
synaptics_sysctl, "I", |
4497 |
"Divisor for fast scrolling"); |
5184 |
"Divisor for fast scrolling"); |
4498 |
|
5185 |
|
Lines 4501-4507
Link Here
|
4501 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5188 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4502 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5189 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4503 |
"vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5190 |
"vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4504 |
&sc->syninfo.vscroll_div_max, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, |
5191 |
sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, |
4505 |
synaptics_sysctl, "I", |
5192 |
synaptics_sysctl, "I", |
4506 |
"Divisor for slow scrolling"); |
5193 |
"Divisor for slow scrolling"); |
4507 |
|
5194 |
|
Lines 4510-4518
Link Here
|
4510 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5197 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
4511 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5198 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
4512 |
"touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5199 |
"touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
4513 |
&sc->syninfo.touchpad_off, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, |
5200 |
sc, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, |
4514 |
synaptics_sysctl, "I", |
5201 |
synaptics_sysctl, "I", |
4515 |
"Turn off touchpad"); |
5202 |
"Turn off touchpad"); |
|
|
5203 |
|
5204 |
sc->syninfo.softbuttons = 0; |
5205 |
sc->syninfo.softbuttons_y = 0; |
5206 |
sc->syninfo.softbutton2_x = 0; |
5207 |
sc->syninfo.softbutton3_x = 0; |
5208 |
sc->syninfo.softbutton_nomove = 0; |
5209 |
|
5210 |
/* skip softbuttons sysctl on not clickpads */ |
5211 |
if (!sc->synhw.capClickPad) |
5212 |
return; |
5213 |
|
5214 |
/* hw.psm.synaptics.softbuttons */ |
5215 |
sc->syninfo.softbuttons = 3; |
5216 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5217 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5218 |
"softbuttons", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5219 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTONS, |
5220 |
synaptics_sysctl, "I", |
5221 |
"Enables top or bottom edges to be a softbuttons on clickpads"); |
5222 |
|
5223 |
/* hw.psm.synaptics.softbuttons_y */ |
5224 |
sc->syninfo.softbuttons_y = sc->synhw.maximumYCoord / 4; |
5225 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5226 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5227 |
"softbuttons_y", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5228 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTONS_Y, |
5229 |
synaptics_sysctl, "I", |
5230 |
"Vertical size of softbuttons area"); |
5231 |
|
5232 |
/* hw.psm.synaptics.softbutton2_x */ |
5233 |
sc->syninfo.softbutton2_x = sc->synhw.maximumXCoord / 3; |
5234 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5235 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5236 |
"softbutton2_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5237 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTON2_X, |
5238 |
synaptics_sysctl, "I", |
5239 |
"Horisontal position of 2-nd softbutton left edge (0-disable)"); |
5240 |
|
5241 |
/* hw.psm.synaptics.softbutton3_x */ |
5242 |
sc->syninfo.softbutton3_x = sc->synhw.maximumXCoord * 2 / 3; |
5243 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5244 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5245 |
"softbutton3_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5246 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTON3_X, |
5247 |
synaptics_sysctl, "I", |
5248 |
"Horisontal position of 3-rd softbutton left edge (0-disable)"); |
5249 |
|
5250 |
/* hw.psm.synaptics.softbutton_nomove */ |
5251 |
sc->syninfo.softbutton_nomove = 0; |
5252 |
SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, |
5253 |
SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, |
5254 |
"softbutton_nomove", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, |
5255 |
sc, SYNAPTICS_SYSCTL_SOFTBUTTON_NOMOVE, |
5256 |
synaptics_sysctl, "I", |
5257 |
"Disable movement on the bottom edge area so it works as buttons"); |
4516 |
} |
5258 |
} |
4517 |
|
5259 |
|
4518 |
static int |
5260 |
static int |
Lines 4854-4860
Link Here
|
4854 |
|
5596 |
|
4855 |
if (arg == PROBE) { |
5597 |
if (arg == PROBE) { |
4856 |
/* Create sysctl tree. */ |
5598 |
/* Create sysctl tree. */ |
4857 |
synaptics_sysctl_create_tree(sc); |
5599 |
synaptics_sysctl_create_tree(sc, "synaptics", |
|
|
5600 |
"Synaptics TouchPad"); |
4858 |
sc->hw.buttons = buttons; |
5601 |
sc->hw.buttons = buttons; |
4859 |
} |
5602 |
} |
4860 |
|
5603 |
|
Lines 5171-5176
Link Here
|
5171 |
return (TRUE); /* PS/2 absolute mode */ |
5914 |
return (TRUE); /* PS/2 absolute mode */ |
5172 |
} |
5915 |
} |
5173 |
|
5916 |
|
|
|
5917 |
/* Elantech Touchpad */ |
5918 |
static int |
5919 |
elantech_read_1(KBDC kbdc, int hwversion, int reg, int *val) |
5920 |
{ |
5921 |
int res, readcmd, retidx; |
5922 |
int resp[3]; |
5923 |
|
5924 |
readcmd = hwversion == 2 ? ELANTECH_REG_READ : ELANTECH_REG_RDWR; |
5925 |
retidx = hwversion == 4 ? 1 : 0; |
5926 |
|
5927 |
res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5928 |
res |= send_aux_command(kbdc, readcmd) != PSM_ACK; |
5929 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5930 |
res |= send_aux_command(kbdc, reg) != PSM_ACK; |
5931 |
res |= get_mouse_status(kbdc, resp, 0, 3) != 3; |
5932 |
|
5933 |
if (res == 0) |
5934 |
*val = resp[retidx]; |
5935 |
|
5936 |
return (res); |
5937 |
} |
5938 |
|
5939 |
static int |
5940 |
elantech_write_1(KBDC kbdc, int hwversion, int reg, int val) |
5941 |
{ |
5942 |
int res, writecmd; |
5943 |
|
5944 |
writecmd = hwversion == 2 ? ELANTECH_REG_WRITE : ELANTECH_REG_RDWR; |
5945 |
|
5946 |
res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5947 |
res |= send_aux_command(kbdc, writecmd) != PSM_ACK; |
5948 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5949 |
res |= send_aux_command(kbdc, reg) != PSM_ACK; |
5950 |
if (hwversion == 4) { |
5951 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5952 |
res |= send_aux_command(kbdc, writecmd) != PSM_ACK; |
5953 |
} |
5954 |
res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5955 |
res |= send_aux_command(kbdc, val) != PSM_ACK; |
5956 |
res |= set_mouse_scaling(kbdc, 1) == 0; |
5957 |
|
5958 |
return (res); |
5959 |
} |
5960 |
|
5961 |
static int |
5962 |
elantech_cmd(KBDC kbdc, int hwversion, int cmd, int *resp) |
5963 |
{ |
5964 |
int res; |
5965 |
|
5966 |
if (hwversion == 2) { |
5967 |
res = set_mouse_scaling(kbdc, 1) == 0; |
5968 |
res |= mouse_ext_command(kbdc, cmd) == 0; |
5969 |
} else { |
5970 |
res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; |
5971 |
res |= send_aux_command(kbdc, cmd) != PSM_ACK; |
5972 |
} |
5973 |
res |= get_mouse_status(kbdc, resp, 0, 3) != 3; |
5974 |
|
5975 |
return (res); |
5976 |
} |
5977 |
|
5978 |
static int |
5979 |
elantech_init(KBDC kbdc, elantechhw_t *elanhw) |
5980 |
{ |
5981 |
int i, val, res, hwversion, reg10; |
5982 |
|
5983 |
/* set absolute mode */ |
5984 |
hwversion = elanhw->hwversion; |
5985 |
reg10 = -1; |
5986 |
switch (hwversion) { |
5987 |
case 2: |
5988 |
reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4; |
5989 |
res = elantech_write_1(kbdc, hwversion, 0x10, reg10); |
5990 |
if (res) |
5991 |
break; |
5992 |
res = elantech_write_1(kbdc, hwversion, 0x11, 0x8A); |
5993 |
break; |
5994 |
case 3: |
5995 |
reg10 = 0x0b; |
5996 |
res = elantech_write_1(kbdc, hwversion, 0x10, reg10); |
5997 |
break; |
5998 |
case 4: |
5999 |
res = elantech_write_1(kbdc, hwversion, 0x07, 0x01); |
6000 |
break; |
6001 |
default: |
6002 |
res = 1; |
6003 |
} |
6004 |
|
6005 |
/* Read back reg 0x10 to ensure hardware is ready. */ |
6006 |
if (res == 0 && reg10 >= 0) { |
6007 |
for (i = 0; i < 5; i++) { |
6008 |
if (elantech_read_1(kbdc, hwversion, 0x10, &val) == 0) |
6009 |
break; |
6010 |
pause("elan", 1); |
6011 |
} |
6012 |
if (i == 5) |
6013 |
res = 1; |
6014 |
} |
6015 |
|
6016 |
if (res) |
6017 |
printf("couldn't set absolute mode\n"); |
6018 |
|
6019 |
return (res); |
6020 |
} |
6021 |
|
6022 |
static void |
6023 |
elantech_init_synaptics(struct psm_softc *sc) |
6024 |
{ |
6025 |
|
6026 |
/* Set capabilites required by movement smother */ |
6027 |
sc->synhw.infoMajor = sc->elanhw.hwversion; |
6028 |
sc->synhw.infoMinor = sc->elanhw.fwversion; |
6029 |
sc->synhw.infoXupmm = (sc->elanhw.dpix * 10 + 5) / 254; |
6030 |
sc->synhw.infoYupmm = (sc->elanhw.dpiy * 10 + 5) / 254; |
6031 |
sc->synhw.verticalScroll = 0; |
6032 |
sc->synhw.nExtendedQueries = 4; |
6033 |
sc->synhw.capExtended = 1; |
6034 |
sc->synhw.capPassthrough = sc->elanhw.hastrackpad; |
6035 |
sc->synhw.capClickPad = sc->elanhw.isclickpad; |
6036 |
sc->synhw.capMultiFinger = 1; |
6037 |
sc->synhw.capPalmDetect = 1; |
6038 |
sc->synhw.capPen = 0; |
6039 |
sc->synhw.capReportsMax = 1; |
6040 |
sc->synhw.maximumXCoord = sc->elanhw.sizex; |
6041 |
sc->synhw.maximumYCoord = sc->elanhw.sizey; |
6042 |
sc->synhw.capReportsMin = 1; |
6043 |
sc->synhw.minimumXCoord = 0; |
6044 |
sc->synhw.minimumYCoord = 0; |
6045 |
|
6046 |
if (sc->syninfo.sysctl_tree == NULL) { |
6047 |
synaptics_sysctl_create_tree(sc, "elantech", |
6048 |
"Elantech Touchpad"); |
6049 |
|
6050 |
/* |
6051 |
* Adjust synaptic smoother tunables |
6052 |
* 1. Disable finger detection pressure threshold. Unlike |
6053 |
* synaptics we assume the finger is acting when packet with |
6054 |
* its X&Y arrives not when pressure exceedes some threshold |
6055 |
* 2. Disable unrelated features like margins and noisy areas |
6056 |
* 3. Disable virtual scroll areas as 2nd finger is preferable |
6057 |
* 4. Scale down divisors and movement lengths by a factor of 3 |
6058 |
* where 3 is Synaptics to Elantech (~2200/800) dpi ratio |
6059 |
*/ |
6060 |
|
6061 |
/* Disable finger detection pressure threshold */ |
6062 |
sc->syninfo.min_pressure = 1; |
6063 |
|
6064 |
/* Use full area of touchpad */ |
6065 |
sc->syninfo.margin_top = 0; |
6066 |
sc->syninfo.margin_right = 0; |
6067 |
sc->syninfo.margin_bottom = 0; |
6068 |
sc->syninfo.margin_left = 0; |
6069 |
/* Disable noisy area */ |
6070 |
sc->syninfo.na_top = 0; |
6071 |
sc->syninfo.na_right = 0; |
6072 |
sc->syninfo.na_bottom = 0; |
6073 |
sc->syninfo.na_left = 0; |
6074 |
|
6075 |
/* tune divisors and movement lengths */ |
6076 |
sc->syninfo.weight_len_squared = 200; |
6077 |
sc->syninfo.div_min = 3; |
6078 |
sc->syninfo.div_max = 6; |
6079 |
sc->syninfo.div_max_na = 10; |
6080 |
sc->syninfo.div_len = 30; |
6081 |
sc->syninfo.tap_max_delta = 25; |
6082 |
|
6083 |
/* disable virtual scrolling areas and tune its divisors */ |
6084 |
sc->syninfo.vscroll_hor_area = 0; |
6085 |
sc->syninfo.vscroll_ver_area = 0; |
6086 |
sc->syninfo.vscroll_min_delta = 15; |
6087 |
sc->syninfo.vscroll_div_min = 30; |
6088 |
sc->syninfo.vscroll_div_max = 50; |
6089 |
} |
6090 |
|
6091 |
return; |
6092 |
} |
6093 |
|
6094 |
static int |
6095 |
enable_elantech(struct psm_softc *sc, enum probearg arg) |
6096 |
{ |
6097 |
static const int ic2hw[] = |
6098 |
/*IC: 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
6099 |
{ 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 0, 0, 4, 4, 0 }; |
6100 |
elantechhw_t elanhw; |
6101 |
int icversion, hwversion, dptracex, dptracey, id, resp[3]; |
6102 |
KBDC kbdc = sc->kbdc; |
6103 |
|
6104 |
VLOG(3, (LOG_DEBUG, "elantech: BEGIN init\n")); |
6105 |
|
6106 |
set_mouse_scaling(kbdc, 1); |
6107 |
set_mouse_scaling(kbdc, 1); |
6108 |
set_mouse_scaling(kbdc, 1); |
6109 |
if (get_mouse_status(kbdc, resp, 0, 3) != 3) |
6110 |
return (FALSE); |
6111 |
|
6112 |
if (!ELANTECH_MAGIC(resp)) |
6113 |
return (FALSE); |
6114 |
|
6115 |
/* Identify the Touchpad version. */ |
6116 |
if (elantech_cmd(kbdc, 2, ELANTECH_FW_VERSION, resp)) |
6117 |
return (FALSE); |
6118 |
|
6119 |
bzero(&elanhw, sizeof(elanhw)); |
6120 |
|
6121 |
elanhw.fwversion = (resp[0] << 16) | (resp[1] << 8) | resp[2]; |
6122 |
icversion = resp[0] & 0x0f; |
6123 |
hwversion = ic2hw[icversion]; |
6124 |
|
6125 |
if (verbose >= 2) |
6126 |
printf("Elantech touchpad hardware v.%d firmware v.0x%06x\n", |
6127 |
hwversion, elanhw.fwversion); |
6128 |
|
6129 |
if (ELANTECH_HW_IS_V1(elanhw.fwversion)) { |
6130 |
printf (" Unsupported touchpad hardware (v1)\n"); |
6131 |
return (FALSE); |
6132 |
} |
6133 |
if (hwversion == 0) { |
6134 |
printf (" Unknown touchpad hardware (firmware v.0x%06x)\n", |
6135 |
elanhw.fwversion); |
6136 |
return (FALSE); |
6137 |
} |
6138 |
|
6139 |
/* Get the Touchpad model information. */ |
6140 |
elanhw.hwversion = hwversion; |
6141 |
elanhw.isclickpad = (resp[1] & 0x10) != 0; |
6142 |
elanhw.hascrc = (resp[1] & 0x40) != 0; |
6143 |
elanhw.haspressure = elanhw.fwversion >= 0x020800; |
6144 |
|
6145 |
/* Read the capability bits. */ |
6146 |
if (elantech_cmd(kbdc, hwversion, ELANTECH_CAPABILITIES, resp) != 0) { |
6147 |
printf(" Failed to read capability bits\n"); |
6148 |
return (FALSE); |
6149 |
} |
6150 |
|
6151 |
elanhw.ntracesx = resp[1] - 1; |
6152 |
elanhw.ntracesy = resp[2] - 1; |
6153 |
elanhw.hastrackpad = (resp[0] & 0x80) != 0; |
6154 |
|
6155 |
/* Get the touchpad resolution */ |
6156 |
switch (hwversion) { |
6157 |
case 2: |
6158 |
elanhw.dpix = elanhw.dpiy = 400; |
6159 |
break; |
6160 |
case 4: |
6161 |
if (elantech_cmd(kbdc, hwversion, ELANTECH_RESOLUTION, resp) |
6162 |
== 0) { |
6163 |
elanhw.dpix = (resp[1] & 0x0f) * 10 + 790; |
6164 |
elanhw.dpiy = ((resp[1] & 0xf0) >> 4) * 10 + 790; |
6165 |
break; |
6166 |
} |
6167 |
/* FALLTHROUGH */ |
6168 |
case 3: |
6169 |
elanhw.dpix = elanhw.dpiy = 800; |
6170 |
break; |
6171 |
} |
6172 |
|
6173 |
if (!elantech_support) |
6174 |
return (FALSE); |
6175 |
|
6176 |
if (elantech_init(kbdc, &elanhw)) { |
6177 |
printf("couldn't initialize elantech touchpad\n"); |
6178 |
return (FALSE); |
6179 |
} |
6180 |
|
6181 |
/* |
6182 |
* Get the touchpad reporting range. |
6183 |
* On HW v.3 touchpads it should be done after switching hardware |
6184 |
* to real resolution mode (by setting bit 3 of reg10) |
6185 |
*/ |
6186 |
if (elantech_cmd(kbdc, hwversion, ELANTECH_FW_ID, resp) != 0) { |
6187 |
printf(" Failed to read touchpad size\n"); |
6188 |
elanhw.sizex = 10000; /* Arbitrary high values to */ |
6189 |
elanhw.sizey = 10000; /* prevent clipping in smoother */ |
6190 |
} else if (hwversion == 2) { |
6191 |
dptracex = dptracey = 64; |
6192 |
if ((elanhw.fwversion >> 16) == 0x14 && (resp[1] & 0x10) && |
6193 |
!elantech_cmd(kbdc, hwversion, ELANTECH_SAMPLE, resp)) { |
6194 |
dptracex = resp[1] / 2; |
6195 |
dptracey = resp[2] / 2; |
6196 |
} |
6197 |
elanhw.sizex = (elanhw.ntracesx - 1) * dptracex; |
6198 |
elanhw.sizey = (elanhw.ntracesy - 1) * dptracey; |
6199 |
} else { |
6200 |
elanhw.sizex = (resp[0] & 0x0f) << 8 | resp[1]; |
6201 |
elanhw.sizey = (resp[0] & 0xf0) << 4 | resp[2]; |
6202 |
} |
6203 |
|
6204 |
if (verbose >= 2) { |
6205 |
printf(" Model information:\n"); |
6206 |
printf(" MaxX: %d\n", elanhw.sizex); |
6207 |
printf(" MaxY: %d\n", elanhw.sizey); |
6208 |
printf(" DpiX: %d\n", elanhw.dpix); |
6209 |
printf(" DpiY: %d\n", elanhw.dpiy); |
6210 |
printf(" TracesX: %d\n", elanhw.ntracesx); |
6211 |
printf(" TracesY: %d\n", elanhw.ntracesy); |
6212 |
printf(" Clickpad: %d\n", elanhw.isclickpad); |
6213 |
printf(" Trackpad: %d\n", elanhw.hastrackpad); |
6214 |
printf(" CRC: %d\n", elanhw.hascrc); |
6215 |
printf(" Pressure: %d\n", elanhw.haspressure); |
6216 |
} |
6217 |
|
6218 |
VLOG(3, (LOG_DEBUG, "elantech: END init\n")); |
6219 |
|
6220 |
if (arg == PROBE) { |
6221 |
sc->elanhw = elanhw; |
6222 |
sc->hw.buttons = 3; |
6223 |
|
6224 |
/* Initialize synaptics movement smoother */ |
6225 |
elantech_init_synaptics(sc); |
6226 |
|
6227 |
for (id = 0; id < PSM_GESTURE_FINGERS; id++) |
6228 |
PSM_FINGER_RESET(sc->elanaction.fingers[id]); |
6229 |
|
6230 |
if (elanhw.hascrc) |
6231 |
sc->config |= PSM_CONFIG_NOCHECKSYNC; |
6232 |
} |
6233 |
|
6234 |
return (TRUE); |
6235 |
} |
6236 |
|
5174 |
/* |
6237 |
/* |
5175 |
* Return true if 'now' is earlier than (start + (secs.usecs)). |
6238 |
* Return true if 'now' is earlier than (start + (secs.usecs)). |
5176 |
* Now may be NULL and the function will fetch the current time from |
6239 |
* Now may be NULL and the function will fetch the current time from |