summaryrefslogtreecommitdiff
path: root/drivers/input/mouse
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-22 18:36:40 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-22 18:36:40 -0700
commit429e6c7f90d12a8551b3eaa9faca7cfaefd99b1d (patch)
tree0c9670ecc648c23f06eb45c2413e46aedfbf8aa1 /drivers/input/mouse
parent2e68039281932e6dc37718a1ea7cbb8e2cda42e6 (diff)
parentf4b369c6fe0ceaba2da2daff8c9eb415f85926dd (diff)
downloadlwn-429e6c7f90d12a8551b3eaa9faca7cfaefd99b1d.tar.gz
lwn-429e6c7f90d12a8551b3eaa9faca7cfaefd99b1d.zip
Merge tag 'input-for-v7.1-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - a new charlieplex GPIO keypad driver - an update to aw86927 driver to support 86938 chip - an update for Chrome OS EC keyboard driver to support Fn-<key> keymap extension - an UAF fix in debugfs teardown in EDT touchscreen driver - a number of conversions for input drivers to use guard() and __free() cleanup primitives - several drivers for bus mice (inport, logibm) and other very old devices have been removed - OLPC HGPK PS/2 protocol has been removed as it's been broken and inactive for 10 something years - dedicated kpsmoused has been removed from psmouse driver - other assorted cleanups and fixups * tag 'input-for-v7.1-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (101 commits) Input: charlieplex_keypad - add GPIO charlieplex keypad dt-bindings: input: add GPIO charlieplex keypad dt-bindings: input: add settling-time-us common property dt-bindings: input: add debounce-delay-ms common property Input: imx_keypad - fix spelling mistake "Colums" -> "Columns" Input: edt-ft5x06 - fix use-after-free in debugfs teardown Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data() Input: ct82c710 - remove driver Input: mk712 - remove driver Input: logibm - remove driver Input: inport - remove driver Input: qt1070 - inline i2c_check_functionality check Input: qt1050 - inline i2c_check_functionality check Input: aiptek - validate raw macro indices before updating state Input: gf2k - skip invalid hat lookup values Input: xpad - add RedOctane Games vendor id Input: xpad - remove stale TODO and changelog header Input: usbtouchscreen - refactor endpoint lookup Input: aw86927 - add support for Awinic AW86938 dt-bindings: input: awinic,aw86927: Add Awinic AW86938 ...
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r--drivers/input/mouse/Kconfig36
-rw-r--r--drivers/input/mouse/Makefile3
-rw-r--r--drivers/input/mouse/alps.c11
-rw-r--r--drivers/input/mouse/alps.h4
-rw-r--r--drivers/input/mouse/appletouch.c21
-rw-r--r--drivers/input/mouse/hgpk.c1063
-rw-r--r--drivers/input/mouse/hgpk.h61
-rw-r--r--drivers/input/mouse/inport.c177
-rw-r--r--drivers/input/mouse/logibm.c166
-rw-r--r--drivers/input/mouse/psmouse-base.c51
-rw-r--r--drivers/input/mouse/psmouse.h6
-rw-r--r--drivers/input/mouse/synaptics_usb.c23
12 files changed, 24 insertions, 1598 deletions
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index c8b87a87744c..074130d88953 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -164,16 +164,6 @@ config MOUSE_PS2_TOUCHKIT
If unsure, say N.
-config MOUSE_PS2_OLPC
- bool "OLPC PS/2 mouse protocol extension"
- depends on MOUSE_PS2 && OLPC
- help
- Say Y here if you have an OLPC XO-1 laptop (with built-in
- PS/2 touchpad/tablet device). The manufacturer calls the
- touchpad an HGPK.
-
- If unsure, say N.
-
config MOUSE_PS2_FOCALTECH
bool "FocalTech PS/2 mouse protocol extension" if EXPERT
default y
@@ -300,32 +290,6 @@ config MOUSE_ELAN_I2C_SMBUS
If unsure, say Y.
-config MOUSE_INPORT
- tristate "InPort/MS/ATIXL busmouse"
- depends on ISA
- help
- Say Y here if you have an InPort, Microsoft or ATI XL busmouse.
- They are rather rare these days.
-
- To compile this driver as a module, choose M here: the
- module will be called inport.
-
-config MOUSE_ATIXL
- bool "ATI XL variant"
- depends on MOUSE_INPORT
- help
- Say Y here if your mouse is of the ATI XL variety.
-
-config MOUSE_LOGIBM
- tristate "Logitech busmouse"
- depends on ISA
- help
- Say Y here if you have a Logitech busmouse.
- They are rather rare these days.
-
- To compile this driver as a module, choose M here: the
- module will be called logibm.
-
config MOUSE_AMIGA
tristate "Amiga mouse"
depends on AMIGA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 78ab5db28d7c..ed40f141691e 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -12,8 +12,6 @@ obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o
obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
-obj-$(CONFIG_MOUSE_INPORT) += inport.o
-obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
@@ -28,7 +26,6 @@ psmouse-objs := psmouse-base.o synaptics.o focaltech.o
psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o
psmouse-$(CONFIG_MOUSE_PS2_BYD) += byd.o
psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o
-psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o
psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o
psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index f3d3b6b4e02d..0ee1a30b9aaf 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -12,6 +12,7 @@
* tpconfig utility (by C. Scott Ananian and Bruce Kall).
*/
+#include "linux/workqueue.h"
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
@@ -1452,7 +1453,7 @@ err_free_input:
static void alps_register_bare_ps2_mouse(struct work_struct *work)
{
struct alps_data *priv = container_of(work, struct alps_data,
- dev3_register_work.work);
+ dev3_register_work);
int error;
guard(mutex)(&alps_mutex);
@@ -1485,8 +1486,7 @@ static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
} else if (unlikely(IS_ERR_OR_NULL(priv->dev3))) {
/* Register dev3 mouse if we received PS/2 packet first time */
if (!IS_ERR(priv->dev3))
- psmouse_queue_work(psmouse, &priv->dev3_register_work,
- 0);
+ schedule_work(&priv->dev3_register_work);
return;
} else {
dev = priv->dev3;
@@ -2975,7 +2975,7 @@ static void alps_disconnect(struct psmouse *psmouse)
psmouse_reset(psmouse);
timer_shutdown_sync(&priv->timer);
- disable_delayed_work_sync(&priv->dev3_register_work);
+ disable_work_sync(&priv->dev3_register_work);
if (priv->dev2)
input_unregister_device(priv->dev2);
if (!IS_ERR_OR_NULL(priv->dev3))
@@ -3147,8 +3147,7 @@ int alps_init(struct psmouse *psmouse)
priv->psmouse = psmouse;
- INIT_DELAYED_WORK(&priv->dev3_register_work,
- alps_register_bare_ps2_mouse);
+ INIT_WORK(&priv->dev3_register_work, alps_register_bare_ps2_mouse);
psmouse->protocol_handler = alps_process_byte;
psmouse->poll = alps_poll;
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 0a1048cf23f6..17bbf6cdba55 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -257,7 +257,7 @@ struct alps_fields {
* @dev3: Generic PS/2 mouse (can be NULL, delayed registering).
* @phys2: Physical path for the trackstick device.
* @phys3: Physical path for the generic PS/2 mouse.
- * @dev3_register_work: Delayed work for registering PS/2 mouse.
+ * @dev3_register_work: A work instance for registering PS/2 mouse.
* @nibble_commands: Command mapping used for touchpad register accesses.
* @addr_command: Command used to tell the touchpad that a register address
* follows.
@@ -289,7 +289,7 @@ struct alps_data {
struct input_dev *dev3;
char phys2[32];
char phys3[32];
- struct delayed_work dev3_register_work;
+ struct work_struct dev3_register_work;
/* these are autodetected when the device is identified */
const struct alps_nibble_commands *nibble_commands;
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 87d8f5afdfd9..eebeb57515e1 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -829,29 +829,20 @@ static int atp_probe(struct usb_interface *iface,
struct atp *dev;
struct input_dev *input_dev;
struct usb_device *udev = interface_to_usbdev(iface);
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- int int_in_endpointAddr = 0;
- int i, error = -ENOMEM;
+ struct usb_endpoint_descriptor *ep;
+ int error;
const struct atp_info *info = (const struct atp_info *)id->driver_info;
/* set up the endpoint information */
/* use only the first interrupt-in endpoint */
- iface_desc = iface->cur_altsetting;
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- endpoint = &iface_desc->endpoint[i].desc;
- if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
- /* we found an interrupt in endpoint */
- int_in_endpointAddr = endpoint->bEndpointAddress;
- break;
- }
- }
- if (!int_in_endpointAddr) {
+ error = usb_find_int_in_endpoint(iface->cur_altsetting, &ep);
+ if (error) {
dev_err(&iface->dev, "Could not find int-in endpoint\n");
return -EIO;
}
/* allocate memory for our device state and initialize it */
+ error = -ENOMEM;
dev = kzalloc_obj(*dev);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
@@ -875,7 +866,7 @@ static int atp_probe(struct usb_interface *iface,
goto err_free_urb;
usb_fill_int_urb(dev->urb, udev,
- usb_rcvintpipe(udev, int_in_endpointAddr),
+ usb_rcvintpipe(udev, usb_endpoint_num(ep)),
dev->data, dev->info->datalen,
dev->info->callback, dev, 1);
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
deleted file mode 100644
index 3c4d16ed88a9..000000000000
--- a/drivers/input/mouse/hgpk.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
- *
- * Copyright (c) 2006-2008 One Laptop Per Child
- * Authors:
- * Zephaniah E. Hull
- * Andres Salomon <dilinger@debian.org>
- *
- * This driver is partly based on the ALPS driver, which is:
- *
- * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
- * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
- * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
- * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
- */
-
-/*
- * The spec from ALPS is available from
- * <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this
- * device as HGPK (Hybrid GS, PT, and Keymatrix).
- *
- * The earliest versions of the device had simultaneous reporting; that
- * was removed. After that, the device used the Advanced Mode GS/PT streaming
- * stuff. That turned out to be too buggy to support, so we've finally
- * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
- */
-
-#define DEBUG
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/serio.h>
-#include <linux/libps2.h>
-#include <linux/delay.h>
-#include <asm/olpc.h>
-
-#include "psmouse.h"
-#include "hgpk.h"
-
-#define ILLEGAL_XY 999999
-
-static bool tpdebug;
-module_param(tpdebug, bool, 0644);
-MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
-
-static int recalib_delta = 100;
-module_param(recalib_delta, int, 0644);
-MODULE_PARM_DESC(recalib_delta,
- "packets containing a delta this large will be discarded, and a "
- "recalibration may be scheduled.");
-
-static int jumpy_delay = 20;
-module_param(jumpy_delay, int, 0644);
-MODULE_PARM_DESC(jumpy_delay,
- "delay (ms) before recal after jumpiness detected");
-
-static int spew_delay = 1;
-module_param(spew_delay, int, 0644);
-MODULE_PARM_DESC(spew_delay,
- "delay (ms) before recal after packet spew detected");
-
-static int recal_guard_time;
-module_param(recal_guard_time, int, 0644);
-MODULE_PARM_DESC(recal_guard_time,
- "interval (ms) during which recal will be restarted if packet received");
-
-static int post_interrupt_delay = 40;
-module_param(post_interrupt_delay, int, 0644);
-MODULE_PARM_DESC(post_interrupt_delay,
- "delay (ms) before recal after recal interrupt detected");
-
-static bool autorecal = true;
-module_param(autorecal, bool, 0644);
-MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
-
-static char hgpk_mode_name[16];
-module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644);
-MODULE_PARM_DESC(hgpk_mode,
- "default hgpk mode: mouse, glidesensor or pentablet");
-
-static int hgpk_default_mode = HGPK_MODE_MOUSE;
-
-static const char * const hgpk_mode_names[] = {
- [HGPK_MODE_MOUSE] = "Mouse",
- [HGPK_MODE_GLIDESENSOR] = "GlideSensor",
- [HGPK_MODE_PENTABLET] = "PenTablet",
-};
-
-static int hgpk_mode_from_name(const char *buf, int len)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) {
- const char *name = hgpk_mode_names[i];
- if (strlen(name) == len && !strncasecmp(name, buf, len))
- return i;
- }
-
- return HGPK_MODE_INVALID;
-}
-
-/*
- * see if new value is within 20% of half of old value
- */
-static int approx_half(int curr, int prev)
-{
- int belowhalf, abovehalf;
-
- if (curr < 5 || prev < 5)
- return 0;
-
- belowhalf = (prev * 8) / 20;
- abovehalf = (prev * 12) / 20;
-
- return belowhalf < curr && curr <= abovehalf;
-}
-
-/*
- * Throw out oddly large delta packets, and any that immediately follow whose
- * values are each approximately half of the previous. It seems that the ALPS
- * firmware emits errant packets, and they get averaged out slowly.
- */
-static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
-{
- struct hgpk_data *priv = psmouse->private;
- int avx, avy;
- bool do_recal = false;
-
- avx = abs(x);
- avy = abs(y);
-
- /* discard if too big, or half that but > 4 times the prev delta */
- if (avx > recalib_delta ||
- (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
- psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
- priv->xbigj = avx;
- } else if (approx_half(avx, priv->xbigj)) {
- psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
- priv->xbigj = avx;
- priv->xsaw_secondary++;
- } else {
- if (priv->xbigj && priv->xsaw_secondary > 1)
- do_recal = true;
- priv->xbigj = 0;
- priv->xsaw_secondary = 0;
- }
-
- if (avy > recalib_delta ||
- (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
- psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
- priv->ybigj = avy;
- } else if (approx_half(avy, priv->ybigj)) {
- psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
- priv->ybigj = avy;
- priv->ysaw_secondary++;
- } else {
- if (priv->ybigj && priv->ysaw_secondary > 1)
- do_recal = true;
- priv->ybigj = 0;
- priv->ysaw_secondary = 0;
- }
-
- priv->xlast = avx;
- priv->ylast = avy;
-
- if (do_recal && jumpy_delay) {
- psmouse_warn(psmouse, "scheduling recalibration\n");
- psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(jumpy_delay));
- }
-
- return priv->xbigj || priv->ybigj;
-}
-
-static void hgpk_reset_spew_detection(struct hgpk_data *priv)
-{
- priv->spew_count = 0;
- priv->dupe_count = 0;
- priv->x_tally = 0;
- priv->y_tally = 0;
- priv->spew_flag = NO_SPEW;
-}
-
-static void hgpk_reset_hack_state(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
-
- priv->abs_x = priv->abs_y = -1;
- priv->xlast = priv->ylast = ILLEGAL_XY;
- priv->xbigj = priv->ybigj = 0;
- priv->xsaw_secondary = priv->ysaw_secondary = 0;
- hgpk_reset_spew_detection(priv);
-}
-
-/*
- * We have no idea why this particular hardware bug occurs. The touchpad
- * will randomly start spewing packets without anything touching the
- * pad. This wouldn't necessarily be bad, but it's indicative of a
- * severely miscalibrated pad; attempting to use the touchpad while it's
- * spewing means the cursor will jump all over the place, and act "drunk".
- *
- * The packets that are spewed tend to all have deltas between -2 and 2, and
- * the cursor will move around without really going very far. It will
- * tend to end up in the same location; if we tally up the changes over
- * 100 packets, we end up w/ a final delta of close to 0. This happens
- * pretty regularly when the touchpad is spewing, and is pretty hard to
- * manually trigger (at least for *my* fingers). So, it makes a perfect
- * scheme for detecting spews.
- */
-static void hgpk_spewing_hack(struct psmouse *psmouse,
- int l, int r, int x, int y)
-{
- struct hgpk_data *priv = psmouse->private;
-
- /* ignore button press packets; many in a row could trigger
- * a false-positive! */
- if (l || r)
- return;
-
- /* don't track spew if the workaround feature has been turned off */
- if (!spew_delay)
- return;
-
- if (abs(x) > 3 || abs(y) > 3) {
- /* no spew, or spew ended */
- hgpk_reset_spew_detection(priv);
- return;
- }
-
- /* Keep a tally of the overall delta to the cursor position caused by
- * the spew */
- priv->x_tally += x;
- priv->y_tally += y;
-
- switch (priv->spew_flag) {
- case NO_SPEW:
- /* we're not spewing, but this packet might be the start */
- priv->spew_flag = MAYBE_SPEWING;
-
- fallthrough;
-
- case MAYBE_SPEWING:
- priv->spew_count++;
-
- if (priv->spew_count < SPEW_WATCH_COUNT)
- break;
-
- /* excessive spew detected, request recalibration */
- priv->spew_flag = SPEW_DETECTED;
-
- fallthrough;
-
- case SPEW_DETECTED:
- /* only recalibrate when the overall delta to the cursor
- * is really small. if the spew is causing significant cursor
- * movement, it is probably a case of the user moving the
- * cursor very slowly across the screen. */
- if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
- psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
- priv->x_tally, priv->y_tally);
- priv->spew_flag = RECALIBRATING;
- psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(spew_delay));
- }
-
- break;
- case RECALIBRATING:
- /* we already detected a spew and requested a recalibration,
- * just wait for the queue to kick into action. */
- break;
- }
-}
-
-/*
- * HGPK Mouse Mode format (standard mouse format, sans middle button)
- *
- * byte 0: y-over x-over y-neg x-neg 1 0 swr swl
- * byte 1: x7 x6 x5 x4 x3 x2 x1 x0
- * byte 2: y7 y6 y5 y4 y3 y2 y1 y0
- *
- * swr/swl are the left/right buttons.
- * x-neg/y-neg are the x and y delta negative bits
- * x-over/y-over are the x and y overflow bits
- *
- * ---
- *
- * HGPK Advanced Mode - single-mode format
- *
- * byte 0(PT): 1 1 0 0 1 1 1 1
- * byte 0(GS): 1 1 1 1 1 1 1 1
- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
- * byte 2(PT): 0 0 x9 x8 x7 ? pt-dsw 0
- * byte 2(GS): 0 x10 x9 x8 x7 ? gs-dsw pt-dsw
- * byte 3: 0 y9 y8 y7 1 0 swr swl
- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0
- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0
- *
- * ?'s are not defined in the protocol spec, may vary between models.
- *
- * swr/swl are the left/right buttons.
- *
- * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a
- * pen/finger
- */
-static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
-{
- struct hgpk_data *priv = psmouse->private;
- int pktcnt = psmouse->pktcnt;
- bool valid;
-
- switch (priv->mode) {
- case HGPK_MODE_MOUSE:
- valid = (packet[0] & 0x0C) == 0x08;
- break;
-
- case HGPK_MODE_GLIDESENSOR:
- valid = pktcnt == 1 ?
- packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80);
- break;
-
- case HGPK_MODE_PENTABLET:
- valid = pktcnt == 1 ?
- packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80);
- break;
-
- default:
- valid = false;
- break;
- }
-
- if (!valid)
- psmouse_dbg(psmouse,
- "bad data, mode %d (%d) %*ph\n",
- priv->mode, pktcnt, 6, psmouse->packet);
-
- return valid;
-}
-
-static void hgpk_process_advanced_packet(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
- struct input_dev *idev = psmouse->dev;
- unsigned char *packet = psmouse->packet;
- int down = !!(packet[2] & 2);
- int left = !!(packet[3] & 1);
- int right = !!(packet[3] & 2);
- int x = packet[1] | ((packet[2] & 0x78) << 4);
- int y = packet[4] | ((packet[3] & 0x70) << 3);
-
- if (priv->mode == HGPK_MODE_GLIDESENSOR) {
- int pt_down = !!(packet[2] & 1);
- int finger_down = !!(packet[2] & 2);
- int z = packet[5];
-
- input_report_abs(idev, ABS_PRESSURE, z);
- if (tpdebug)
- psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
- pt_down, finger_down, z);
- } else {
- /*
- * PenTablet mode does not report pressure, so we don't
- * report it here
- */
- if (tpdebug)
- psmouse_dbg(psmouse, "pd=%d ", down);
- }
-
- if (tpdebug)
- psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
- left, right, x, y);
-
- input_report_key(idev, BTN_TOUCH, down);
- input_report_key(idev, BTN_LEFT, left);
- input_report_key(idev, BTN_RIGHT, right);
-
- /*
- * If this packet says that the finger was removed, reset our position
- * tracking so that we don't erroneously detect a jump on next press.
- */
- if (!down) {
- hgpk_reset_hack_state(psmouse);
- goto done;
- }
-
- /*
- * Weed out duplicate packets (we get quite a few, and they mess up
- * our jump detection)
- */
- if (x == priv->abs_x && y == priv->abs_y) {
- if (++priv->dupe_count > SPEW_WATCH_COUNT) {
- if (tpdebug)
- psmouse_dbg(psmouse, "hard spew detected\n");
- priv->spew_flag = RECALIBRATING;
- psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(spew_delay));
- }
- goto done;
- }
-
- /* not a duplicate, continue with position reporting */
- priv->dupe_count = 0;
-
- /* Don't apply hacks in PT mode, it seems reliable */
- if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
- int x_diff = priv->abs_x - x;
- int y_diff = priv->abs_y - y;
- if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
- if (tpdebug)
- psmouse_dbg(psmouse, "discarding\n");
- goto done;
- }
- hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
- }
-
- input_report_abs(idev, ABS_X, x);
- input_report_abs(idev, ABS_Y, y);
- priv->abs_x = x;
- priv->abs_y = y;
-
-done:
- input_sync(idev);
-}
-
-static void hgpk_process_simple_packet(struct psmouse *psmouse)
-{
- struct input_dev *dev = psmouse->dev;
- unsigned char *packet = psmouse->packet;
- int left = packet[0] & 1;
- int right = (packet[0] >> 1) & 1;
- int x = packet[1] - ((packet[0] << 4) & 0x100);
- int y = ((packet[0] << 3) & 0x100) - packet[2];
-
- if (packet[0] & 0xc0)
- psmouse_dbg(psmouse,
- "overflow -- 0x%02x 0x%02x 0x%02x\n",
- packet[0], packet[1], packet[2]);
-
- if (hgpk_discard_decay_hack(psmouse, x, y)) {
- if (tpdebug)
- psmouse_dbg(psmouse, "discarding\n");
- return;
- }
-
- hgpk_spewing_hack(psmouse, left, right, x, y);
-
- if (tpdebug)
- psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
- left, right, x, y);
-
- input_report_key(dev, BTN_LEFT, left);
- input_report_key(dev, BTN_RIGHT, right);
-
- input_report_rel(dev, REL_X, x);
- input_report_rel(dev, REL_Y, y);
-
- input_sync(dev);
-}
-
-static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
-
- if (!hgpk_is_byte_valid(psmouse, psmouse->packet))
- return PSMOUSE_BAD_DATA;
-
- if (psmouse->pktcnt >= psmouse->pktsize) {
- if (priv->mode == HGPK_MODE_MOUSE)
- hgpk_process_simple_packet(psmouse);
- else
- hgpk_process_advanced_packet(psmouse);
- return PSMOUSE_FULL_PACKET;
- }
-
- if (priv->recalib_window) {
- if (time_before(jiffies, priv->recalib_window)) {
- /*
- * ugh, got a packet inside our recalibration
- * window, schedule another recalibration.
- */
- psmouse_dbg(psmouse,
- "packet inside calibration window, queueing another recalibration\n");
- psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(post_interrupt_delay));
- }
- priv->recalib_window = 0;
- }
-
- return PSMOUSE_GOOD_DATA;
-}
-
-static int hgpk_select_mode(struct psmouse *psmouse)
-{
- struct ps2dev *ps2dev = &psmouse->ps2dev;
- struct hgpk_data *priv = psmouse->private;
- int i;
- int cmd;
-
- /*
- * 4 disables to enable advanced mode
- * then 3 0xf2 bytes as the preamble for GS/PT selection
- */
- const int advanced_init[] = {
- PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
- PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE,
- 0xf2, 0xf2, 0xf2,
- };
-
- switch (priv->mode) {
- case HGPK_MODE_MOUSE:
- psmouse->pktsize = 3;
- break;
-
- case HGPK_MODE_GLIDESENSOR:
- case HGPK_MODE_PENTABLET:
- psmouse->pktsize = 6;
-
- /* Switch to 'Advanced mode.', four disables in a row. */
- for (i = 0; i < ARRAY_SIZE(advanced_init); i++)
- if (ps2_command(ps2dev, NULL, advanced_init[i]))
- return -EIO;
-
- /* select between GlideSensor (mouse) or PenTablet */
- cmd = priv->mode == HGPK_MODE_GLIDESENSOR ?
- PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21;
-
- if (ps2_command(ps2dev, NULL, cmd))
- return -EIO;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void hgpk_setup_input_device(struct input_dev *input,
- struct input_dev *old_input,
- enum hgpk_mode mode)
-{
- if (old_input) {
- input->name = old_input->name;
- input->phys = old_input->phys;
- input->id = old_input->id;
- input->dev.parent = old_input->dev.parent;
- }
-
- memset(input->evbit, 0, sizeof(input->evbit));
- memset(input->relbit, 0, sizeof(input->relbit));
- memset(input->keybit, 0, sizeof(input->keybit));
-
- /* All modes report left and right buttons */
- __set_bit(EV_KEY, input->evbit);
- __set_bit(BTN_LEFT, input->keybit);
- __set_bit(BTN_RIGHT, input->keybit);
-
- switch (mode) {
- case HGPK_MODE_MOUSE:
- __set_bit(EV_REL, input->evbit);
- __set_bit(REL_X, input->relbit);
- __set_bit(REL_Y, input->relbit);
- break;
-
- case HGPK_MODE_GLIDESENSOR:
- __set_bit(BTN_TOUCH, input->keybit);
- __set_bit(BTN_TOOL_FINGER, input->keybit);
-
- __set_bit(EV_ABS, input->evbit);
-
- /* GlideSensor has pressure sensor, PenTablet does not */
- input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0);
-
- /* From device specs */
- input_set_abs_params(input, ABS_X, 0, 399, 0, 0);
- input_set_abs_params(input, ABS_Y, 0, 290, 0, 0);
-
- /* Calculated by hand based on usable size (52mm x 38mm) */
- input_abs_set_res(input, ABS_X, 8);
- input_abs_set_res(input, ABS_Y, 8);
- break;
-
- case HGPK_MODE_PENTABLET:
- __set_bit(BTN_TOUCH, input->keybit);
- __set_bit(BTN_TOOL_FINGER, input->keybit);
-
- __set_bit(EV_ABS, input->evbit);
-
- /* From device specs */
- input_set_abs_params(input, ABS_X, 0, 999, 0, 0);
- input_set_abs_params(input, ABS_Y, 5, 239, 0, 0);
-
- /* Calculated by hand based on usable size (156mm x 38mm) */
- input_abs_set_res(input, ABS_X, 6);
- input_abs_set_res(input, ABS_Y, 8);
- break;
-
- default:
- BUG();
- }
-}
-
-static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
-{
- int err;
-
- psmouse_reset(psmouse);
-
- if (recalibrate) {
- struct ps2dev *ps2dev = &psmouse->ps2dev;
-
- /* send the recalibrate request */
- if (ps2_command(ps2dev, NULL, 0xf5) ||
- ps2_command(ps2dev, NULL, 0xf5) ||
- ps2_command(ps2dev, NULL, 0xe6) ||
- ps2_command(ps2dev, NULL, 0xf5)) {
- return -1;
- }
-
- /* according to ALPS, 150mS is required for recalibration */
- msleep(150);
- }
-
- err = hgpk_select_mode(psmouse);
- if (err) {
- psmouse_err(psmouse, "failed to select mode\n");
- return err;
- }
-
- hgpk_reset_hack_state(psmouse);
-
- return 0;
-}
-
-static int hgpk_force_recalibrate(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
- int err;
-
- /* C-series touchpads added the recalibrate command */
- if (psmouse->model < HGPK_MODEL_C)
- return 0;
-
- if (!autorecal) {
- psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
- return 0;
- }
-
- psmouse_dbg(psmouse, "recalibrating touchpad..\n");
-
- /* we don't want to race with the irq handler, nor with resyncs */
- psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
-
- /* start by resetting the device */
- err = hgpk_reset_device(psmouse, true);
- if (err)
- return err;
-
- /*
- * XXX: If a finger is down during this delay, recalibration will
- * detect capacitance incorrectly. This is a hardware bug, and
- * we don't have a good way to deal with it. The 2s window stuff
- * (below) is our best option for now.
- */
- if (psmouse_activate(psmouse))
- return -1;
-
- if (tpdebug)
- psmouse_dbg(psmouse, "touchpad reactivated\n");
-
- /*
- * If we get packets right away after recalibrating, it's likely
- * that a finger was on the touchpad. If so, it's probably
- * miscalibrated, so we optionally schedule another.
- */
- if (recal_guard_time)
- priv->recalib_window = jiffies +
- msecs_to_jiffies(recal_guard_time);
-
- return 0;
-}
-
-/*
- * This puts the touchpad in a power saving mode; according to ALPS, current
- * consumption goes down to 50uA after running this. To turn power back on,
- * we drive MS-DAT low. Measuring with a 1mA resolution ammeter says that
- * the current on the SUS_3.3V rail drops from 3mA or 4mA to 0 when we do this.
- *
- * We have no formal spec that details this operation -- the low-power
- * sequence came from a long-lost email trail.
- */
-static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
-{
- struct ps2dev *ps2dev = &psmouse->ps2dev;
- int timeo;
- int err;
-
- /* Added on D-series touchpads */
- if (psmouse->model < HGPK_MODEL_D)
- return 0;
-
- if (enable) {
- psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
-
- /*
- * Sending a byte will drive MS-DAT low; this will wake up
- * the controller. Once we get an ACK back from it, it
- * means we can continue with the touchpad re-init. ALPS
- * tells us that 1s should be long enough, so set that as
- * the upper bound. (in practice, it takes about 3 loops.)
- */
- for (timeo = 20; timeo > 0; timeo--) {
- if (!ps2_sendbyte(ps2dev, PSMOUSE_CMD_DISABLE, 20))
- break;
- msleep(25);
- }
-
- err = hgpk_reset_device(psmouse, false);
- if (err) {
- psmouse_err(psmouse, "Failed to reset device!\n");
- return err;
- }
-
- /* should be all set, enable the touchpad */
- psmouse_activate(psmouse);
- psmouse_dbg(psmouse, "Touchpad powered up.\n");
- } else {
- psmouse_dbg(psmouse, "Powering off touchpad.\n");
-
- if (ps2_command(ps2dev, NULL, 0xec) ||
- ps2_command(ps2dev, NULL, 0xec) ||
- ps2_command(ps2dev, NULL, 0xea)) {
- return -1;
- }
-
- psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-
- /* probably won't see an ACK, the touchpad will be off */
- ps2_sendbyte(ps2dev, 0xec, 20);
- }
-
- return 0;
-}
-
-static int hgpk_poll(struct psmouse *psmouse)
-{
- /* We can't poll, so always return failure. */
- return -1;
-}
-
-static int hgpk_reconnect(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
-
- /*
- * During suspend/resume the ps2 rails remain powered. We don't want
- * to do a reset because it's flush data out of buffers; however,
- * earlier prototypes (B1) had some brokenness that required a reset.
- */
- if (olpc_board_at_least(olpc_board(0xb2)))
- if (psmouse->ps2dev.serio->dev.power.power_state.event !=
- PM_EVENT_ON)
- return 0;
-
- priv->powered = 1;
- return hgpk_reset_device(psmouse, false);
-}
-
-static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
-{
- struct hgpk_data *priv = psmouse->private;
-
- return sprintf(buf, "%d\n", priv->powered);
-}
-
-static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
- const char *buf, size_t count)
-{
- struct hgpk_data *priv = psmouse->private;
- unsigned int value;
- int err;
-
- err = kstrtouint(buf, 10, &value);
- if (err)
- return err;
-
- if (value > 1)
- return -EINVAL;
-
- if (value != priv->powered) {
- /*
- * hgpk_toggle_power will deal w/ state so
- * we're not racing w/ irq
- */
- err = hgpk_toggle_powersave(psmouse, value);
- if (!err)
- priv->powered = value;
- }
-
- return err ? err : count;
-}
-
-__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
- hgpk_show_powered, hgpk_set_powered, false);
-
-static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf)
-{
- struct hgpk_data *priv = psmouse->private;
-
- return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]);
-}
-
-static ssize_t attr_set_mode(struct psmouse *psmouse, void *data,
- const char *buf, size_t len)
-{
- struct hgpk_data *priv = psmouse->private;
- enum hgpk_mode old_mode = priv->mode;
- enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len);
- struct input_dev *old_dev = psmouse->dev;
- struct input_dev *new_dev;
- int err;
-
- if (new_mode == HGPK_MODE_INVALID)
- return -EINVAL;
-
- if (old_mode == new_mode)
- return len;
-
- new_dev = input_allocate_device();
- if (!new_dev)
- return -ENOMEM;
-
- psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
-
- /* Switch device into the new mode */
- priv->mode = new_mode;
- err = hgpk_reset_device(psmouse, false);
- if (err)
- goto err_try_restore;
-
- hgpk_setup_input_device(new_dev, old_dev, new_mode);
-
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
-
- err = input_register_device(new_dev);
- if (err)
- goto err_try_restore;
-
- psmouse->dev = new_dev;
- input_unregister_device(old_dev);
-
- return len;
-
-err_try_restore:
- input_free_device(new_dev);
- priv->mode = old_mode;
- hgpk_reset_device(psmouse, false);
-
- return err;
-}
-
-PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL,
- attr_show_mode, attr_set_mode);
-
-static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
- void *data, char *buf)
-{
- return -EINVAL;
-}
-
-static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
- const char *buf, size_t count)
-{
- struct hgpk_data *priv = psmouse->private;
- unsigned int value;
- int err;
-
- err = kstrtouint(buf, 10, &value);
- if (err)
- return err;
-
- if (value != 1)
- return -EINVAL;
-
- /*
- * We queue work instead of doing recalibration right here
- * to avoid adding locking to hgpk_force_recalibrate()
- * since workqueue provides serialization.
- */
- psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
- return count;
-}
-
-__PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL,
- hgpk_trigger_recal_show, hgpk_trigger_recal, false);
-
-static void hgpk_disconnect(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
-
- device_remove_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_powered.dattr);
- device_remove_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_hgpk_mode.dattr);
-
- if (psmouse->model >= HGPK_MODEL_C)
- device_remove_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_recalibrate.dattr);
-
- psmouse_reset(psmouse);
- kfree(priv);
-}
-
-static void hgpk_recalib_work(struct work_struct *work)
-{
- struct delayed_work *w = to_delayed_work(work);
- struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
- struct psmouse *psmouse = priv->psmouse;
-
- if (hgpk_force_recalibrate(psmouse))
- psmouse_err(psmouse, "recalibration failed!\n");
-}
-
-static int hgpk_register(struct psmouse *psmouse)
-{
- struct hgpk_data *priv = psmouse->private;
- int err;
-
- /* register handlers */
- psmouse->protocol_handler = hgpk_process_byte;
- psmouse->poll = hgpk_poll;
- psmouse->disconnect = hgpk_disconnect;
- psmouse->reconnect = hgpk_reconnect;
-
- /* Disable the idle resync. */
- psmouse->resync_time = 0;
- /* Reset after a lot of bad bytes. */
- psmouse->resetafter = 1024;
-
- hgpk_setup_input_device(psmouse->dev, NULL, priv->mode);
-
- err = device_create_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_powered.dattr);
- if (err) {
- psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
- return err;
- }
-
- err = device_create_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_hgpk_mode.dattr);
- if (err) {
- psmouse_err(psmouse,
- "Failed creating 'hgpk_mode' sysfs node\n");
- goto err_remove_powered;
- }
-
- /* C-series touchpads added the recalibrate command */
- if (psmouse->model >= HGPK_MODEL_C) {
- err = device_create_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_recalibrate.dattr);
- if (err) {
- psmouse_err(psmouse,
- "Failed creating 'recalibrate' sysfs node\n");
- goto err_remove_mode;
- }
- }
-
- return 0;
-
-err_remove_mode:
- device_remove_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_hgpk_mode.dattr);
-err_remove_powered:
- device_remove_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_powered.dattr);
- return err;
-}
-
-int hgpk_init(struct psmouse *psmouse)
-{
- struct hgpk_data *priv;
- int err;
-
- priv = kzalloc_obj(*priv);
- if (!priv) {
- err = -ENOMEM;
- goto alloc_fail;
- }
-
- psmouse->private = priv;
-
- priv->psmouse = psmouse;
- priv->powered = true;
- priv->mode = hgpk_default_mode;
- INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
-
- err = hgpk_reset_device(psmouse, false);
- if (err)
- goto init_fail;
-
- err = hgpk_register(psmouse);
- if (err)
- goto init_fail;
-
- return 0;
-
-init_fail:
- kfree(priv);
-alloc_fail:
- return err;
-}
-
-static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
-{
- struct ps2dev *ps2dev = &psmouse->ps2dev;
- unsigned char param[3];
-
- /* E7, E7, E7, E9 gets us a 3 byte identifier */
- if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
- ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
- ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
- return -EIO;
- }
-
- psmouse_dbg(psmouse, "ID: %*ph\n", 3, param);
-
- /* HGPK signature: 0x67, 0x00, 0x<model> */
- if (param[0] != 0x67 || param[1] != 0x00)
- return -ENODEV;
-
- psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
-
- return param[2];
-}
-
-int hgpk_detect(struct psmouse *psmouse, bool set_properties)
-{
- int version;
-
- version = hgpk_get_model(psmouse);
- if (version < 0)
- return version;
-
- if (set_properties) {
- psmouse->vendor = "ALPS";
- psmouse->name = "HGPK";
- psmouse->model = version;
- }
-
- return 0;
-}
-
-void hgpk_module_init(void)
-{
- hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name,
- strlen(hgpk_mode_name));
- if (hgpk_default_mode == HGPK_MODE_INVALID) {
- hgpk_default_mode = HGPK_MODE_MOUSE;
- strscpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
- sizeof(hgpk_mode_name));
- }
-}
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
deleted file mode 100644
index ce041591f1a8..000000000000
--- a/drivers/input/mouse/hgpk.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
- */
-
-#ifndef _HGPK_H
-#define _HGPK_H
-
-#define HGPK_GS 0xff /* The GlideSensor */
-#define HGPK_PT 0xcf /* The PenTablet */
-
-enum hgpk_model_t {
- HGPK_MODEL_PREA = 0x0a, /* pre-B1s */
- HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */
- HGPK_MODEL_B = 0x28, /* B2s, has capacitance issues */
- HGPK_MODEL_C = 0x3c,
- HGPK_MODEL_D = 0x50, /* C1, mass production */
-};
-
-enum hgpk_spew_flag {
- NO_SPEW,
- MAYBE_SPEWING,
- SPEW_DETECTED,
- RECALIBRATING,
-};
-
-#define SPEW_WATCH_COUNT 42 /* at 12ms/packet, this is 1/2 second */
-
-enum hgpk_mode {
- HGPK_MODE_MOUSE,
- HGPK_MODE_GLIDESENSOR,
- HGPK_MODE_PENTABLET,
- HGPK_MODE_INVALID
-};
-
-struct hgpk_data {
- struct psmouse *psmouse;
- enum hgpk_mode mode;
- bool powered;
- enum hgpk_spew_flag spew_flag;
- int spew_count, x_tally, y_tally; /* spew detection */
- unsigned long recalib_window;
- struct delayed_work recalib_wq;
- int abs_x, abs_y;
- int dupe_count;
- int xbigj, ybigj, xlast, ylast; /* jumpiness detection */
- int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
-};
-
-int hgpk_detect(struct psmouse *psmouse, bool set_properties);
-int hgpk_init(struct psmouse *psmouse);
-
-#ifdef CONFIG_MOUSE_PS2_OLPC
-void hgpk_module_init(void);
-#else
-static inline void hgpk_module_init(void)
-{
-}
-#endif
-
-#endif
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
deleted file mode 100644
index 401d8bff8e84..000000000000
--- a/drivers/input/mouse/inport.c
+++ /dev/null
@@ -1,177 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 1999-2001 Vojtech Pavlik
- *
- * Based on the work of:
- * Teemu Rantanen Derrick Cole
- * Peter Cervasio Christoph Niemann
- * Philip Blundell Russell King
- * Bob Harris
- */
-
-/*
- * Inport (ATI XL and Microsoft) busmouse driver for Linux
- */
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver");
-MODULE_LICENSE("GPL");
-
-#define INPORT_BASE 0x23c
-#define INPORT_EXTENT 4
-
-#define INPORT_CONTROL_PORT INPORT_BASE + 0
-#define INPORT_DATA_PORT INPORT_BASE + 1
-#define INPORT_SIGNATURE_PORT INPORT_BASE + 2
-
-#define INPORT_REG_BTNS 0x00
-#define INPORT_REG_X 0x01
-#define INPORT_REG_Y 0x02
-#define INPORT_REG_MODE 0x07
-#define INPORT_RESET 0x80
-
-#ifdef CONFIG_MOUSE_ATIXL
-#define INPORT_NAME "ATI XL Mouse"
-#define INPORT_VENDOR 0x0002
-#define INPORT_SPEED_30HZ 0x01
-#define INPORT_SPEED_50HZ 0x02
-#define INPORT_SPEED_100HZ 0x03
-#define INPORT_SPEED_200HZ 0x04
-#define INPORT_MODE_BASE INPORT_SPEED_100HZ
-#define INPORT_MODE_IRQ 0x08
-#else
-#define INPORT_NAME "Microsoft InPort Mouse"
-#define INPORT_VENDOR 0x0001
-#define INPORT_MODE_BASE 0x10
-#define INPORT_MODE_IRQ 0x01
-#endif
-#define INPORT_MODE_HOLD 0x20
-
-#define INPORT_IRQ 5
-
-static int inport_irq = INPORT_IRQ;
-module_param_hw_named(irq, inport_irq, uint, irq, 0);
-MODULE_PARM_DESC(irq, "IRQ number (5=default)");
-
-static struct input_dev *inport_dev;
-
-static irqreturn_t inport_interrupt(int irq, void *dev_id)
-{
- unsigned char buttons;
-
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
- outb(INPORT_REG_X, INPORT_CONTROL_PORT);
- input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
-
- outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
- input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT));
-
- outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
- buttons = inb(INPORT_DATA_PORT);
-
- input_report_key(inport_dev, BTN_MIDDLE, buttons & 1);
- input_report_key(inport_dev, BTN_LEFT, buttons & 2);
- input_report_key(inport_dev, BTN_RIGHT, buttons & 4);
-
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
- input_sync(inport_dev);
- return IRQ_HANDLED;
-}
-
-static int inport_open(struct input_dev *dev)
-{
- if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
- return -EBUSY;
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
- return 0;
-}
-
-static void inport_close(struct input_dev *dev)
-{
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- free_irq(inport_irq, NULL);
-}
-
-static int __init inport_init(void)
-{
- unsigned char a, b, c;
- int err;
-
- if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
- printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
- return -EBUSY;
- }
-
- a = inb(INPORT_SIGNATURE_PORT);
- b = inb(INPORT_SIGNATURE_PORT);
- c = inb(INPORT_SIGNATURE_PORT);
- if (a == b || a != c) {
- printk(KERN_INFO "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
- err = -ENODEV;
- goto err_release_region;
- }
-
- inport_dev = input_allocate_device();
- if (!inport_dev) {
- printk(KERN_ERR "inport.c: Not enough memory for input device\n");
- err = -ENOMEM;
- goto err_release_region;
- }
-
- inport_dev->name = INPORT_NAME;
- inport_dev->phys = "isa023c/input0";
- inport_dev->id.bustype = BUS_ISA;
- inport_dev->id.vendor = INPORT_VENDOR;
- inport_dev->id.product = 0x0001;
- inport_dev->id.version = 0x0100;
-
- inport_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
- inport_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
- BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
- inport_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
-
- inport_dev->open = inport_open;
- inport_dev->close = inport_close;
-
- outb(INPORT_RESET, INPORT_CONTROL_PORT);
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
-
- err = input_register_device(inport_dev);
- if (err)
- goto err_free_dev;
-
- return 0;
-
- err_free_dev:
- input_free_device(inport_dev);
- err_release_region:
- release_region(INPORT_BASE, INPORT_EXTENT);
-
- return err;
-}
-
-static void __exit inport_exit(void)
-{
- input_unregister_device(inport_dev);
- release_region(INPORT_BASE, INPORT_EXTENT);
-}
-
-module_init(inport_init);
-module_exit(inport_exit);
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
deleted file mode 100644
index 0aab63dbc30a..000000000000
--- a/drivers/input/mouse/logibm.c
+++ /dev/null
@@ -1,166 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 1999-2001 Vojtech Pavlik
- *
- * Based on the work of:
- * James Banks Matthew Dillon
- * David Giller Nathan Laredo
- * Linus Torvalds Johan Myreen
- * Cliff Matthews Philip Blundell
- * Russell King
- */
-
-/*
- * Logitech Bus Mouse Driver for Linux
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Logitech busmouse driver");
-MODULE_LICENSE("GPL");
-
-#define LOGIBM_BASE 0x23c
-#define LOGIBM_EXTENT 4
-
-#define LOGIBM_DATA_PORT LOGIBM_BASE + 0
-#define LOGIBM_SIGNATURE_PORT LOGIBM_BASE + 1
-#define LOGIBM_CONTROL_PORT LOGIBM_BASE + 2
-#define LOGIBM_CONFIG_PORT LOGIBM_BASE + 3
-
-#define LOGIBM_ENABLE_IRQ 0x00
-#define LOGIBM_DISABLE_IRQ 0x10
-#define LOGIBM_READ_X_LOW 0x80
-#define LOGIBM_READ_X_HIGH 0xa0
-#define LOGIBM_READ_Y_LOW 0xc0
-#define LOGIBM_READ_Y_HIGH 0xe0
-
-#define LOGIBM_DEFAULT_MODE 0x90
-#define LOGIBM_CONFIG_BYTE 0x91
-#define LOGIBM_SIGNATURE_BYTE 0xa5
-
-#define LOGIBM_IRQ 5
-
-static int logibm_irq = LOGIBM_IRQ;
-module_param_hw_named(irq, logibm_irq, uint, irq, 0);
-MODULE_PARM_DESC(irq, "IRQ number (5=default)");
-
-static struct input_dev *logibm_dev;
-
-static irqreturn_t logibm_interrupt(int irq, void *dev_id)
-{
- char dx, dy;
- unsigned char buttons;
-
- outb(LOGIBM_READ_X_LOW, LOGIBM_CONTROL_PORT);
- dx = (inb(LOGIBM_DATA_PORT) & 0xf);
- outb(LOGIBM_READ_X_HIGH, LOGIBM_CONTROL_PORT);
- dx |= (inb(LOGIBM_DATA_PORT) & 0xf) << 4;
- outb(LOGIBM_READ_Y_LOW, LOGIBM_CONTROL_PORT);
- dy = (inb(LOGIBM_DATA_PORT) & 0xf);
- outb(LOGIBM_READ_Y_HIGH, LOGIBM_CONTROL_PORT);
- buttons = inb(LOGIBM_DATA_PORT);
- dy |= (buttons & 0xf) << 4;
- buttons = ~buttons >> 5;
-
- input_report_rel(logibm_dev, REL_X, dx);
- input_report_rel(logibm_dev, REL_Y, dy);
- input_report_key(logibm_dev, BTN_RIGHT, buttons & 1);
- input_report_key(logibm_dev, BTN_MIDDLE, buttons & 2);
- input_report_key(logibm_dev, BTN_LEFT, buttons & 4);
- input_sync(logibm_dev);
-
- outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
- return IRQ_HANDLED;
-}
-
-static int logibm_open(struct input_dev *dev)
-{
- if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
- printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
- return -EBUSY;
- }
- outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
- return 0;
-}
-
-static void logibm_close(struct input_dev *dev)
-{
- outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
- free_irq(logibm_irq, NULL);
-}
-
-static int __init logibm_init(void)
-{
- int err;
-
- if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
- printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
- return -EBUSY;
- }
-
- outb(LOGIBM_CONFIG_BYTE, LOGIBM_CONFIG_PORT);
- outb(LOGIBM_SIGNATURE_BYTE, LOGIBM_SIGNATURE_PORT);
- udelay(100);
-
- if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
- printk(KERN_INFO "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
- err = -ENODEV;
- goto err_release_region;
- }
-
- outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
- outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
-
- logibm_dev = input_allocate_device();
- if (!logibm_dev) {
- printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
- err = -ENOMEM;
- goto err_release_region;
- }
-
- logibm_dev->name = "Logitech bus mouse";
- logibm_dev->phys = "isa023c/input0";
- logibm_dev->id.bustype = BUS_ISA;
- logibm_dev->id.vendor = 0x0003;
- logibm_dev->id.product = 0x0001;
- logibm_dev->id.version = 0x0100;
-
- logibm_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
- logibm_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
- BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
- logibm_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
-
- logibm_dev->open = logibm_open;
- logibm_dev->close = logibm_close;
-
- err = input_register_device(logibm_dev);
- if (err)
- goto err_free_dev;
-
- return 0;
-
- err_free_dev:
- input_free_device(logibm_dev);
- err_release_region:
- release_region(LOGIBM_BASE, LOGIBM_EXTENT);
-
- return err;
-}
-
-static void __exit logibm_exit(void)
-{
- input_unregister_device(logibm_dev);
- release_region(LOGIBM_BASE, LOGIBM_EXTENT);
-}
-
-module_init(logibm_init);
-module_exit(logibm_exit);
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index ff8cd2d68a3c..6ab5f1d96eae 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -26,7 +26,6 @@
#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
-#include "hgpk.h"
#include "lifebook.h"
#include "trackpoint.h"
#include "touchkit_ps2.h"
@@ -114,8 +113,6 @@ ATTRIBUTE_GROUPS(psmouse_dev);
*/
static DEFINE_MUTEX(psmouse_mutex);
-static struct workqueue_struct *kpsmoused_wq;
-
struct psmouse *psmouse_from_serio(struct serio *serio)
{
struct ps2dev *ps2dev = serio_get_drvdata(serio);
@@ -241,12 +238,6 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
return PSMOUSE_FULL_PACKET;
}
-void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
- unsigned long delay)
-{
- queue_delayed_work(kpsmoused_wq, work, delay);
-}
-
/*
* __psmouse_set_state() sets new psmouse state and resets all flags.
*/
@@ -380,7 +371,7 @@ static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
- psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
+ schedule_work(&psmouse->resync_work);
return;
}
@@ -393,9 +384,7 @@ static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
return;
}
- if (psmouse->packet[1] == PSMOUSE_RET_ID ||
- (psmouse->protocol->type == PSMOUSE_HGPK &&
- psmouse->packet[1] == PSMOUSE_RET_BAT)) {
+ if (psmouse->packet[1] == PSMOUSE_RET_ID) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
serio_reconnect(ps2dev->serio);
return;
@@ -418,7 +407,7 @@ static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
- psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
+ schedule_work(&psmouse->resync_work);
return;
}
@@ -837,14 +826,6 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.detect = touchkit_ps2_detect,
},
#endif
-#ifdef CONFIG_MOUSE_PS2_OLPC
- {
- .type = PSMOUSE_HGPK,
- .name = "OLPC HGPK",
- .alias = "hgpk",
- .detect = hgpk_detect,
- },
-#endif
#ifdef CONFIG_MOUSE_PS2_ELANTECH
{
.type = PSMOUSE_ELANTECH,
@@ -1153,13 +1134,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_ALPS;
}
- /* Try OLPC HGPK touchpad */
- if (max_proto > PSMOUSE_IMEX &&
- psmouse_try_protocol(psmouse, PSMOUSE_HGPK, &max_proto,
- set_properties, true)) {
- return PSMOUSE_HGPK;
- }
-
/* Try Elantech touchpad */
if (max_proto > PSMOUSE_IMEX &&
psmouse_try_protocol(psmouse, PSMOUSE_ELANTECH,
@@ -1331,7 +1305,7 @@ int psmouse_deactivate(struct psmouse *psmouse)
static void psmouse_resync(struct work_struct *work)
{
struct psmouse *parent = NULL, *psmouse =
- container_of(work, struct psmouse, resync_work.work);
+ container_of(work, struct psmouse, resync_work);
struct serio *serio = psmouse->ps2dev.serio;
psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
bool failed = false, enabled = false;
@@ -1484,7 +1458,7 @@ static void psmouse_disconnect(struct serio *serio)
/* make sure we don't have a resync in progress */
mutex_unlock(&psmouse_mutex);
- flush_workqueue(kpsmoused_wq);
+ disable_work_sync(&psmouse->resync_work);
mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1598,7 +1572,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
ps2_init(&psmouse->ps2dev, serio,
psmouse_pre_receive_byte, psmouse_receive_byte);
- INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
+ INIT_WORK(&psmouse->resync_work, psmouse_resync);
psmouse->dev = input_dev;
scnprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
@@ -2035,27 +2009,17 @@ static int __init psmouse_init(void)
lifebook_module_init();
synaptics_module_init();
- hgpk_module_init();
err = psmouse_smbus_module_init();
if (err)
return err;
- kpsmoused_wq = alloc_ordered_workqueue("kpsmoused", 0);
- if (!kpsmoused_wq) {
- pr_err("failed to create kpsmoused workqueue\n");
- err = -ENOMEM;
- goto err_smbus_exit;
- }
-
err = serio_register_driver(&psmouse_drv);
if (err)
- goto err_destroy_wq;
+ goto err_smbus_exit;
return 0;
-err_destroy_wq:
- destroy_workqueue(kpsmoused_wq);
err_smbus_exit:
psmouse_smbus_module_exit();
return err;
@@ -2064,7 +2028,6 @@ err_smbus_exit:
static void __exit psmouse_exit(void)
{
serio_unregister_driver(&psmouse_drv);
- destroy_workqueue(kpsmoused_wq);
psmouse_smbus_module_exit();
}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 4d8acfe0d82a..90ed8cd15d85 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -59,7 +59,7 @@ enum psmouse_type {
PSMOUSE_TRACKPOINT,
PSMOUSE_TOUCHKIT_PS2,
PSMOUSE_CORTRON,
- PSMOUSE_HGPK,
+ PSMOUSE_HGPK, /* No longer used */
PSMOUSE_ELANTECH,
PSMOUSE_FSP,
PSMOUSE_SYNAPTICS_RELATIVE,
@@ -90,7 +90,7 @@ struct psmouse {
void *private;
struct input_dev *dev;
struct ps2dev ps2dev;
- struct delayed_work resync_work;
+ struct work_struct resync_work;
const char *vendor;
const char *name;
const struct psmouse_protocol *protocol;
@@ -132,8 +132,6 @@ struct psmouse {
struct psmouse *psmouse_from_serio(struct serio *serio);
-void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
- unsigned long delay);
int psmouse_reset(struct psmouse *psmouse);
void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c
index 5a86f6f387d8..880a0c79148c 100644
--- a/drivers/input/mouse/synaptics_usb.c
+++ b/drivers/input/mouse/synaptics_usb.c
@@ -220,25 +220,6 @@ resubmit:
__func__, error);
}
-static struct usb_endpoint_descriptor *
-synusb_get_in_endpoint(struct usb_host_interface *iface)
-{
-
- struct usb_endpoint_descriptor *endpoint;
- int i;
-
- for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
- endpoint = &iface->endpoint[i].desc;
-
- if (usb_endpoint_is_int_in(endpoint)) {
- /* we found our interrupt in endpoint */
- return endpoint;
- }
- }
-
- return NULL;
-}
-
static int synusb_open(struct input_dev *dev)
{
struct synusb *synusb = input_get_drvdata(dev);
@@ -307,8 +288,8 @@ static int synusb_probe(struct usb_interface *intf,
return error;
}
- ep = synusb_get_in_endpoint(intf->cur_altsetting);
- if (!ep)
+ error = usb_find_int_in_endpoint(intf->cur_altsetting, &ep);
+ if (error)
return -ENODEV;
synusb = kzalloc_obj(*synusb);