diff options
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/alps.c | 1 | ||||
-rw-r--r-- | drivers/input/mouse/appletouch.c | 24 | ||||
-rw-r--r-- | drivers/input/mouse/bcm5974.c | 108 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.c | 48 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.h | 5 | ||||
-rw-r--r-- | drivers/input/mouse/lifebook.c | 6 | ||||
-rw-r--r-- | drivers/input/mouse/maplemouse.c | 43 |
7 files changed, 173 insertions, 62 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index cbedf957cc5..daecc75c72e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -37,6 +37,7 @@ #define ALPS_FW_BK_2 0x40 static const struct alps_model_info alps_model_data[] = { + { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 454b96112f0..e0140fdc02a 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -255,15 +255,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output"); */ static int atp_geyser_init(struct usb_device *udev) { - char data[8]; + char *data; int size; int i; + int ret; + + data = kmalloc(8, GFP_KERNEL); + if (!data) { + err("Out of memory"); + return -ENOMEM; + } size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ATP_GEYSER_MODE_READ_REQUEST_ID, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, ATP_GEYSER_MODE_REQUEST_VALUE, - ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); + ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); if (size != 8) { dprintk("atp_geyser_init: read error\n"); @@ -271,7 +278,8 @@ static int atp_geyser_init(struct usb_device *udev) dprintk("appletouch[%d]: %d\n", i, data[i]); err("Failed to read mode from device."); - return -EIO; + ret = -EIO; + goto out_free; } /* Apply the mode switch */ @@ -281,7 +289,7 @@ static int atp_geyser_init(struct usb_device *udev) ATP_GEYSER_MODE_WRITE_REQUEST_ID, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, ATP_GEYSER_MODE_REQUEST_VALUE, - ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); + ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); if (size != 8) { dprintk("atp_geyser_init: write error\n"); @@ -289,9 +297,13 @@ static int atp_geyser_init(struct usb_device *udev) dprintk("appletouch[%d]: %d\n", i, data[i]); err("Failed to request geyser raw mode"); - return -EIO; + ret = -EIO; + goto out_free; } - return 0; + ret = 0; +out_free: + kfree(data); + return ret; } /* diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2998a6ac9ae..2d8fc0bf692 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -51,6 +51,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 +/* Macbook5,1 (unibody), aka wellspring3 */ +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -72,6 +76,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), + /* Macbook5,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), /* Terminating entry */ {} }; @@ -96,14 +104,23 @@ struct bt_data { u8 rel_y; /* relative y coordinate */ }; -/* trackpad header structure */ -struct tp_header { - u8 unknown1[16]; /* constants, timers, etc */ - u8 fingers; /* number of fingers on trackpad */ - u8 unknown2[9]; /* constants, timers, etc */ +/* trackpad header types */ +enum tp_type { + TYPE1, /* plain trackpad */ + TYPE2 /* button integrated in trackpad */ }; -/* trackpad finger structure */ +/* trackpad finger data offsets, le16-aligned */ +#define FINGER_TYPE1 (13 * sizeof(__le16)) +#define FINGER_TYPE2 (15 * sizeof(__le16)) + +/* trackpad button data offsets */ +#define BUTTON_TYPE2 15 + +/* list of device capability bits */ +#define HAS_INTEGRATED_BUTTON 1 + +/* trackpad finger structure, le16-aligned */ struct tp_finger { __le16 origin; /* zero when switching track finger */ __le16 abs_x; /* absolute x coodinate */ @@ -117,13 +134,11 @@ struct tp_finger { __le16 force_minor; /* trackpad force, minor axis? */ __le16 unused[3]; /* zeros */ __le16 multi; /* one finger: varies, more fingers: constant */ -}; +} __attribute__((packed,aligned(2))); -/* trackpad data structure, empirically at least ten fingers */ -struct tp_data { - struct tp_header header; - struct tp_finger finger[16]; -}; +/* trackpad finger data size, empirically at least ten fingers */ +#define SIZEOF_FINGER sizeof(struct tp_finger) +#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) /* device-specific parameters */ struct bcm5974_param { @@ -136,9 +151,12 @@ struct bcm5974_param { /* device-specific configuration */ struct bcm5974_config { int ansi, iso, jis; /* the product id of this device */ + int caps; /* device capability bitmask */ int bt_ep; /* the endpoint of the button interface */ int bt_datalen; /* data length of the button interface */ int tp_ep; /* the endpoint of the trackpad interface */ + enum tp_type tp_type; /* type of trackpad interface */ + int tp_offset; /* offset to trackpad finger data */ int tp_datalen; /* data length of the trackpad interface */ struct bcm5974_param p; /* finger pressure limits */ struct bcm5974_param w; /* finger width limits */ @@ -158,7 +176,7 @@ struct bcm5974 { struct urb *bt_urb; /* button usb request block */ struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ - struct tp_data *tp_data; /* trackpad transferred data */ + u8 *tp_data; /* trackpad transferred data */ int fingers; /* number of fingers on trackpad */ }; @@ -183,8 +201,9 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, + 0, 0x84, sizeof(struct bt_data), - 0x81, sizeof(struct tp_data), + 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, @@ -194,13 +213,26 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, + 0, 0x84, sizeof(struct bt_data), - 0x81, sizeof(struct tp_data), + 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING3_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, + { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } + }, {} }; @@ -257,6 +289,7 @@ static void setup_events_to_report(struct input_dev *input_dev, __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit); } @@ -266,6 +299,11 @@ static int report_bt_state(struct bcm5974 *dev, int size) if (size != sizeof(struct bt_data)) return -EIO; + dprintk(7, + "bcm5974: button data: %x %x %x %x\n", + dev->bt_data->unknown1, dev->bt_data->button, + dev->bt_data->rel_x, dev->bt_data->rel_y); + input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); input_sync(dev->input); @@ -276,29 +314,37 @@ static int report_bt_state(struct bcm5974 *dev, int size) static int report_tp_state(struct bcm5974 *dev, int size) { const struct bcm5974_config *c = &dev->cfg; - const struct tp_finger *f = dev->tp_data->finger; + const struct tp_finger *f; struct input_dev *input = dev->input; - const int fingers = (size - 26) / 28; - int raw_p, raw_w, raw_x, raw_y; - int ptest = 0, origin = 0, nmin = 0, nmax = 0; + int raw_p, raw_w, raw_x, raw_y, raw_n; + int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; - if (size < 26 || (size - 26) % 28 != 0) + if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) return -EIO; + /* finger data, le16-aligned */ + f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); + raw_n = (size - c->tp_offset) / SIZEOF_FINGER; + /* always track the first finger; when detached, start over */ - if (fingers) { + if (raw_n) { raw_p = raw2int(f->force_major); raw_w = raw2int(f->size_major); raw_x = raw2int(f->abs_x); raw_y = raw2int(f->abs_y); dprintk(9, - "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", - raw_p, raw_w, raw_x, raw_y); + "bcm5974: " + "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", + raw_p, raw_w, raw_x, raw_y, raw_n); ptest = int2bound(&c->p, raw_p); origin = raw2int(f->origin); + + /* set the integrated button if applicable */ + if (c->tp_type == TYPE2) + ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); } /* while tracking finger still valid, count all fingers */ @@ -307,12 +353,13 @@ static int report_tp_state(struct bcm5974 *dev, int size) abs_w = int2bound(&c->w, raw_w); abs_x = int2bound(&c->x, raw_x - c->x.devmin); abs_y = int2bound(&c->y, c->y.devmax - raw_y); - for (; f != dev->tp_data->finger + fingers; f++) { + while (raw_n--) { ptest = int2bound(&c->p, raw2int(f->force_major)); if (ptest > PRESSURE_LOW) nmax++; if (ptest > PRESSURE_HIGH) nmin++; + f++; } } @@ -324,7 +371,8 @@ static int report_tp_state(struct bcm5974 *dev, int size) input_report_key(input, BTN_TOUCH, dev->fingers > 0); input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); + input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3); + input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3); input_report_abs(input, ABS_PRESSURE, abs_p); input_report_abs(input, ABS_TOOL_WIDTH, abs_w); @@ -335,11 +383,15 @@ static int report_tp_state(struct bcm5974 *dev, int size) dprintk(8, "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " - "nmin: %d nmax: %d n: %d\n", - abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); + "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w, + abs_x, abs_y, nmin, nmax, dev->fingers, ibt); } + /* type 2 reports button events via ibt only */ + if (c->tp_type == TYPE2) + input_report_key(input, BTN_LEFT, ibt); + input_sync(input); return 0; @@ -649,6 +701,8 @@ static int bcm5974_probe(struct usb_interface *iface, input_dev->name = "bcm5974"; input_dev->phys = dev->phys; usb_to_input_id(dev->udev, &input_dev->id); + /* report driver capabilities via the version field */ + input_dev->id.version = cfg->caps; input_dev->dev.parent = &iface->dev; input_set_drvdata(input_dev, dev); diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 6ab0eb1ada1..4bc78892ba9 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1,7 +1,7 @@ /* - * Elantech Touchpad driver (v5) + * Elantech Touchpad driver (v6) * - * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> + * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -178,6 +178,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; int fingers; + static int old_fingers; if (etd->fw_version_maj == 0x01) { /* byte 0: D U p1 p2 1 p3 R L @@ -190,6 +191,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) fingers = (packet[0] & 0xc0) >> 6; } + if (etd->jumpy_cursor) { + /* Discard packets that are likely to have bogus coordinates */ + if (fingers > old_fingers) { + elantech_debug("elantech.c: discarding packet\n"); + goto discard_packet_v1; + } + } + input_report_key(dev, BTN_TOUCH, fingers != 0); /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 @@ -216,6 +225,9 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) } input_sync(dev); + + discard_packet_v1: + old_fingers = fingers; } /* @@ -363,9 +375,14 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) rc = -1; break; } + } + + if (rc == 0) { /* - * Read back reg 0x10. The touchpad is probably initalising - * and not ready until we read back the value we just wrote. + * Read back reg 0x10. For hardware version 1 we must make + * sure the absolute mode bit is set. For hardware version 2 + * the touchpad is probably initalising and not ready until + * we read back the value we just wrote. */ do { rc = elantech_read_reg(psmouse, 0x10, &val); @@ -373,12 +390,18 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) break; tries--; elantech_debug("elantech.c: retrying read (%d).\n", - tries); + tries); msleep(ETP_READ_BACK_DELAY); } while (tries > 0); - if (rc) + + if (rc) { pr_err("elantech.c: failed to read back register 0x10.\n"); - break; + } else if (etd->hw_version == 1 && + !(val & ETP_R10_ABSOLUTE_MODE)) { + pr_err("elantech.c: touchpad refuses " + "to switch to absolute mode.\n"); + rc = -1; + } } if (rc) @@ -662,6 +685,17 @@ int elantech_init(struct psmouse *psmouse) param[0], param[1], param[2]); etd->capabilities = param[0]; + /* + * This firmware seems to suffer from misreporting coordinates when + * a touch action starts causing the mouse cursor or scrolled page + * to jump. Enable a workaround. + */ + if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { + pr_info("elantech.c: firmware version 2.34 detected, " + "enabling jumpy cursor workaround\n"); + etd->jumpy_cursor = 1; + } + if (elantech_set_absolute_mode(psmouse)) { pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); goto init_fail; diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index bee282b540b..ed848cc8081 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -1,7 +1,7 @@ /* - * Elantech Touchpad driver (v5) + * Elantech Touchpad driver (v6) * - * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> + * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -104,6 +104,7 @@ struct elantech_data { unsigned char fw_version_min; unsigned char hw_version; unsigned char paritycheck; + unsigned char jumpy_cursor; unsigned char parity[256]; }; diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index df81b0aaa9f..15ac3205ac0 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -61,6 +61,12 @@ static const struct dmi_system_id lifebook_dmi_table[] = { }, }, { + .ident = "Lifebook B-2130", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), + }, + }, + { .ident = "Lifebook B213x/B2150", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index d196abfb68b..5f278176eb9 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c @@ -2,8 +2,8 @@ * SEGA Dreamcast mouse driver * Based on drivers/usb/usbmouse.c * - * Copyright Yaegashi Takeshi, 2001 - * Adrian McMenamin, 2008 + * Copyright (c) Yaegashi Takeshi, 2001 + * Copyright (c) Adrian McMenamin, 2008 - 2009 */ #include <linux/kernel.h> @@ -29,7 +29,7 @@ static void dc_mouse_callback(struct mapleq *mq) struct maple_device *mapledev = mq->dev; struct dc_mouse *mse = maple_get_drvdata(mapledev); struct input_dev *dev = mse->dev; - unsigned char *res = mq->recvbuf; + unsigned char *res = mq->recvbuf->buf; buttons = ~res[8]; relx = *(unsigned short *)(res + 12) - 512; @@ -47,7 +47,7 @@ static void dc_mouse_callback(struct mapleq *mq) static int dc_mouse_open(struct input_dev *dev) { - struct dc_mouse *mse = dev->dev.platform_data; + struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev)); maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, MAPLE_FUNC_MOUSE); @@ -57,29 +57,33 @@ static int dc_mouse_open(struct input_dev *dev) static void dc_mouse_close(struct input_dev *dev) { - struct dc_mouse *mse = dev->dev.platform_data; + struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev)); maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, MAPLE_FUNC_MOUSE); } - +/* allow the mouse to be used */ static int __devinit probe_maple_mouse(struct device *dev) { struct maple_device *mdev = to_maple_dev(dev); struct maple_driver *mdrv = to_maple_driver(dev->driver); + int error; struct input_dev *input_dev; struct dc_mouse *mse; - int error; mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); - input_dev = input_allocate_device(); - - if (!mse || !input_dev) { + if (!mse) { error = -ENOMEM; goto fail; } + input_dev = input_allocate_device(); + if (!input_dev) { + error = -ENOMEM; + goto fail_nomem; + } + mse->dev = input_dev; mse->mdev = mdev; @@ -89,25 +93,24 @@ static int __devinit probe_maple_mouse(struct device *dev) BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | BIT_MASK(REL_WHEEL); - input_dev->name = mdev->product_name; - input_dev->id.bustype = BUS_HOST; input_dev->open = dc_mouse_open; input_dev->close = dc_mouse_close; + input_dev->name = mdev->product_name; + input_dev->id.bustype = BUS_HOST; + error = input_register_device(input_dev); + if (error) + goto fail_register; mdev->driver = mdrv; maple_set_drvdata(mdev, mse); - error = input_register_device(input_dev); - if (error) - goto fail; - - return 0; + return error; -fail: +fail_register: input_free_device(input_dev); - maple_set_drvdata(mdev, NULL); +fail_nomem: kfree(mse); - mdev->driver = NULL; +fail: return error; } |