Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 238ccbb0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
  ...
parents c5113e3d 1d9f2626
Loading
Loading
Loading
Loading
+2 −9
Original line number Diff line number Diff line
@@ -5,9 +5,6 @@
#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
#define __ASM_ARCH_EP93XX_KEYPAD_H

#define MAX_MATRIX_KEY_ROWS		(8)
#define MAX_MATRIX_KEY_COLS		(8)

/* flags for the ep93xx_keypad driver */
#define EP93XX_KEYPAD_DISABLE_3_KEY	(1<<0)	/* disable 3-key reset */
#define EP93XX_KEYPAD_DIAG_MODE		(1<<1)	/* diagnostic mode */
@@ -18,8 +15,6 @@

/**
 * struct ep93xx_keypad_platform_data - platform specific device structure
 * @matrix_key_rows:		number of rows in the keypad matrix
 * @matrix_key_cols:		number of columns in the keypad matrix
 * @matrix_key_map:		array of keycodes defining the keypad matrix
 * @matrix_key_map_size:	ARRAY_SIZE(matrix_key_map)
 * @debounce:			debounce start count; terminal count is 0xff
@@ -27,8 +22,6 @@
 * @flags:			see above
 */
struct ep93xx_keypad_platform_data {
	unsigned int	matrix_key_rows;
	unsigned int	matrix_key_cols;
	unsigned int	*matrix_key_map;
	int		matrix_key_map_size;
	unsigned int	debounce;
@@ -36,7 +29,7 @@ struct ep93xx_keypad_platform_data {
	unsigned int	flags;
};

/* macro for creating the matrix_key_map table */
#define KEY(row, col, val)	(((row) << 28) | ((col) << 24) | (val))
#define EP93XX_MATRIX_ROWS		(8)
#define EP93XX_MATRIX_COLS		(8)

#endif	/* __ASM_ARCH_EP93XX_KEYPAD_H */
+7 −3
Original line number Diff line number Diff line
@@ -233,7 +233,8 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
}

/*
 * Making beeps and bells.
 * Making beeps and bells. Note that we prefer beeps to bells, but when
 * shutting the sound off we do both.
 */

static int kd_sound_helper(struct input_handle *handle, void *data)
@@ -242,9 +243,12 @@ static int kd_sound_helper(struct input_handle *handle, void *data)
	struct input_dev *dev = handle->dev;

	if (test_bit(EV_SND, dev->evbit)) {
		if (test_bit(SND_TONE, dev->sndbit))
		if (test_bit(SND_TONE, dev->sndbit)) {
			input_inject_event(handle, EV_SND, SND_TONE, *hz);
		if (test_bit(SND_BELL, handle->dev->sndbit))
			if (*hz)
				return 0;
		}
		if (test_bit(SND_BELL, dev->sndbit))
			input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
	}

+8 −2
Original line number Diff line number Diff line
@@ -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)
{
+49 −101
Original line number Diff line number Diff line
@@ -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);

+238 −27
Original line number Diff line number Diff line
@@ -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,7 +72,15 @@ 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
@@ -78,11 +89,71 @@ static const struct alps_model_info alps_model_data[] = {
 * 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);
Loading