diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:31:44 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:31:44 -0800 |
commit | 238ccbb050a243e935bb3fc679c2e4bbff7004aa (patch) | |
tree | 3381b895861f625b1524acfd32d4a90eb79108bd /drivers/input | |
parent | c5113e3d66d7c7140fe854c7638a27eb3a23fd7d (diff) | |
parent | 1d9f26262aef6d63ff65eba0fd5f1583f342b69b (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (22 commits)
Input: ALPS - add interleaved protocol support (Dell E6x00 series)
Input: keyboard - don't override beep with a bell
Input: altera_ps2 - fix test of unsigned in altera_ps2_probe()
Input: add mc13783 touchscreen driver
Input: ep93xx_keypad - update driver to new core support
Input: wacom - separate pen from express keys on Graphire
Input: wacom - add defines for data packet report IDs
Input: wacom - add support for new LCD tablets
Input: wacom - add defines for packet lengths of various devices
Input: wacom - ensure the device is initialized properly upon resume
Input: at32psif - do not sleep in atomic context
Input: i8042 - add Gigabyte M1022M to the noloop list
Input: i8042 - allow installing platform filters for incoming data
Input: i8042 - fix locking in interrupt routine
Input: ALPS - do not set REL_X/REL_Y capabilities on the touchpad
Input: document use of input_event() function
Input: sa1111ps2 - annotate probe() and remove() methods
Input: ambakmi - annotate probe() and remove() methods
Input: gscps2 - fix probe() and remove() annotations
Input: altera_ps2 - add annotations to probe and remove methods
...
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/input.c | 10 | ||||
-rw-r--r-- | drivers/input/keyboard/ep93xx_keypad.c | 150 | ||||
-rw-r--r-- | drivers/input/mouse/alps.c | 265 | ||||
-rw-r--r-- | drivers/input/mouse/alps.h | 1 | ||||
-rw-r--r-- | drivers/input/serio/altera_ps2.c | 15 | ||||
-rw-r--r-- | drivers/input/serio/ambakmi.c | 9 | ||||
-rw-r--r-- | drivers/input/serio/at32psif.c | 3 | ||||
-rw-r--r-- | drivers/input/serio/gscps2.c | 6 | ||||
-rw-r--r-- | drivers/input/serio/hil_mlc.c | 8 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 8 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 88 | ||||
-rw-r--r-- | drivers/input/serio/sa1111ps2.c | 10 | ||||
-rw-r--r-- | drivers/input/tablet/wacom.h | 11 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 231 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 368 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.h | 29 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 12 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/mc13783_ts.c | 258 |
19 files changed, 1111 insertions, 372 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 5c16001959cc..ab060710688f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -296,9 +296,15 @@ static void input_handle_event(struct input_dev *dev, * @value: value of the event * * This function should be used by drivers implementing various input - * devices. See also input_inject_event(). + * devices to report input events. See also input_inject_event(). + * + * NOTE: input_event() may be safely used right after input device was + * allocated with input_allocate_device(), even before it is registered + * with input_register_device(), but the event will not reach any of the + * input handlers. Such early invocation of input_event() may be used + * to 'seed' initial state of a switch or initial position of absolute + * axis, etc. */ - void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 181d30e3018e..e45740429f7e 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -22,11 +22,11 @@ #include <linux/platform_device.h> #include <linux/interrupt.h> -#include <linux/input.h> #include <linux/clk.h> +#include <linux/io.h> +#include <linux/input/matrix_keypad.h> #include <mach/hardware.h> -#include <mach/gpio.h> #include <mach/ep93xx_keypad.h> /* @@ -60,38 +60,37 @@ #define KEY_REG_KEY1_MASK (0x0000003f) #define KEY_REG_KEY1_SHIFT (0) -#define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) -#define keypad_writel(v, off) __raw_writel((v), keypad->mmio_base + (off)) - -#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) +#define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS) struct ep93xx_keypad { struct ep93xx_keypad_platform_data *pdata; - - struct clk *clk; struct input_dev *input_dev; + struct clk *clk; + void __iomem *mmio_base; - int irq; - int enabled; + unsigned int matrix_keycodes[EP93XX_MATRIX_SIZE]; int key1; int key2; - unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; + int irq; + + bool enabled; }; static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) { struct ep93xx_keypad_platform_data *pdata = keypad->pdata; struct input_dev *input_dev = keypad->input_dev; + unsigned int *key; int i; - for (i = 0; i < pdata->matrix_key_map_size; i++) { - unsigned int key = pdata->matrix_key_map[i]; - int row = (key >> 28) & 0xf; - int col = (key >> 24) & 0xf; - int code = key & 0xffffff; + key = &pdata->matrix_key_map[0]; + for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { + int row = KEY_ROW(*key); + int col = KEY_COL(*key); + int code = KEY_VAL(*key); keypad->matrix_keycodes[(row << 3) + col] = code; __set_bit(code, input_dev->keybit); @@ -102,9 +101,11 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) { struct ep93xx_keypad *keypad = dev_id; struct input_dev *input_dev = keypad->input_dev; - unsigned int status = keypad_readl(KEY_REG); + unsigned int status; int keycode, key1, key2; + status = __raw_readl(keypad->mmio_base + KEY_REG); + keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; key1 = keypad->matrix_keycodes[keycode]; @@ -152,7 +153,10 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) struct ep93xx_keypad_platform_data *pdata = keypad->pdata; unsigned int val = 0; - clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV); + if (pdata->flags & EP93XX_KEYPAD_KDIV) + clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4); + else + clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16); if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) val |= KEY_INIT_DIS3KY; @@ -167,7 +171,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); - keypad_writel(val, KEY_INIT); + __raw_writel(val, keypad->mmio_base + KEY_INIT); } static int ep93xx_keypad_open(struct input_dev *pdev) @@ -177,7 +181,7 @@ static int ep93xx_keypad_open(struct input_dev *pdev) if (!keypad->enabled) { ep93xx_keypad_config(keypad); clk_enable(keypad->clk); - keypad->enabled = 1; + keypad->enabled = true; } return 0; @@ -189,7 +193,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev) if (keypad->enabled) { clk_disable(keypad->clk); - keypad->enabled = 0; + keypad->enabled = false; } } @@ -211,7 +215,7 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev, if (keypad->enabled) { clk_disable(keypad->clk); - keypad->enabled = 0; + keypad->enabled = false; } mutex_unlock(&input_dev->mutex); @@ -236,7 +240,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) if (!keypad->enabled) { ep93xx_keypad_config(keypad); clk_enable(keypad->clk); - keypad->enabled = 1; + keypad->enabled = true; } } @@ -252,88 +256,56 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) { struct ep93xx_keypad *keypad; - struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data; struct input_dev *input_dev; struct resource *res; - int irq, err, i, gpio; - - if (!pdata || - !pdata->matrix_key_rows || - pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS || - !pdata->matrix_key_cols || - pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) { - dev_err(&pdev->dev, "invalid or missing platform data\n"); - return -EINVAL; - } + int err; keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); - if (!keypad) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); + if (!keypad) return -ENOMEM; - } - keypad->pdata = pdata; + keypad->pdata = pdev->dev.platform_data; + if (!keypad->pdata) { + err = -EINVAL; + goto failed_free; + } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get keypad irq\n"); + keypad->irq = platform_get_irq(pdev, 0); + if (!keypad->irq) { err = -ENXIO; goto failed_free; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); err = -ENXIO; goto failed_free; } res = request_mem_region(res->start, resource_size(res), pdev->name); if (!res) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); err = -EBUSY; goto failed_free; } keypad->mmio_base = ioremap(res->start, resource_size(res)); if (keypad->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); err = -ENXIO; goto failed_free_mem; } - /* Request the needed GPIO's */ - gpio = EP93XX_GPIO_LINE_ROW0; - for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) { - err = gpio_request(gpio, pdev->name); - if (err) { - dev_err(&pdev->dev, "failed to request gpio-%d\n", - gpio); - goto failed_free_rows; - } - } - - gpio = EP93XX_GPIO_LINE_COL0; - for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) { - err = gpio_request(gpio, pdev->name); - if (err) { - dev_err(&pdev->dev, "failed to request gpio-%d\n", - gpio); - goto failed_free_cols; - } - } + err = ep93xx_keypad_acquire_gpio(pdev); + if (err) + goto failed_free_io; - keypad->clk = clk_get(&pdev->dev, "key_clk"); + keypad->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) { - dev_err(&pdev->dev, "failed to get keypad clock\n"); err = PTR_ERR(keypad->clk); - goto failed_free_io; + goto failed_free_gpio; } - /* Create and register the input driver */ input_dev = input_allocate_device(); if (!input_dev) { - dev_err(&pdev->dev, "failed to allocate input device\n"); err = -ENOMEM; goto failed_put_clk; } @@ -358,44 +330,29 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) ep93xx_keypad_build_keycode(keypad); platform_set_drvdata(pdev, keypad); - err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED, - pdev->name, keypad); - if (err) { - dev_err(&pdev->dev, "failed to request IRQ\n"); + err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, + IRQF_DISABLED, pdev->name, keypad); + if (err) goto failed_free_dev; - } - - keypad->irq = irq; - /* Register the input device */ err = input_register_device(input_dev); - if (err) { - dev_err(&pdev->dev, "failed to register input device\n"); + if (err) goto failed_free_irq; - } device_init_wakeup(&pdev->dev, 1); return 0; failed_free_irq: - free_irq(irq, pdev); + free_irq(keypad->irq, pdev); platform_set_drvdata(pdev, NULL); failed_free_dev: input_free_device(input_dev); failed_put_clk: clk_put(keypad->clk); +failed_free_gpio: + ep93xx_keypad_release_gpio(pdev); failed_free_io: - i = keypad->pdata->matrix_key_cols - 1; - gpio = EP93XX_GPIO_LINE_COL0 + i; -failed_free_cols: - for ( ; i >= 0; i--, gpio--) - gpio_free(gpio); - i = keypad->pdata->matrix_key_rows - 1; - gpio = EP93XX_GPIO_LINE_ROW0 + i; -failed_free_rows: - for ( ; i >= 0; i--, gpio--) - gpio_free(gpio); iounmap(keypad->mmio_base); failed_free_mem: release_mem_region(res->start, resource_size(res)); @@ -408,7 +365,6 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) { struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; - int i, gpio; free_irq(keypad->irq, pdev); @@ -420,15 +376,7 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) input_unregister_device(keypad->input_dev); - i = keypad->pdata->matrix_key_cols - 1; - gpio = EP93XX_GPIO_LINE_COL0 + i; - for ( ; i >= 0; i--, gpio--) - gpio_free(gpio); - - i = keypad->pdata->matrix_key_rows - 1; - gpio = EP93XX_GPIO_LINE_ROW0 + i; - for ( ; i >= 0; i--, gpio--) - gpio_free(gpio); + ep93xx_keypad_release_gpio(pdev); iounmap(keypad->mmio_base); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a3f492a50850..f93c2c0daf1f 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -5,6 +5,7 @@ * 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> + * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> * * ALPS detection, tap switching and status querying info is taken from * tpconfig utility (by C. Scott Ananian and Bruce Kall). @@ -28,7 +29,6 @@ #define dbg(format, arg...) do {} while (0) #endif - #define ALPS_OLDPROTO 0x01 /* old style input */ #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ #define ALPS_PASS 0x04 /* device has a pass-through port */ @@ -37,7 +37,8 @@ #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ - +#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with + 6-byte ALPS packet */ static const struct alps_model_info alps_model_data[] = { { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ @@ -58,7 +59,9 @@ static const struct alps_model_info alps_model_data[] = { { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ + { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ }; @@ -69,20 +72,88 @@ static const struct alps_model_info alps_model_data[] = { */ /* - * ALPS abolute Mode - new format + * PS/2 packet format + * + * byte 0: 0 0 YSGN XSGN 1 M R L + * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 + * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 + * + * Note that the device never signals overflow condition. + * + * ALPS absolute Mode - new format * * byte 0: 1 ? ? ? 1 ? ? ? * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 - * byte 2: 0 x10 x9 x8 x7 ? fin ges + * byte 2: 0 x10 x9 x8 x7 ? fin ges * byte 3: 0 y9 y8 y7 1 M R L * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 * + * Dualpoint device -- interleaved packet format + * + * byte 0: 1 1 0 0 1 1 1 1 + * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 + * byte 2: 0 x10 x9 x8 x7 0 fin ges + * byte 3: 0 0 YSGN XSGN 1 1 1 1 + * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 + * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 + * byte 6: 0 y9 y8 y7 1 m r l + * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 + * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 + * + * CAPITALS = stick, miniscules = touchpad + * * ?'s can have different meanings on different models, * such as wheel rotation, extra buttons, stick buttons * on a dualpoint, etc. */ +static bool alps_is_valid_first_byte(const struct alps_model_info *model, + unsigned char data) +{ + return (data & model->mask0) == model->byte0; +} + +static void alps_report_buttons(struct psmouse *psmouse, + struct input_dev *dev1, struct input_dev *dev2, + int left, int right, int middle) +{ + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; + + if (model->flags & ALPS_PS2_INTERLEAVED) { + struct input_dev *dev; + + /* + * If shared button has already been reported on the + * other device (dev2) then this event should be also + * sent through that device. + */ + dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_LEFT, left); + + dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_RIGHT, right); + + dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_MIDDLE, middle); + + /* + * Sync the _other_ device now, we'll do the first + * device later once we report the rest of the events. + */ + input_sync(dev2); + } else { + /* + * For devices with non-interleaved packets we know what + * device buttons belong to so we can simply report them. + */ + input_report_key(dev1, BTN_LEFT, left); + input_report_key(dev1, BTN_RIGHT, right); + input_report_key(dev1, BTN_MIDDLE, middle); + } +} + static void alps_process_packet(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -93,18 +164,6 @@ static void alps_process_packet(struct psmouse *psmouse) int x, y, z, ges, fin, left, right, middle; int back = 0, forward = 0; - if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ - input_report_key(dev2, BTN_LEFT, packet[0] & 1); - input_report_key(dev2, BTN_RIGHT, packet[0] & 2); - input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); - input_report_rel(dev2, REL_X, - packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); - input_report_rel(dev2, REL_Y, - packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); - input_sync(dev2); - return; - } - if (model->flags & ALPS_OLDPROTO) { left = packet[2] & 0x10; right = packet[2] & 0x08; @@ -140,18 +199,13 @@ static void alps_process_packet(struct psmouse *psmouse) input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); - input_report_key(dev2, BTN_LEFT, left); - input_report_key(dev2, BTN_RIGHT, right); - input_report_key(dev2, BTN_MIDDLE, middle); + alps_report_buttons(psmouse, dev2, dev, left, right, middle); - input_sync(dev); input_sync(dev2); return; } - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_MIDDLE, middle); + alps_report_buttons(psmouse, dev, dev2, left, right, middle); /* Convert hardware tap to a reasonable Z value */ if (ges && !fin) @@ -202,25 +256,168 @@ static void alps_process_packet(struct psmouse *psmouse) input_sync(dev); } +static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +{ + struct alps_data *priv = psmouse->private; + struct input_dev *dev2 = priv->dev2; + + if (report_buttons) + alps_report_buttons(psmouse, dev2, psmouse->dev, + packet[0] & 1, packet[0] & 2, packet[0] & 4); + + input_report_rel(dev2, REL_X, + packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); + input_report_rel(dev2, REL_Y, + packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); + + input_sync(dev2); +} + +static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) +{ + struct alps_data *priv = psmouse->private; + + if (psmouse->pktcnt < 6) + return PSMOUSE_GOOD_DATA; + + if (psmouse->pktcnt == 6) { + /* + * Start a timer to flush the packet if it ends up last + * 6-byte packet in the stream. Timer needs to fire + * psmouse core times out itself. 20 ms should be enough + * to decide if we are getting more data or not. + */ + mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); + return PSMOUSE_GOOD_DATA; + } + + del_timer(&priv->timer); + + if (psmouse->packet[6] & 0x80) { + + /* + * Highest bit is set - that means we either had + * complete ALPS packet and this is start of the + * next packet or we got garbage. + */ + + if (((psmouse->packet[3] | + psmouse->packet[4] | + psmouse->packet[5]) & 0x80) || + (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { + dbg("refusing packet %x %x %x %x " + "(suspected interleaved ps/2)\n", + psmouse->packet[3], psmouse->packet[4], + psmouse->packet[5], psmouse->packet[6]); + return PSMOUSE_BAD_DATA; + } + + alps_process_packet(psmouse); + + /* Continue with the next packet */ + psmouse->packet[0] = psmouse->packet[6]; + psmouse->pktcnt = 1; + + } else { + + /* + * High bit is 0 - that means that we indeed got a PS/2 + * packet in the middle of ALPS packet. + * + * There is also possibility that we got 6-byte ALPS + * packet followed by 3-byte packet from trackpoint. We + * can not distinguish between these 2 scenarios but + * becase the latter is unlikely to happen in course of + * normal operation (user would need to press all + * buttons on the pad and start moving trackpoint + * without touching the pad surface) we assume former. + * Even if we are wrong the wost thing that would happen + * the cursor would jump but we should not get protocol + * desynchronization. + */ + + alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], + false); + + /* + * Continue with the standard ALPS protocol handling, + * but make sure we won't process it as an interleaved + * packet again, which may happen if all buttons are + * pressed. To avoid this let's reset the 4th bit which + * is normally 1. + */ + psmouse->packet[3] = psmouse->packet[6] & 0xf7; + psmouse->pktcnt = 4; + } + + return PSMOUSE_GOOD_DATA; +} + +static void alps_flush_packet(unsigned long data) +{ + struct psmouse *psmouse = (struct psmouse *)data; + + serio_pause_rx(psmouse->ps2dev.serio); + + if (psmouse->pktcnt == 6) { + + /* + * We did not any more data in reasonable amount of time. + * Validate the last 3 bytes and process as a standard + * ALPS packet. + */ + if ((psmouse->packet[3] | + psmouse->packet[4] | + psmouse->packet[5]) & 0x80) { + dbg("refusing packet %x %x %x " + "(suspected interleaved ps/2)\n", + psmouse->packet[3], psmouse->packet[4], + psmouse->packet[5]); + } else { + alps_process_packet(psmouse); + } + psmouse->pktcnt = 0; + } + + serio_continue_rx(psmouse->ps2dev.serio); +} + static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ if (psmouse->pktcnt == 3) { - alps_process_packet(psmouse); + alps_report_bare_ps2_packet(psmouse, psmouse->packet, + true); return PSMOUSE_FULL_PACKET; } return PSMOUSE_GOOD_DATA; } - if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) + /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ + + if ((model->flags & ALPS_PS2_INTERLEAVED) && + psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { + return alps_handle_interleaved_ps2(psmouse); + } + + if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { + dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", + psmouse->packet[0], model->mask0, model->byte0); return PSMOUSE_BAD_DATA; + } /* Bytes 2 - 6 should have 0 in the highest bit */ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + dbg("refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); return PSMOUSE_BAD_DATA; + } if (psmouse->pktcnt == 6) { alps_process_packet(psmouse); @@ -459,6 +656,7 @@ static void alps_disconnect(struct psmouse *psmouse) struct alps_data *priv = psmouse->private; psmouse_reset(psmouse); + del_timer_sync(&priv->timer); input_unregister_device(priv->dev2); kfree(priv); } @@ -476,6 +674,8 @@ int alps_init(struct psmouse *psmouse) goto init_fail; priv->dev2 = dev2; + setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); + psmouse->private = priv; model = alps_get_model(psmouse, &version); @@ -487,6 +687,17 @@ int alps_init(struct psmouse *psmouse) if (alps_hw_init(psmouse)) goto init_fail; + /* + * Undo part of setup done for us by psmouse core since touchpad + * is not a relative device. + */ + __clear_bit(EV_REL, dev1->evbit); + __clear_bit(REL_X, dev1->relbit); + __clear_bit(REL_Y, dev1->relbit); + + /* + * Now set up our capabilities. + */ dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index bc87936fee1a..904ed8b3c8be 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -23,6 +23,7 @@ struct alps_data { char phys[32]; /* Phys */ const struct alps_model_info *i;/* Info */ int prev_fin; /* Finger bit from previous packet */ + struct timer_list timer; }; #ifdef CONFIG_MOUSE_PS2_ALPS diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index f479ea50919f..320b7ca48bf8 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -79,11 +79,11 @@ static void altera_ps2_close(struct serio *io) /* * Add one device to this driver. */ -static int altera_ps2_probe(struct platform_device *pdev) +static int __devinit altera_ps2_probe(struct platform_device *pdev) { struct ps2if *ps2if; struct serio *serio; - int error; + int error, irq; ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL); @@ -108,11 +108,13 @@ static int altera_ps2_probe(struct platform_device *pdev) goto err_free_mem; } - ps2if->irq = platform_get_irq(pdev, 0); - if (ps2if->irq < 0) { + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { error = -ENXIO; goto err_free_mem; } + ps2if->irq = irq; if (!request_mem_region(ps2if->iomem_res->start, resource_size(ps2if->iomem_res), pdev->name)) { @@ -155,7 +157,7 @@ static int altera_ps2_probe(struct platform_device *pdev) /* * Remove one device from this driver. */ -static int altera_ps2_remove(struct platform_device *pdev) +static int __devexit altera_ps2_remove(struct platform_device *pdev) { struct ps2if *ps2if = platform_get_drvdata(pdev); @@ -175,9 +177,10 @@ static int altera_ps2_remove(struct platform_device *pdev) */ static struct platform_driver altera_ps2_driver = { .probe = altera_ps2_probe, - .remove = altera_ps2_remove, + .remove = __devexit_p(altera_ps2_remove), .driver = { .name = DRV_NAME, + .owner = THIS_MODULE, }, }; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 89b394183a75..92563a681d65 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io) clk_disable(kmi->clk); } -static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) { struct amba_kmi_port *kmi; struct serio *io; @@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) io->port_data = kmi; io->dev.parent = &dev->dev; - kmi->io = io; + kmi->io = io; kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!kmi->base) { ret = -ENOMEM; @@ -162,7 +162,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) return ret; } -static int amba_kmi_remove(struct amba_device *dev) +static int __devexit amba_kmi_remove(struct amba_device *dev) { struct amba_kmi_port *kmi = amba_get_drvdata(dev); @@ -197,10 +197,11 @@ static struct amba_id amba_kmi_idtable[] = { static struct amba_driver ambakmi_driver = { .drv = { .name = "kmi-pl050", + .owner = THIS_MODULE, }, .id_table = amba_kmi_idtable, .probe = amba_kmi_probe, - .remove = amba_kmi_remove, + .remove = __devexit_p(amba_kmi_remove), .resume = amba_kmi_resume, }; diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index a6fb7a3dcc46..b54452a8c771 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c @@ -137,7 +137,7 @@ static int psif_write(struct serio *io, unsigned char val) spin_lock_irqsave(&psif->lock, flags); while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) - msleep(10); + udelay(50); if (timeout >= 0) { psif_writel(psif, THR, val); @@ -352,6 +352,7 @@ static struct platform_driver psif_driver = { .remove = __exit_p(psif_remove), .driver = { .name = "atmel_psif", + .owner = THIS_MODULE, }, .suspend = psif_suspend, .resume = psif_resume, diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index bd0f92d9f40f..06addfa7cc47 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -6,7 +6,7 @@ * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> * * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c - * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> + * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> @@ -326,7 +326,7 @@ static void gscps2_close(struct serio *port) * @return: success/error report */ -static int __init gscps2_probe(struct parisc_device *dev) +static int __devinit gscps2_probe(struct parisc_device *dev) { struct gscps2port *ps2port; struct serio *serio; @@ -443,7 +443,7 @@ static struct parisc_driver parisc_ps2_driver = { .name = "gsc_ps2", .id_table = gscps2_device_tbl, .probe = gscps2_probe, - .remove = gscps2_remove, + .remove = __devexit_p(gscps2_remove), }; static int __init gscps2_init(void) diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 7ba9f2b2c041..6cd03ebaf5fb 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/driv |