summaryrefslogtreecommitdiff
path: root/drivers/input/mouse
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r--drivers/input/mouse/Kconfig46
-rw-r--r--drivers/input/mouse/Makefile4
-rw-r--r--drivers/input/mouse/alps.c13
-rw-r--r--drivers/input/mouse/alps.h4
-rw-r--r--drivers/input/mouse/appletouch.c23
-rw-r--r--drivers/input/mouse/bcm5974.c44
-rw-r--r--drivers/input/mouse/byd.c4
-rw-r--r--drivers/input/mouse/cyapa.c2
-rw-r--r--drivers/input/mouse/cypress_ps2.c2
-rw-r--r--drivers/input/mouse/elan_i2c.h3
-rw-r--r--drivers/input/mouse/elan_i2c_core.c82
-rw-r--r--drivers/input/mouse/elan_i2c_i2c.c7
-rw-r--r--drivers/input/mouse/elan_i2c_smbus.c3
-rw-r--r--drivers/input/mouse/elantech.c2
-rw-r--r--drivers/input/mouse/focaltech.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/lifebook.c2
-rw-r--r--drivers/input/mouse/logibm.c166
-rw-r--r--drivers/input/mouse/maplemouse.c11
-rw-r--r--drivers/input/mouse/pc110pad.c160
-rw-r--r--drivers/input/mouse/psmouse-base.c141
-rw-r--r--drivers/input/mouse/psmouse-smbus.c4
-rw-r--r--drivers/input/mouse/psmouse.h6
-rw-r--r--drivers/input/mouse/sentelic.c2
-rw-r--r--drivers/input/mouse/sermouse.c2
-rw-r--r--drivers/input/mouse/synaptics.c14
-rw-r--r--drivers/input/mouse/synaptics_i2c.c4
-rw-r--r--drivers/input/mouse/synaptics_usb.c25
-rw-r--r--drivers/input/mouse/trackpoint.c48
-rw-r--r--drivers/input/mouse/trackpoint.h5
-rw-r--r--drivers/input/mouse/vmmouse.c2
-rw-r--r--drivers/input/mouse/vsxxxaa.c2
34 files changed, 280 insertions, 1875 deletions
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 833b643f0616..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,42 +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_PC110PAD
- tristate "IBM PC110 touchpad"
- depends on ISA
- help
- Say Y if you have the IBM PC-110 micro-notebook and want its
- touchpad supported.
-
- To compile this driver as a module, choose M here: the
- module will be called pc110pad.
-
config MOUSE_AMIGA
tristate "Amiga mouse"
depends on AMIGA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index a1336d5bee6f..ed40f141691e 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -12,10 +12,7 @@ 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_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
@@ -29,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 df8953a5196e..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;
@@ -3206,7 +3205,7 @@ int alps_detect(struct psmouse *psmouse, bool set_properties)
*/
psmouse_reset(psmouse);
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
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 3ce63fb35992..eebeb57515e1 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -829,30 +829,21 @@ 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 */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ error = -ENOMEM;
+ dev = kzalloc_obj(*dev);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
dev_err(&iface->dev, "Out of memory\n");
@@ -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/bcm5974.c b/drivers/input/mouse/bcm5974.c
index dfdfb59cc8b5..e772bac3b64c 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -286,6 +286,8 @@ struct bcm5974 {
const struct tp_finger *index[MAX_FINGERS]; /* finger index data */
struct input_mt_pos pos[MAX_FINGERS]; /* position array */
int slots[MAX_FINGERS]; /* slot assignments */
+ struct work_struct mode_reset_work;
+ unsigned long last_mode_reset;
};
/* trackpad finger block data, le16-aligned */
@@ -696,6 +698,32 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
return retval;
}
+/*
+ * Mode switches sent before the control response are ignored.
+ * Fixing this state requires switching to normal mode and waiting
+ * about 1ms before switching back to wellspring mode.
+ */
+static void bcm5974_mode_reset_work(struct work_struct *work)
+{
+ struct bcm5974 *dev = container_of(work, struct bcm5974, mode_reset_work);
+ int error;
+
+ guard(mutex)(&dev->pm_mutex);
+ dev->last_mode_reset = jiffies;
+
+ error = bcm5974_wellspring_mode(dev, false);
+ if (error) {
+ dev_err(&dev->intf->dev, "reset to normal mode failed\n");
+ return;
+ }
+
+ fsleep(1000);
+
+ error = bcm5974_wellspring_mode(dev, true);
+ if (error)
+ dev_err(&dev->intf->dev, "mode switch after reset failed\n");
+}
+
static void bcm5974_irq_button(struct urb *urb)
{
struct bcm5974 *dev = urb->context;
@@ -752,10 +780,20 @@ static void bcm5974_irq_trackpad(struct urb *urb)
if (dev->tp_urb->actual_length == 2)
goto exit;
- if (report_tp_state(dev, dev->tp_urb->actual_length))
+ if (report_tp_state(dev, dev->tp_urb->actual_length)) {
dprintk(1, "bcm5974: bad trackpad package, length: %d\n",
dev->tp_urb->actual_length);
+ /*
+ * Receiving a HID packet means we aren't in wellspring mode.
+ * If we haven't tried a reset in the last second, try now.
+ */
+ if (dev->tp_urb->actual_length == 8 &&
+ time_after(jiffies, dev->last_mode_reset + msecs_to_jiffies(1000))) {
+ schedule_work(&dev->mode_reset_work);
+ }
+ }
+
exit:
error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC);
if (error)
@@ -895,7 +933,7 @@ static int bcm5974_probe(struct usb_interface *iface,
cfg = bcm5974_get_config(udev);
/* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc_obj(*dev);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
dev_err(&iface->dev, "out of memory\n");
@@ -906,6 +944,7 @@ static int bcm5974_probe(struct usb_interface *iface,
dev->intf = iface;
dev->input = input_dev;
dev->cfg = *cfg;
+ INIT_WORK(&dev->mode_reset_work, bcm5974_mode_reset_work);
mutex_init(&dev->pm_mutex);
/* setup urbs */
@@ -998,6 +1037,7 @@ static void bcm5974_disconnect(struct usb_interface *iface)
{
struct bcm5974 *dev = usb_get_intfdata(iface);
+ disable_work_sync(&dev->mode_reset_work);
usb_set_intfdata(iface, NULL);
input_unregister_device(dev->input);
diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c
index 7f85c7ab68c5..5fc3c629590a 100644
--- a/drivers/input/mouse/byd.c
+++ b/drivers/input/mouse/byd.c
@@ -423,7 +423,7 @@ static void byd_disconnect(struct psmouse *psmouse)
struct byd_data *priv = psmouse->private;
if (priv) {
- timer_delete(&priv->timer);
+ timer_shutdown_sync(&priv->timer);
kfree(psmouse->private);
psmouse->private = NULL;
}
@@ -469,7 +469,7 @@ int byd_init(struct psmouse *psmouse)
if (byd_reset_touchpad(psmouse))
return -EIO;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 6e0d956617a1..47000c30e4d8 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -1456,7 +1456,7 @@ static const struct dev_pm_ops cyapa_pm_ops = {
};
static const struct i2c_device_id cyapa_id_table[] = {
- { "cyapa" },
+ { .name = "cyapa" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyapa_id_table);
diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c
index 9446657a5f35..309063d07b4d 100644
--- a/drivers/input/mouse/cypress_ps2.c
+++ b/drivers/input/mouse/cypress_ps2.c
@@ -624,7 +624,7 @@ int cypress_init(struct psmouse *psmouse)
struct cytp_data *cytp;
int error;
- cytp = kzalloc(sizeof(*cytp), GFP_KERNEL);
+ cytp = kzalloc_obj(*cytp);
if (!cytp)
return -ENOMEM;
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index 3c84deefa327..555824e57743 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -102,7 +102,8 @@ struct elan_transport_ops {
int (*prepare_fw_update)(struct i2c_client *client, u16 ic_type,
u8 iap_version, u16 fw_page_size);
int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size,
- const u8 *page, u16 checksum, int idx);
+ u16 fw_page_delay, const u8 *page, u16 checksum,
+ int idx);
int (*finish_fw_update)(struct i2c_client *client,
struct completion *reset_done);
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index fee1796da3d0..f5e505edbc33 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -16,27 +16,27 @@
*/
#include <linux/acpi.h>
+#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string_choices.h>
-#include <linux/input.h>
-#include <linux/uaccess.h>
#include <linux/jiffies.h>
-#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_wakeirq.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string_choices.h>
+#include <linux/uaccess.h>
#include <linux/unaligned.h>
#include "elan_i2c.h"
@@ -86,6 +86,7 @@ struct elan_tp_data {
u16 ic_type;
u16 fw_validpage_count;
u16 fw_page_size;
+ u16 fw_page_delay;
u32 fw_signature_address;
u8 min_baseline;
@@ -127,8 +128,11 @@ static u32 elan_i2c_lookup_quirks(u16 ic_type, u16 product_id)
}
static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count,
- u32 *signature_address, u16 *page_size)
+ u32 *signature_address, u16 *page_size,
+ u16 *page_delay)
{
+ *page_delay = 30;
+
switch (ic_type) {
case 0x00:
case 0x06:
@@ -162,6 +166,10 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count,
case 0x15:
*validpage_count = 1024;
break;
+ case 0x19:
+ *validpage_count = 2032;
+ *page_delay = 10;
+ break;
default:
/* unknown ic type clear value */
*validpage_count = 0;
@@ -176,6 +184,7 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count,
if ((ic_type == 0x14 || ic_type == 0x15) && iap_version >= 2) {
*validpage_count /= 8;
*page_size = ETP_FW_PAGE_SIZE_512;
+ *page_delay = 50;
} else if (ic_type >= 0x0D && iap_version >= 1) {
*validpage_count /= 2;
*page_size = ETP_FW_PAGE_SIZE_128;
@@ -365,7 +374,8 @@ static int elan_query_device_info(struct elan_tp_data *data)
error = elan_get_fwinfo(data->ic_type, data->iap_version,
&data->fw_validpage_count,
&data->fw_signature_address,
- &data->fw_page_size);
+ &data->fw_page_size,
+ &data->fw_page_delay);
if (error)
dev_warn(&data->client->dev,
"unexpected iap version %#04x (ic type: %#04x), firmware update will not work\n",
@@ -425,8 +435,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
if (error)
return error;
}
- data->width_x = data->max_x / x_traces;
- data->width_y = data->max_y / y_traces;
+
+ if (!x_traces || !y_traces) {
+ dev_warn(&client->dev,
+ "invalid trace numbers: x=%u, y=%u\n",
+ x_traces, y_traces);
+ data->width_x = 1;
+ data->width_y = 1;
+ } else {
+ data->width_x = data->max_x / x_traces;
+ data->width_y = data->max_y / y_traces;
+ }
if (device_property_read_u32(&client->dev,
"touchscreen-x-mm", &x_mm) ||
@@ -440,8 +459,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
data->x_res = elan_convert_resolution(hw_x_res, data->pattern);
data->y_res = elan_convert_resolution(hw_y_res, data->pattern);
} else {
- data->x_res = (data->max_x + 1) / x_mm;
- data->y_res = (data->max_y + 1) / y_mm;
+ if (unlikely(x_mm == 0 || y_mm == 0)) {
+ dev_warn(&client->dev,
+ "invalid physical dimensions: x_mm=%u, y_mm=%u\n",
+ x_mm, y_mm);
+ data->x_res = 1;
+ data->y_res = 1;
+ } else {
+ data->x_res = (data->max_x + 1) / x_mm;
+ data->y_res = (data->max_y + 1) / y_mm;
+ }
}
if (device_property_read_bool(&client->dev, "elan,clickpad"))
@@ -459,14 +486,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
**********************************************************
*/
static int elan_write_fw_block(struct elan_tp_data *data, u16 page_size,
- const u8 *page, u16 checksum, int idx)
+ u16 page_delay, const u8 *page, u16 checksum,
+ int idx)
{
int retry = ETP_RETRY_COUNT;
int error;
do {
error = data->ops->write_fw_block(data->client, page_size,
- page, checksum, idx);
+ page_delay, page, checksum,
+ idx);
if (!error)
return 0;
@@ -505,7 +534,8 @@ static int __elan_update_firmware(struct elan_tp_data *data,
checksum += ((page[j + 1] << 8) | page[j]);
error = elan_write_fw_block(data, data->fw_page_size,
- page, checksum, i);
+ data->fw_page_delay, page, checksum,
+ i);
if (error) {
dev_err(dev, "write page %d fail: %d\n", i, error);
return error;
@@ -645,6 +675,11 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
return error;
}
+ if (fw->size < data->fw_signature_address + sizeof(signature)) {
+ dev_err(dev, "firmware file too small\n");
+ return -EBADF;
+ }
+
/* Firmware file must match signature data */
fw_signature = &fw->data[data->fw_signature_address];
if (memcmp(fw_signature, signature, sizeof(signature)) != 0) {
@@ -948,6 +983,7 @@ static void elan_report_contact(struct elan_tp_data *data, int contact_num,
if (data->report_features & ETP_FEATURE_REPORT_MK) {
unsigned int mk_x, mk_y, area_x, area_y;
+ int adj_width_x, adj_width_y;
u8 mk_data = high_precision ?
packet[ETP_MK_DATA_OFFSET + contact_num] :
finger_data[3];
@@ -959,8 +995,14 @@ static void elan_report_contact(struct elan_tp_data *data, int contact_num,
* To avoid treating large finger as palm, let's reduce
* the width x and y per trace.
*/
- area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE);
- area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE);
+
+ adj_width_x = data->width_x > ETP_FWIDTH_REDUCE ?
+ data->width_x - ETP_FWIDTH_REDUCE : 0;
+ adj_width_y = data->width_y > ETP_FWIDTH_REDUCE ?
+ data->width_y - ETP_FWIDTH_REDUCE : 0;
+
+ area_x = mk_x * adj_width_x;
+ area_y = mk_y * adj_width_y;
input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
input_report_abs(input, ABS_MT_TOUCH_MAJOR,
@@ -1399,7 +1441,7 @@ err:
static DEFINE_SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume);
static const struct i2c_device_id elan_id[] = {
- { DRIVER_NAME },
+ { .name = DRIVER_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, elan_id);
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index a9057d124a88..56a745c0555b 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -625,7 +625,8 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
}
static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size,
- const u8 *page, u16 checksum, int idx)
+ u16 fw_page_delay, const u8 *page, u16 checksum,
+ int idx)
{
struct device *dev = &client->dev;
u8 val[3];
@@ -650,7 +651,7 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size,
}
/* Wait for F/W to update one page ROM data. */
- msleep(fw_page_size == ETP_FW_PAGE_SIZE_512 ? 50 : 35);
+ msleep(fw_page_delay);
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
if (error) {
@@ -690,7 +691,7 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client,
if (error) {
dev_err(dev, "device reset failed: %d\n", error);
} else if (!wait_for_completion_timeout(completion,
- msecs_to_jiffies(300))) {
+ msecs_to_jiffies(700))) {
dev_err(dev, "timeout waiting for device reset\n");
error = -ETIMEDOUT;
}
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index 6dc148b9d959..0287441cda46 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -416,7 +416,8 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client, u16 ic_type,
static int elan_smbus_write_fw_block(struct i2c_client *client, u16 fw_page_size,
- const u8 *page, u16 checksum, int idx)
+ u16 fw_page_delay, const u8 *page, u16 checksum,
+ int idx)
{
struct device *dev = &client->dev;
int error;
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 79ad98cc1e79..f8575b80d19d 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -2074,7 +2074,7 @@ static int elantech_setup_ps2(struct psmouse *psmouse,
int error = -EINVAL;
struct input_dev *tp_dev;
- psmouse->private = etd = kzalloc(sizeof(*etd), GFP_KERNEL);
+ psmouse->private = etd = kzalloc_obj(*etd);
if (!etd)
return -ENOMEM;
diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c
index 356b99d48544..3efef6c98393 100644
--- a/drivers/input/mouse/focaltech.c
+++ b/drivers/input/mouse/focaltech.c
@@ -78,8 +78,8 @@ struct focaltech_finger_state {
* Absolute position (from the bottom left corner) of the
* finger.
*/
- unsigned int x;
- unsigned int y;
+ int x;
+ int y;
};
/*
@@ -108,7 +108,7 @@ struct focaltech_hw_state {
};
struct focaltech_data {
- unsigned int x_max, y_max;
+ int x_max, y_max;
struct focaltech_hw_state state;
};
@@ -126,17 +126,16 @@ static void focaltech_report_state(struct psmouse *psmouse)
input_mt_slot(dev, i);
input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
if (active) {
- unsigned int clamped_x, clamped_y;
/*
* The touchpad might report invalid data, so we clamp
* the resulting values so that we do not confuse
- * userspace.
+ * userspace or accumulate coordinate wind-up.
*/
- clamped_x = clamp(finger->x, 0U, priv->x_max);
- clamped_y = clamp(finger->y, 0U, priv->y_max);
- input_report_abs(dev, ABS_MT_POSITION_X, clamped_x);
+ finger->x = clamp(finger->x, 0, priv->x_max);
+ finger->y = clamp(finger->y, 0, priv->y_max);
+ input_report_abs(dev, ABS_MT_POSITION_X, finger->x);
input_report_abs(dev, ABS_MT_POSITION_Y,
- priv->y_max - clamped_y);
+ priv->y_max - finger->y);
input_report_abs(dev, ABS_TOOL_WIDTH, state->width);
}
}
@@ -197,7 +196,7 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
{
struct focaltech_data *priv = psmouse->private;
struct focaltech_hw_state *state = &priv->state;
- int finger1, finger2;
+ unsigned int finger1, finger2;
state->pressed = packet[0] >> 7;
finger1 = ((packet[0] >> 4) & 0x7) - 1;
@@ -408,7 +407,7 @@ int focaltech_init(struct psmouse *psmouse)
struct focaltech_data *priv;
int error;
- psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ psmouse->private = priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
deleted file mode 100644
index 6125652e5ad8..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(sizeof(*priv), GFP_KERNEL);
- 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/lifebook.c b/drivers/input/mouse/lifebook.c
index 283ef46f039f..ef11b7b19833 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -273,7 +273,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse)
struct lifebook_data *priv;
int error = -ENOMEM;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
dev2 = input_allocate_device();
if (!priv || !dev2)
goto err_out;
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/maplemouse.c b/drivers/input/mouse/maplemouse.c
index baef4be14b54..0c8f7d1b02aa 100644
--- a/drivers/input/mouse/maplemouse.c
+++ b/drivers/input/mouse/maplemouse.c
@@ -48,7 +48,7 @@ static void dc_mouse_callback(struct mapleq *mq)
static int dc_mouse_open(struct input_dev *dev)
{
- struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev));
+ struct dc_mouse *mse = input_get_drvdata(dev);
maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50,
MAPLE_FUNC_MOUSE);
@@ -58,7 +58,7 @@ static int dc_mouse_open(struct input_dev *dev)
static void dc_mouse_close(struct input_dev *dev)
{
- struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev));
+ struct dc_mouse *mse = input_get_drvdata(dev);
maple_getcond_callback(mse->mdev, dc_mouse_callback, 0,
MAPLE_FUNC_MOUSE);
@@ -73,7 +73,7 @@ static int probe_maple_mouse(struct device *dev)
struct input_dev *input_dev;
struct dc_mouse *mse;
- mse = kzalloc(sizeof(*mse), GFP_KERNEL);
+ mse = kzalloc_obj(*mse);
if (!mse) {
error = -ENOMEM;
goto fail;
@@ -88,6 +88,9 @@ static int probe_maple_mouse(struct device *dev)
mse->dev = input_dev;
mse->mdev = mdev;
+ maple_set_drvdata(mdev, mse);
+
+ input_set_drvdata(input_dev, mse);
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
@@ -102,12 +105,12 @@ static int probe_maple_mouse(struct device *dev)
goto fail_register;
mdev->driver = mdrv;
- maple_set_drvdata(mdev, mse);
return error;
fail_register:
input_free_device(input_dev);
+ maple_set_drvdata(mdev, NULL);
fail_nomem:
kfree(mse);
fail:
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
deleted file mode 100644
index efa58049f746..000000000000
--- a/drivers/input/mouse/pc110pad.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 2000-2001 Vojtech Pavlik
- *
- * Based on the work of:
- * Alan Cox Robin O'Leary
- */
-
-/*
- * IBM PC110 touchpad driver for Linux
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/input.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("IBM PC110 touchpad driver");
-MODULE_LICENSE("GPL");
-
-#define PC110PAD_OFF 0x30
-#define PC110PAD_ON 0x38
-
-static int pc110pad_irq = 10;
-static int pc110pad_io = 0x15e0;
-
-static struct input_dev *pc110pad_dev;
-static int pc110pad_data[3];
-static int pc110pad_count;
-
-static irqreturn_t pc110pad_interrupt(int irq, void *ptr)
-{
- int value = inb_p(pc110pad_io);
- int handshake = inb_p(pc110pad_io + 2);
-
- outb(handshake | 1, pc110pad_io + 2);
- udelay(2);
- outb(handshake & ~1, pc110pad_io + 2);
- udelay(2);
- inb_p(0x64);
-
- pc110pad_data[pc110pad_count++] = value;
-
- if (pc110pad_count < 3)
- return IRQ_HANDLED;
-
- input_report_key(pc110pad_dev, BTN_TOUCH,
- pc110pad_data[0] & 0x01);
- input_report_abs(pc110pad_dev, ABS_X,
- pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
- input_report_abs(pc110pad_dev, ABS_Y,
- pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
- input_sync(pc110pad_dev);
-
- pc110pad_count = 0;
- return IRQ_HANDLED;
-}
-
-static void pc110pad_close(struct input_dev *dev)
-{
- outb(PC110PAD_OFF, pc110pad_io + 2);
-}
-
-static int pc110pad_open(struct input_dev *dev)
-{
- pc110pad_interrupt(0, NULL);
- pc110pad_interrupt(0, NULL);
- pc110pad_interrupt(0, NULL);
- outb(PC110PAD_ON, pc110pad_io + 2);
- pc110pad_count = 0;
-
- return 0;
-}
-
-/*
- * We try to avoid enabling the hardware if it's not
- * there, but we don't know how to test. But we do know
- * that the PC110 is not a PCI system. So if we find any
- * PCI devices in the machine, we don't have a PC110.
- */
-static int __init pc110pad_init(void)
-{
- int err;
-
- if (!no_pci_devices())
- return -ENODEV;
-
- if (!request_region(pc110pad_io, 4, "pc110pad")) {
- printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n",
- pc110pad_io, pc110pad_io + 4);
- return -EBUSY;
- }
-
- outb(PC110PAD_OFF, pc110pad_io + 2);
-
- if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
- printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
- err = -EBUSY;
- goto err_release_region;
- }
-
- pc110pad_dev = input_allocate_device();
- if (!pc110pad_dev) {
- printk(KERN_ERR "pc110pad: Not enough memory.\n");
- err = -ENOMEM;
- goto err_free_irq;
- }
-
- pc110pad_dev->name = "IBM PC110 TouchPad";
- pc110pad_dev->phys = "isa15e0/input0";
- pc110pad_dev->id.bustype = BUS_ISA;
- pc110pad_dev->id.vendor = 0x0003;
- pc110pad_dev->id.product = 0x0001;
- pc110pad_dev->id.version = 0x0100;
-
- pc110pad_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- pc110pad_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
- pc110pad_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
- input_abs_set_max(pc110pad_dev, ABS_X, 0x1ff);
- input_abs_set_max(pc110pad_dev, ABS_Y, 0x0ff);
-
- pc110pad_dev->open = pc110pad_open;
- pc110pad_dev->close = pc110pad_close;
-
- err = input_register_device(pc110pad_dev);
- if (err)
- goto err_free_dev;
-
- return 0;
-
- err_free_dev:
- input_free_device(pc110pad_dev);
- err_free_irq:
- free_irq(pc110pad_irq, NULL);
- err_release_region:
- release_region(pc110pad_io, 4);
-
- return err;
-}
-
-static void __exit pc110pad_exit(void)
-{
- outb(PC110PAD_OFF, pc110pad_io + 2);
- free_irq(pc110pad_irq, NULL);
- input_unregister_device(pc110pad_dev);
- release_region(pc110pad_io, 4);
-}
-
-module_init(pc110pad_init);
-module_exit(pc110pad_exit);
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 77ea7da3b1c5..23164688210d 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.
*/
@@ -265,9 +256,8 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta
*/
void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
- serio_pause_rx(psmouse->ps2dev.serio);
+ guard(serio_pause_rx)(psmouse->ps2dev.serio);
__psmouse_set_state(psmouse, new_state);
- serio_continue_rx(psmouse->ps2dev.serio);
}
/*
@@ -276,7 +266,15 @@ void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
*/
static int psmouse_handle_byte(struct psmouse *psmouse)
{
- psmouse_ret_t rc = psmouse->protocol_handler(psmouse);
+ psmouse_ret_t rc;
+
+ /* protocol_handler is NULL when device is being disconnected */
+ if (unlikely(!psmouse->protocol_handler)) {
+ psmouse->pktcnt = 0;
+ return 0;
+ }
+
+ rc = psmouse->protocol_handler(psmouse);
switch (rc) {
case PSMOUSE_BAD_DATA:
@@ -380,7 +378,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 +391,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 +414,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;
}
@@ -495,13 +491,16 @@ static int psmouse_poll(struct psmouse *psmouse)
PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
}
-static bool psmouse_check_pnp_id(const char *id, const char * const ids[])
+static bool psmouse_check_pnp_id(const char *p, const char * const ids[])
{
- int i;
+ const char * const *id;
+ size_t len;
- for (i = 0; ids[i]; i++)
- if (!strcasecmp(id, ids[i]))
+ for (id = ids; *id; id++) {
+ len = strlen(*id);
+ if (!strncasecmp(p, *id, len) && (p[len] == ' ' || p[len] == '\0'))
return true;
+ }
return false;
}
@@ -512,28 +511,26 @@ static bool psmouse_check_pnp_id(const char *id, const char * const ids[])
bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[])
{
struct serio *serio = psmouse->ps2dev.serio;
- char *p, *fw_id_copy, *save_ptr;
- bool found = false;
+ const char *p = serio->firmware_id;
- if (strncmp(serio->firmware_id, "PNP: ", 5))
+ if (!strstarts(p, "PNP: "))
return false;
- fw_id_copy = kstrndup(&serio->firmware_id[5],
- sizeof(serio->firmware_id) - 5,
- GFP_KERNEL);
- if (!fw_id_copy)
- return false;
+ p += 5;
+ while (*p) {
+ p = skip_spaces(p);
+ if (!*p)
+ break;
- save_ptr = fw_id_copy;
- while ((p = strsep(&fw_id_copy, " ")) != NULL) {
- if (psmouse_check_pnp_id(p, ids)) {
- found = true;
+ if (psmouse_check_pnp_id(p, ids))
+ return true;
+
+ p = strchr(p, ' ');
+ if (!p)
break;
- }
}
- kfree(save_ptr);
- return found;
+ return false;
}
/*
@@ -837,14 +834,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 +1142,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,16 +1313,16 @@ 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;
int i;
- mutex_lock(&psmouse_mutex);
+ guard(mutex)(&psmouse_mutex);
if (psmouse->state != PSMOUSE_RESYNCING)
- goto out;
+ return;
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = psmouse_from_serio(serio->parent);
@@ -1418,8 +1400,6 @@ static void psmouse_resync(struct work_struct *work)
if (parent)
psmouse_activate(parent);
- out:
- mutex_unlock(&psmouse_mutex);
}
/*
@@ -1430,7 +1410,7 @@ static void psmouse_cleanup(struct serio *serio)
struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
- mutex_lock(&psmouse_mutex);
+ guard(mutex)(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = psmouse_from_serio(serio->parent);
@@ -1466,8 +1446,6 @@ static void psmouse_cleanup(struct serio *serio)
psmouse_activate(parent);
}
-
- mutex_unlock(&psmouse_mutex);
}
/*
@@ -1478,20 +1456,20 @@ static void psmouse_disconnect(struct serio *serio)
struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
- mutex_lock(&psmouse_mutex);
+ disable_work_sync(&psmouse->resync_work);
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ guard(mutex)(&psmouse_mutex);
- /* make sure we don't have a resync in progress */
- mutex_unlock(&psmouse_mutex);
- flush_workqueue(kpsmoused_wq);
- mutex_lock(&psmouse_mutex);
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
+ scoped_guard(serio_pause_rx, serio)
+ psmouse->protocol_handler = NULL;
+
if (psmouse->disconnect)
psmouse->disconnect(psmouse);
@@ -1510,8 +1488,6 @@ static void psmouse_disconnect(struct serio *serio)
if (parent)
psmouse_activate(parent);
-
- mutex_unlock(&psmouse_mutex);
}
static int psmouse_switch_protocol(struct psmouse *psmouse,
@@ -1591,14 +1567,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_deactivate(parent);
}
- psmouse = kzalloc(sizeof(*psmouse), GFP_KERNEL);
+ psmouse = kzalloc_obj(*psmouse);
input_dev = input_allocate_device();
if (!psmouse || !input_dev)
goto err_free;
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);
@@ -1680,14 +1656,12 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
enum psmouse_type type;
int rc = -1;
- mutex_lock(&psmouse_mutex);
+ lockdep_assert_held(&psmouse_mutex);
if (fast_reconnect) {
reconnect_handler = psmouse->fast_reconnect;
- if (!reconnect_handler) {
- rc = -ENOENT;
- goto out_unlock;
- }
+ if (!reconnect_handler)
+ return -ENOENT;
} else {
reconnect_handler = psmouse->reconnect;
}
@@ -1739,18 +1713,20 @@ out:
if (parent)
psmouse_activate(parent);
-out_unlock:
- mutex_unlock(&psmouse_mutex);
return rc;
}
static int psmouse_reconnect(struct serio *serio)
{
+ guard(mutex)(&psmouse_mutex);
+
return __psmouse_reconnect(serio, false);
}
static int psmouse_fast_reconnect(struct serio *serio)
{
+ guard(mutex)(&psmouse_mutex);
+
return __psmouse_reconnect(serio, true);
}
@@ -2035,27 +2011,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 +2030,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-smbus.c b/drivers/input/mouse/psmouse-smbus.c
index 15bd49ccad22..98d9c860d2db 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -154,7 +154,7 @@ static void psmouse_smbus_schedule_remove(struct i2c_client *client)
{
struct psmouse_smbus_removal_work *rwork;
- rwork = kzalloc(sizeof(*rwork), GFP_KERNEL);
+ rwork = kzalloc_obj(*rwork);
if (rwork) {
INIT_WORK(&rwork->work, psmouse_smbus_remove_i2c_device);
rwork->client = client;
@@ -232,7 +232,7 @@ int psmouse_smbus_init(struct psmouse *psmouse,
struct psmouse_smbus_dev *smbdev;
int error;
- smbdev = kzalloc(sizeof(*smbdev), GFP_KERNEL);
+ smbdev = kzalloc_obj(*smbdev);
if (!smbdev)
return -ENOMEM;
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/sentelic.c b/drivers/input/mouse/sentelic.c
index 44b136fc29aa..cda6febe3faf 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -1028,7 +1028,7 @@ int fsp_init(struct psmouse *psmouse)
"Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n",
ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver);
- psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ psmouse->private = priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 218c8432a13b..c334a488700f 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -231,7 +231,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
unsigned char c = serio->id.extra;
int err = -ENOMEM;
- sermouse = kzalloc(sizeof(*sermouse), GFP_KERNEL);
+ sermouse = kzalloc_obj(*sermouse);
input_dev = input_allocate_device();
if (!sermouse || !input_dev)
goto fail1;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index c5c88a75a019..a8ce89d41faa 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -164,6 +164,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS
static const char * const smbus_pnp_ids[] = {
/* all of the topbuttonpad_pnp_ids are valid, we just add some extras */
+ "DLL0597", /* Dell Inspiron 3521 */
"DLL060d", /* Dell Precision M3800 */
"LEN0048", /* X1 Carbon 3 */
"LEN0046", /* X250 */
@@ -190,6 +191,7 @@ static const char * const smbus_pnp_ids[] = {
"LEN2044", /* L470 */
"LEN2054", /* E480 */
"LEN2055", /* E580 */
+ "LEN2058", /* E490 */
"LEN2068", /* T14 Gen 1 */
"SYN1221", /* TUXEDO InfinityBook Pro 14 v5 */
"SYN3003", /* HP EliteBook 850 G1 */
@@ -741,7 +743,7 @@ static void synaptics_pt_create(struct psmouse *psmouse)
{
struct serio *serio;
- serio = kzalloc(sizeof(*serio), GFP_KERNEL);
+ serio = kzalloc_obj(*serio);
if (!serio) {
psmouse_err(psmouse,
"not enough memory for pass-through port\n");
@@ -1597,7 +1599,7 @@ static int synaptics_init_ps2(struct psmouse *psmouse,
synaptics_apply_quirks(psmouse, info);
- psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ psmouse->private = priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
@@ -1836,6 +1838,14 @@ static int synaptics_setup_intertouch(struct psmouse *psmouse,
return -ENXIO;
}
+
+ /* Disable intertouch on known-broken board revisions */
+ if (info->board_id == 2722) {
+ psmouse_info(psmouse,
+ "Disabling intertouch for board id %u\n",
+ info->board_id);
+ return -ENXIO;
+ }
}
psmouse_info(psmouse, "Trying to set up SMBus access\n");
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 6f3d5c33b807..66e833974c6d 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -261,7 +261,7 @@ static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val)
if (error)
return error;
- return error;
+ return 0;
}
static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg)
@@ -607,7 +607,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
synaptics_i2c_resume);
static const struct i2c_device_id synaptics_i2c_id_table[] = {
- { "synaptics_i2c" },
+ { .name = "synaptics_i2c" },
{ }
};
MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table);
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c
index 75e45f3ae675..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,11 +288,11 @@ 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(sizeof(*synusb), GFP_KERNEL);
+ synusb = kzalloc_obj(*synusb);
input_dev = input_allocate_device();
if (!synusb || !input_dev) {
error = -ENOMEM;
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 5f6643b69a2c..3bd8fdf56cd3 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -5,6 +5,7 @@
* Trademarks are the property of their respective owners.
*/
+#include <linux/array_size.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/serio.h>
@@ -12,6 +13,7 @@
#include <linux/input.h>
#include <linux/libps2.h>
#include <linux/proc_fs.h>
+#include <linux/string.h>
#include <linux/uaccess.h>
#include "psmouse.h"
#include "trackpoint.h"
@@ -393,6 +395,44 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
return 0;
}
+/* List of known incapable device PNP IDs */
+static const char * const dt_incompatible_devices[] = {
+ "LEN0304",
+ "LEN0306",
+ "LEN0317",
+ "LEN031A",
+ "LEN031B",
+ "LEN031C",
+ "LEN031D",
+};
+
+/*
+ * Checks if it's a doubletap capable device.
+ * The PNP ID format is "PNP: LEN030d PNP0f13".
+ */
+static bool trackpoint_is_dt_capable(const char *pnp_id)
+{
+ size_t i;
+
+ if (!pnp_id)
+ return false;
+
+ /* Must start with "PNP: LEN03" */
+ if (!strstarts(pnp_id, "PNP: LEN03"))
+ return false;
+
+ /* Ensure enough length before comparing */
+ if (strlen(pnp_id) < 12)
+ return false;
+
+ /* Check deny-list */
+ for (i = 0; i < ARRAY_SIZE(dt_incompatible_devices); i++) {
+ if (!strncmp(pnp_id + 5, dt_incompatible_devices[i], 7))
+ return false;
+ }
+ return true;
+}
+
int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -409,7 +449,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
if (!set_properties)
return 0;
- tp = kzalloc(sizeof(*tp), GFP_KERNEL);
+ tp = kzalloc_obj(*tp);
if (!tp)
return -ENOMEM;
@@ -470,6 +510,12 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
psmouse->vendor, firmware_id,
(button_info & 0xf0) >> 4, button_info & 0x0f);
+ if (trackpoint_is_dt_capable(ps2dev->serio->firmware_id)) {
+ error = trackpoint_write(ps2dev, TP_DOUBLETAP, TP_DOUBLETAP_ENABLE);
+ if (error)
+ psmouse_warn(psmouse, "Failed to enable doubletap: %d\n", error);
+ }
+
return 0;
}
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index eb5412904fe0..3e03cdb39449 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -69,6 +69,8 @@
/* (how hard it is to drag */
/* with Z-axis pressed) */
+#define TP_DOUBLETAP 0x58 /* TrackPoint doubletap register */
+
#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
/* to trigger dragging */
@@ -110,6 +112,9 @@
external device will be forced to 1 */
#define TP_MASK_EXT_TAG 0x04
+/* Doubletap register values */
+#define TP_DOUBLETAP_ENABLE 0xFF /* Enable value */
+#define TP_DOUBLETAP_DISABLE 0xFE /* Disable value */
/* Power on Self Test Results */
#define TP_POR_SUCCESS 0x3B
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index fb1d986a6895..aaecdd3d50b6 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -409,7 +409,7 @@ int vmmouse_init(struct psmouse *psmouse)
if (error)
return error;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
abs_dev = input_allocate_device();
if (!priv || !abs_dev) {
error = -ENOMEM;
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index 707cd28f4ba6..042a17fe81db 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -456,7 +456,7 @@ static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int err = -ENOMEM;
- mouse = kzalloc(sizeof(*mouse), GFP_KERNEL);
+ mouse = kzalloc_obj(*mouse);
input_dev = input_allocate_device();
if (!mouse || !input_dev)
goto fail1;