diff options
Diffstat (limited to 'drivers/input/mouse')
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; |
