^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2006-2008 One Laptop Per Child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Zephaniah E. Hull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Andres Salomon <dilinger@debian.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This driver is partly based on the ALPS driver, which is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * The spec from ALPS is available from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * device as HGPK (Hybrid GS, PT, and Keymatrix).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The earliest versions of the device had simultaneous reporting; that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * was removed. After that, the device used the Advanced Mode GS/PT streaming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * stuff. That turned out to be too buggy to support, so we've finally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/libps2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/olpc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include "psmouse.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "hgpk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ILLEGAL_XY 999999
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static bool tpdebug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) module_param(tpdebug, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int recalib_delta = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) module_param(recalib_delta, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MODULE_PARM_DESC(recalib_delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) "packets containing a delta this large will be discarded, and a "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "recalibration may be scheduled.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static int jumpy_delay = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) module_param(jumpy_delay, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) MODULE_PARM_DESC(jumpy_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) "delay (ms) before recal after jumpiness detected");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int spew_delay = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) module_param(spew_delay, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) MODULE_PARM_DESC(spew_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) "delay (ms) before recal after packet spew detected");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int recal_guard_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) module_param(recal_guard_time, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) MODULE_PARM_DESC(recal_guard_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) "interval (ms) during which recal will be restarted if packet received");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int post_interrupt_delay = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) module_param(post_interrupt_delay, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MODULE_PARM_DESC(post_interrupt_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) "delay (ms) before recal after recal interrupt detected");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static bool autorecal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) module_param(autorecal, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static char hgpk_mode_name[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) MODULE_PARM_DESC(hgpk_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "default hgpk mode: mouse, glidesensor or pentablet");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int hgpk_default_mode = HGPK_MODE_MOUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static const char * const hgpk_mode_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) [HGPK_MODE_MOUSE] = "Mouse",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) [HGPK_MODE_GLIDESENSOR] = "GlideSensor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) [HGPK_MODE_PENTABLET] = "PenTablet",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int hgpk_mode_from_name(const char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const char *name = hgpk_mode_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (strlen(name) == len && !strncasecmp(name, buf, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return HGPK_MODE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * see if new value is within 20% of half of old value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int approx_half(int curr, int prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int belowhalf, abovehalf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (curr < 5 || prev < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) belowhalf = (prev * 8) / 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) abovehalf = (prev * 12) / 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return belowhalf < curr && curr <= abovehalf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Throw out oddly large delta packets, and any that immediately follow whose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * values are each approximately half of the previous. It seems that the ALPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * firmware emits errant packets, and they get averaged out slowly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int avx, avy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) bool do_recal = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) avx = abs(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) avy = abs(y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* discard if too big, or half that but > 4 times the prev delta */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (avx > recalib_delta ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) priv->xbigj = avx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else if (approx_half(avx, priv->xbigj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) priv->xbigj = avx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) priv->xsaw_secondary++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (priv->xbigj && priv->xsaw_secondary > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) do_recal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) priv->xbigj = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) priv->xsaw_secondary = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (avy > recalib_delta ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) priv->ybigj = avy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) } else if (approx_half(avy, priv->ybigj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) priv->ybigj = avy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) priv->ysaw_secondary++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (priv->ybigj && priv->ysaw_secondary > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) do_recal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) priv->ybigj = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) priv->ysaw_secondary = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) priv->xlast = avx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) priv->ylast = avy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (do_recal && jumpy_delay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) psmouse_warn(psmouse, "scheduling recalibration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) psmouse_queue_work(psmouse, &priv->recalib_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) msecs_to_jiffies(jumpy_delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return priv->xbigj || priv->ybigj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static void hgpk_reset_spew_detection(struct hgpk_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) priv->spew_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) priv->dupe_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) priv->x_tally = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) priv->y_tally = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) priv->spew_flag = NO_SPEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static void hgpk_reset_hack_state(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) priv->abs_x = priv->abs_y = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) priv->xlast = priv->ylast = ILLEGAL_XY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) priv->xbigj = priv->ybigj = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) priv->xsaw_secondary = priv->ysaw_secondary = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) hgpk_reset_spew_detection(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * We have no idea why this particular hardware bug occurs. The touchpad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * will randomly start spewing packets without anything touching the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * pad. This wouldn't necessarily be bad, but it's indicative of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * severely miscalibrated pad; attempting to use the touchpad while it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * spewing means the cursor will jump all over the place, and act "drunk".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * The packets that are spewed tend to all have deltas between -2 and 2, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * the cursor will move around without really going very far. It will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * tend to end up in the same location; if we tally up the changes over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * 100 packets, we end up w/ a final delta of close to 0. This happens
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * pretty regularly when the touchpad is spewing, and is pretty hard to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * manually trigger (at least for *my* fingers). So, it makes a perfect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * scheme for detecting spews.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static void hgpk_spewing_hack(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int l, int r, int x, int y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* ignore button press packets; many in a row could trigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * a false-positive! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (l || r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* don't track spew if the workaround feature has been turned off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!spew_delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (abs(x) > 3 || abs(y) > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* no spew, or spew ended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) hgpk_reset_spew_detection(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* Keep a tally of the overall delta to the cursor position caused by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * the spew */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) priv->x_tally += x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) priv->y_tally += y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) switch (priv->spew_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case NO_SPEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* we're not spewing, but this packet might be the start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) priv->spew_flag = MAYBE_SPEWING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case MAYBE_SPEWING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) priv->spew_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (priv->spew_count < SPEW_WATCH_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* excessive spew detected, request recalibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) priv->spew_flag = SPEW_DETECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case SPEW_DETECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* only recalibrate when the overall delta to the cursor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * is really small. if the spew is causing significant cursor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * movement, it is probably a case of the user moving the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * cursor very slowly across the screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) priv->x_tally, priv->y_tally);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) priv->spew_flag = RECALIBRATING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) psmouse_queue_work(psmouse, &priv->recalib_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) msecs_to_jiffies(spew_delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case RECALIBRATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* we already detected a spew and requested a recalibration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * just wait for the queue to kick into action. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * HGPK Mouse Mode format (standard mouse format, sans middle button)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * byte 0: y-over x-over y-neg x-neg 1 0 swr swl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * byte 1: x7 x6 x5 x4 x3 x2 x1 x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * byte 2: y7 y6 y5 y4 y3 y2 y1 y0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * swr/swl are the left/right buttons.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * x-neg/y-neg are the x and y delta negative bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * x-over/y-over are the x and y overflow bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * ---
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * HGPK Advanced Mode - single-mode format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * byte 0(PT): 1 1 0 0 1 1 1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * byte 0(GS): 1 1 1 1 1 1 1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * byte 2(PT): 0 0 x9 x8 x7 ? pt-dsw 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * byte 2(GS): 0 x10 x9 x8 x7 ? gs-dsw pt-dsw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * byte 3: 0 y9 y8 y7 1 0 swr swl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * byte 4: 0 y6 y5 y4 y3 y2 y1 y0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * byte 5: 0 z6 z5 z4 z3 z2 z1 z0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * ?'s are not defined in the protocol spec, may vary between models.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * swr/swl are the left/right buttons.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * pen/finger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int pktcnt = psmouse->pktcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) bool valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) switch (priv->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case HGPK_MODE_MOUSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) valid = (packet[0] & 0x0C) == 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) case HGPK_MODE_GLIDESENSOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) valid = pktcnt == 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) case HGPK_MODE_PENTABLET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) valid = pktcnt == 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) valid = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (!valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) "bad data, mode %d (%d) %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) priv->mode, pktcnt, 6, psmouse->packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static void hgpk_process_advanced_packet(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct input_dev *idev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int down = !!(packet[2] & 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int left = !!(packet[3] & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int right = !!(packet[3] & 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int x = packet[1] | ((packet[2] & 0x78) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int y = packet[4] | ((packet[3] & 0x70) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (priv->mode == HGPK_MODE_GLIDESENSOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int pt_down = !!(packet[2] & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int finger_down = !!(packet[2] & 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int z = packet[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) input_report_abs(idev, ABS_PRESSURE, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pt_down, finger_down, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * PenTablet mode does not report pressure, so we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * report it here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) psmouse_dbg(psmouse, "pd=%d ", down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) left, right, x, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) input_report_key(idev, BTN_TOUCH, down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) input_report_key(idev, BTN_LEFT, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) input_report_key(idev, BTN_RIGHT, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * If this packet says that the finger was removed, reset our position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * tracking so that we don't erroneously detect a jump on next press.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!down) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) hgpk_reset_hack_state(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * Weed out duplicate packets (we get quite a few, and they mess up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * our jump detection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (x == priv->abs_x && y == priv->abs_y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (++priv->dupe_count > SPEW_WATCH_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) psmouse_dbg(psmouse, "hard spew detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) priv->spew_flag = RECALIBRATING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) psmouse_queue_work(psmouse, &priv->recalib_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) msecs_to_jiffies(spew_delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* not a duplicate, continue with position reporting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) priv->dupe_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Don't apply hacks in PT mode, it seems reliable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int x_diff = priv->abs_x - x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int y_diff = priv->abs_y - y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) psmouse_dbg(psmouse, "discarding\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) input_report_abs(idev, ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) input_report_abs(idev, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) priv->abs_x = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) priv->abs_y = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) input_sync(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static void hgpk_process_simple_packet(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int left = packet[0] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int right = (packet[0] >> 1) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int x = packet[1] - ((packet[0] << 4) & 0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int y = ((packet[0] << 3) & 0x100) - packet[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (packet[0] & 0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) "overflow -- 0x%02x 0x%02x 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) packet[0], packet[1], packet[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (hgpk_discard_decay_hack(psmouse, x, y)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) psmouse_dbg(psmouse, "discarding\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) hgpk_spewing_hack(psmouse, left, right, x, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) left, right, x, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) input_report_key(dev, BTN_LEFT, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) input_report_key(dev, BTN_RIGHT, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) input_report_rel(dev, REL_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) input_report_rel(dev, REL_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!hgpk_is_byte_valid(psmouse, psmouse->packet))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return PSMOUSE_BAD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (psmouse->pktcnt >= psmouse->pktsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (priv->mode == HGPK_MODE_MOUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) hgpk_process_simple_packet(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) hgpk_process_advanced_packet(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return PSMOUSE_FULL_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (priv->recalib_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (time_before(jiffies, priv->recalib_window)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * ugh, got a packet inside our recalibration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * window, schedule another recalibration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) "packet inside calibration window, queueing another recalibration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) psmouse_queue_work(psmouse, &priv->recalib_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) msecs_to_jiffies(post_interrupt_delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) priv->recalib_window = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int hgpk_select_mode(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * 4 disables to enable advanced mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * then 3 0xf2 bytes as the preamble for GS/PT selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) const int advanced_init[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 0xf2, 0xf2, 0xf2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) switch (priv->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case HGPK_MODE_MOUSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) psmouse->pktsize = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case HGPK_MODE_GLIDESENSOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case HGPK_MODE_PENTABLET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) psmouse->pktsize = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* Switch to 'Advanced mode.', four disables in a row. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) for (i = 0; i < ARRAY_SIZE(advanced_init); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (ps2_command(ps2dev, NULL, advanced_init[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* select between GlideSensor (mouse) or PenTablet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) cmd = priv->mode == HGPK_MODE_GLIDESENSOR ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (ps2_command(ps2dev, NULL, cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void hgpk_setup_input_device(struct input_dev *input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct input_dev *old_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) enum hgpk_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (old_input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) input->name = old_input->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) input->phys = old_input->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) input->id = old_input->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) input->dev.parent = old_input->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) memset(input->evbit, 0, sizeof(input->evbit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) memset(input->relbit, 0, sizeof(input->relbit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) memset(input->keybit, 0, sizeof(input->keybit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* All modes report left and right buttons */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) __set_bit(EV_KEY, input->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) __set_bit(BTN_LEFT, input->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) __set_bit(BTN_RIGHT, input->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) case HGPK_MODE_MOUSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) __set_bit(EV_REL, input->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) __set_bit(REL_X, input->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) __set_bit(REL_Y, input->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case HGPK_MODE_GLIDESENSOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) __set_bit(BTN_TOUCH, input->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) __set_bit(BTN_TOOL_FINGER, input->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) __set_bit(EV_ABS, input->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* GlideSensor has pressure sensor, PenTablet does not */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /* From device specs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) input_set_abs_params(input, ABS_X, 0, 399, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) input_set_abs_params(input, ABS_Y, 0, 290, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* Calculated by hand based on usable size (52mm x 38mm) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) input_abs_set_res(input, ABS_X, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) input_abs_set_res(input, ABS_Y, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case HGPK_MODE_PENTABLET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) __set_bit(BTN_TOUCH, input->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) __set_bit(BTN_TOOL_FINGER, input->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) __set_bit(EV_ABS, input->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* From device specs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) input_set_abs_params(input, ABS_X, 0, 999, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) input_set_abs_params(input, ABS_Y, 5, 239, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* Calculated by hand based on usable size (156mm x 38mm) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) input_abs_set_res(input, ABS_X, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) input_abs_set_res(input, ABS_Y, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (recalibrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* send the recalibrate request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (ps2_command(ps2dev, NULL, 0xf5) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ps2_command(ps2dev, NULL, 0xf5) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ps2_command(ps2dev, NULL, 0xe6) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ps2_command(ps2dev, NULL, 0xf5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* according to ALPS, 150mS is required for recalibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) msleep(150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) err = hgpk_select_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) psmouse_err(psmouse, "failed to select mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) hgpk_reset_hack_state(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int hgpk_force_recalibrate(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /* C-series touchpads added the recalibrate command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (psmouse->model < HGPK_MODEL_C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (!autorecal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) psmouse_dbg(psmouse, "recalibrating touchpad..\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* we don't want to race with the irq handler, nor with resyncs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* start by resetting the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) err = hgpk_reset_device(psmouse, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * XXX: If a finger is down during this delay, recalibration will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * detect capacitance incorrectly. This is a hardware bug, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * we don't have a good way to deal with it. The 2s window stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * (below) is our best option for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (psmouse_activate(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (tpdebug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) psmouse_dbg(psmouse, "touchpad reactivated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * If we get packets right away after recalibrating, it's likely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * that a finger was on the touchpad. If so, it's probably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * miscalibrated, so we optionally schedule another.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (recal_guard_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) priv->recalib_window = jiffies +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) msecs_to_jiffies(recal_guard_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * This puts the touchpad in a power saving mode; according to ALPS, current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * consumption goes down to 50uA after running this. To turn power back on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * we drive MS-DAT low. Measuring with a 1mA resolution ammeter says that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * the current on the SUS_3.3V rail drops from 3mA or 4mA to 0 when we do this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * We have no formal spec that details this operation -- the low-power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * sequence came from a long-lost email trail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int timeo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /* Added on D-series touchpads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (psmouse->model < HGPK_MODEL_D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * Sending a byte will drive MS-DAT low; this will wake up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * the controller. Once we get an ACK back from it, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * means we can continue with the touchpad re-init. ALPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * tells us that 1s should be long enough, so set that as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * the upper bound. (in practice, it takes about 3 loops.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) for (timeo = 20; timeo > 0; timeo--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (!ps2_sendbyte(ps2dev, PSMOUSE_CMD_DISABLE, 20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) msleep(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) err = hgpk_reset_device(psmouse, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) psmouse_err(psmouse, "Failed to reset device!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* should be all set, enable the touchpad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) psmouse_activate(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) psmouse_dbg(psmouse, "Touchpad powered up.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) psmouse_dbg(psmouse, "Powering off touchpad.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (ps2_command(ps2dev, NULL, 0xec) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ps2_command(ps2dev, NULL, 0xec) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ps2_command(ps2dev, NULL, 0xea)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) psmouse_set_state(psmouse, PSMOUSE_IGNORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* probably won't see an ACK, the touchpad will be off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ps2_sendbyte(ps2dev, 0xec, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int hgpk_poll(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /* We can't poll, so always return failure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) static int hgpk_reconnect(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * During suspend/resume the ps2 rails remain powered. We don't want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * to do a reset because it's flush data out of buffers; however,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * earlier prototypes (B1) had some brokenness that required a reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (olpc_board_at_least(olpc_board(0xb2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (psmouse->ps2dev.serio->dev.power.power_state.event !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) PM_EVENT_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) priv->powered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return hgpk_reset_device(psmouse, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return sprintf(buf, "%d\n", priv->powered);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) err = kstrtouint(buf, 10, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (value > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (value != priv->powered) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * hgpk_toggle_power will deal w/ state so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * we're not racing w/ irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) err = hgpk_toggle_powersave(psmouse, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) priv->powered = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return err ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) hgpk_show_powered, hgpk_set_powered, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static ssize_t attr_set_mode(struct psmouse *psmouse, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) const char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) enum hgpk_mode old_mode = priv->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) struct input_dev *old_dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) struct input_dev *new_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (new_mode == HGPK_MODE_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (old_mode == new_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) new_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (!new_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* Switch device into the new mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) priv->mode = new_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) err = hgpk_reset_device(psmouse, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) goto err_try_restore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) hgpk_setup_input_device(new_dev, old_dev, new_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) err = input_register_device(new_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) goto err_try_restore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) psmouse->dev = new_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) input_unregister_device(old_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) err_try_restore:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) input_free_device(new_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) priv->mode = old_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) hgpk_reset_device(psmouse, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) attr_show_mode, attr_set_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) void *data, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) err = kstrtouint(buf, 10, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (value != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * We queue work instead of doing recalibration right here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * to avoid adding locking to to hgpk_force_recalibrate()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * since workqueue provides serialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) __PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) hgpk_trigger_recal_show, hgpk_trigger_recal, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static void hgpk_disconnect(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) device_remove_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) &psmouse_attr_powered.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) device_remove_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) &psmouse_attr_hgpk_mode.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (psmouse->model >= HGPK_MODEL_C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) device_remove_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) &psmouse_attr_recalibrate.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static void hgpk_recalib_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct delayed_work *w = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct psmouse *psmouse = priv->psmouse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (hgpk_force_recalibrate(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) psmouse_err(psmouse, "recalibration failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static int hgpk_register(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct hgpk_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* register handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) psmouse->protocol_handler = hgpk_process_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) psmouse->poll = hgpk_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) psmouse->disconnect = hgpk_disconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) psmouse->reconnect = hgpk_reconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* Disable the idle resync. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) psmouse->resync_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /* Reset after a lot of bad bytes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) psmouse->resetafter = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) hgpk_setup_input_device(psmouse->dev, NULL, priv->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) err = device_create_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) &psmouse_attr_powered.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) err = device_create_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) &psmouse_attr_hgpk_mode.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) psmouse_err(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) "Failed creating 'hgpk_mode' sysfs node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) goto err_remove_powered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* C-series touchpads added the recalibrate command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (psmouse->model >= HGPK_MODEL_C) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) err = device_create_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) &psmouse_attr_recalibrate.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) psmouse_err(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) "Failed creating 'recalibrate' sysfs node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) goto err_remove_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) err_remove_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) device_remove_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) &psmouse_attr_hgpk_mode.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) err_remove_powered:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) device_remove_file(&psmouse->ps2dev.serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) &psmouse_attr_powered.dattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int hgpk_init(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct hgpk_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (!priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) goto alloc_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) psmouse->private = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) priv->psmouse = psmouse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) priv->powered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) priv->mode = hgpk_default_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) err = hgpk_reset_device(psmouse, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) goto init_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) err = hgpk_register(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) goto init_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) init_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) alloc_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) unsigned char param[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* E7, E7, E7, E9 gets us a 3 byte identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) psmouse_dbg(psmouse, "ID: %*ph\n", 3, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* HGPK signature: 0x67, 0x00, 0x<model> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (param[0] != 0x67 || param[1] != 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return param[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) int hgpk_detect(struct psmouse *psmouse, bool set_properties)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) int version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) version = hgpk_get_model(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (version < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (set_properties) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) psmouse->vendor = "ALPS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) psmouse->name = "HGPK";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) psmouse->model = version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) void hgpk_module_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) strlen(hgpk_mode_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) if (hgpk_default_mode == HGPK_MODE_INVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) hgpk_default_mode = HGPK_MODE_MOUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) sizeof(hgpk_mode_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }