Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: make EVIOCGSND return meaningful data
  Input: ressurect EVIOCGREP and EVIOCSREP
  Input: psmouse - fix new device detection logic
  Input: move input_device_id to mod_devicetable.h
  Input: allow using several chords for braille
  Input: allow passing NULL to input_free_device()
  Input: spitzkbd - fix the reversed Address and Calender keys
  Input: ads7846 - improve filtering for thumb press accuracy
  Input: ads7846 - report 0 pressure value along with pen up event
  Input: ads7846 - handle IRQs that were latched during disabled IRQs
  Input: ads7846 - miscellaneous fixes
  Input: ads7846 - use msleep() instead of udelay() in suspend
  Input: ads7846 - debouncing and rudimentary sample filtering
  Input: ads7846 - power down ADC a bit later
  Input: ads7846 - add pen_down sysfs attribute
  Input: wistron - add support for Fujitsu N3510
  Input: wistron - add signature for Amilo M7400
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 935670a..5755b7e 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -860,9 +860,32 @@
 }
 
 /* by default, 300ms interval for combination release */
-static long brl_timeout = 300;
-MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)");
-module_param(brl_timeout, long, 0644);
+static unsigned brl_timeout = 300;
+MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
+module_param(brl_timeout, uint, 0644);
+
+static unsigned brl_nbchords = 1;
+MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
+module_param(brl_nbchords, uint, 0644);
+
+static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag, struct pt_regs *regs)
+{
+	static unsigned long chords;
+	static unsigned committed;
+
+	if (!brl_nbchords)
+		k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag, regs);
+	else {
+		committed |= pattern;
+		chords++;
+		if (chords == brl_nbchords) {
+			k_unicode(vc, BRL_UC_ROW | committed, up_flag, regs);
+			chords = 0;
+			committed = 0;
+		}
+	}
+}
+
 static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
 {
 	static unsigned pressed,committing;
@@ -882,11 +905,6 @@
 	if (value > 8)
 		return;
 
-	if (brl_timeout < 0) {
-		k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs);
-		return;
-	}
-
 	if (up_flag) {
 		if (brl_timeout) {
 			if (!committing ||
@@ -897,13 +915,13 @@
 			pressed &= ~(1 << (value - 1));
 			if (!pressed) {
 				if (committing) {
-					k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+					k_brlcommit(vc, committing, 0, regs);
 					committing = 0;
 				}
 			}
 		} else {
 			if (committing) {
-				k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+				k_brlcommit(vc, committing, 0, regs);
 				committing = 0;
 			}
 			pressed &= ~(1 << (value - 1));
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a34e3d9..ba325f1 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -403,6 +403,27 @@
 		case EVIOCGID:
 			if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
 				return -EFAULT;
+			return 0;
+
+		case EVIOCGREP:
+			if (!test_bit(EV_REP, dev->evbit))
+				return -ENOSYS;
+			if (put_user(dev->rep[REP_DELAY], ip))
+				return -EFAULT;
+			if (put_user(dev->rep[REP_PERIOD], ip + 1))
+				return -EFAULT;
+			return 0;
+
+		case EVIOCSREP:
+			if (!test_bit(EV_REP, dev->evbit))
+				return -ENOSYS;
+			if (get_user(u, ip))
+				return -EFAULT;
+			if (get_user(v, ip + 1))
+				return -EFAULT;
+
+			input_event(dev, EV_REP, REP_DELAY, u);
+			input_event(dev, EV_REP, REP_PERIOD, v);
 
 			return 0;
 
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a935abe..3038c26 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -155,6 +155,9 @@
 			if (code > SND_MAX || !test_bit(code, dev->sndbit))
 				return;
 
+			if (!!test_bit(code, dev->snd) != !!value)
+				change_bit(code, dev->snd);
+
 			if (dev->event) dev->event(dev, type, code, value);
 
 			break;
@@ -286,19 +289,19 @@
 	for (; id->flags || id->driver_info; id++) {
 
 		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
-			if (id->id.bustype != dev->id.bustype)
+			if (id->bustype != dev->id.bustype)
 				continue;
 
 		if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
-			if (id->id.vendor != dev->id.vendor)
+			if (id->vendor != dev->id.vendor)
 				continue;
 
 		if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
-			if (id->id.product != dev->id.product)
+			if (id->product != dev->id.product)
 				continue;
 
 		if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
-			if (id->id.version != dev->id.version)
+			if (id->version != dev->id.version)
 				continue;
 
 		MATCH_BIT(evbit,  EV_MAX);
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index bc61cf8..1d238a9 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -53,8 +53,8 @@
 	KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0,  /* 1-16 */
 	0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
 	KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0,                                 /* 33-48 */
-	SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,         /* 49-64 */
-	SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0,	  /* 65-80 */
+	SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,         /* 49-64 */
+	SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0,	  /* 65-80 */
 	SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0,      /* 81-96 */
 	KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0  /* 97-112 */
 };
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 4b415d9b..36cd2e0 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -273,6 +273,18 @@
 	{ KE_END,  0 }
 };
 
+static struct key_entry keymap_fujitsu_n3510[] = {
+	{ KE_KEY, 0x11, KEY_PROG1 },
+	{ KE_KEY, 0x12, KEY_PROG2 },
+	{ KE_KEY, 0x36, KEY_WWW },
+	{ KE_KEY, 0x31, KEY_MAIL },
+	{ KE_KEY, 0x71, KEY_STOPCD },
+	{ KE_KEY, 0x72, KEY_PLAYPAUSE },
+	{ KE_KEY, 0x74, KEY_REWIND },
+	{ KE_KEY, 0x78, KEY_FORWARD },
+	{ KE_END, 0 }
+};
+
 static struct key_entry keymap_wistron_ms2141[] = {
 	{ KE_KEY,  0x11, KEY_PROG1 },
 	{ KE_KEY,  0x12, KEY_PROG2 },
@@ -323,6 +335,24 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Fujitsu-Siemens Amilo M7400",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M        "),
+		},
+		.driver_data = keymap_fs_amilo_pro_v2000
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Fujitsu N3510",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
+		},
+		.driver_data = keymap_fujitsu_n3510
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Acer Aspire 1500",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 32d70ed..136321a 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -302,8 +302,10 @@
  * Check if this is a new device announcement (0xAA 0x00)
  */
 	if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
-		if (psmouse->pktcnt == 1)
+		if (psmouse->pktcnt == 1) {
+			psmouse->last = jiffies;
 			goto out;
+		}
 
 		if (psmouse->packet[1] == PSMOUSE_RET_ID) {
 			__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 46d1fec..1494175 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -2,6 +2,8 @@
  * ADS7846 based touchscreen and sensor driver
  *
  * Copyright (c) 2005 David Brownell
+ * Copyright (c) 2006 Nokia Corporation
+ * Various changes: Imre Deak <imre.deak@nokia.com>
  *
  * Using code from:
  *  - corgi_ts.c
@@ -34,17 +36,25 @@
 
 
 /*
- * This code has been lightly tested on an ads7846.
+ * This code has been tested on an ads7846 / N770 device.
  * Support for ads7843 and ads7845 has only been stubbed in.
  *
- * Not yet done:  investigate the values reported.  Are x/y/pressure
- * event values sane enough for X11?  How accurate are the temperature
- * and voltage readings?  (System-specific calibration should support
+ * Not yet done:  How accurate are the temperature and voltage
+ * readings? (System-specific calibration should support
  * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
  *
+ * IRQ handling needs a workaround because of a shortcoming in handling
+ * edge triggered IRQs on some platforms like the OMAP1/2. These
+ * platforms don't handle the ARM lazy IRQ disabling properly, thus we
+ * have to maintain our own SW IRQ disabled status. This should be
+ * removed as soon as the affected platform's IRQ handling is fixed.
+ *
  * app note sbaa036 talks in more detail about accurate sampling...
  * that ought to help in situations like LCDs inducing noise (which
  * can also be helped by using synch signals) and more generally.
+ * This driver tries to utilize the measures described in the app
+ * note. The strength of filtering can be set in the board-* specific
+ * files.
  */
 
 #define	TS_POLL_PERIOD	msecs_to_jiffies(10)
@@ -61,6 +71,7 @@
 	__be16 x;
 	__be16 y;
 	__be16 z1, z2;
+	int    ignore;
 };
 
 struct ads7846 {
@@ -71,12 +82,23 @@
 	u16			model;
 	u16			vref_delay_usecs;
 	u16			x_plate_ohms;
+	u16			pressure_max;
 
-	u8			read_x, read_y, read_z1, read_z2;
+	u8			read_x, read_y, read_z1, read_z2, pwrdown;
+	u16			dummy;		/* for the pwrdown read */
 	struct ts_event		tc;
 
-	struct spi_transfer	xfer[8];
-	struct spi_message	msg;
+	struct spi_transfer	xfer[10];
+	struct spi_message	msg[5];
+	struct spi_message	*last_msg;
+	int			msg_idx;
+	int			read_cnt;
+	int			read_rep;
+	int			last_read;
+
+	u16			debounce_max;
+	u16			debounce_tol;
+	u16			debounce_rep;
 
 	spinlock_t		lock;
 	struct timer_list	timer;		/* P: lock */
@@ -84,6 +106,9 @@
 	unsigned		pending:1;	/* P: lock */
 // FIXME remove "irq_disabled"
 	unsigned		irq_disabled:1;	/* P: lock */
+	unsigned		disabled:1;
+
+	int			(*get_pendown_state)(void);
 };
 
 /* leave chip selected when we're done, for quicker re-select? */
@@ -125,7 +150,9 @@
 #define	READ_Y	(READ_12BIT_DFR(y)  | ADS_PD10_ADC_ON)
 #define	READ_Z1	(READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
 #define	READ_Z2	(READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
-#define	READ_X	(READ_12BIT_DFR(x)  | ADS_PD10_PDOWN)	/* LAST */
+
+#define	READ_X	(READ_12BIT_DFR(x)  | ADS_PD10_ADC_ON)
+#define	PWRDOWN	(READ_12BIT_DFR(y)  | ADS_PD10_PDOWN)	/* LAST */
 
 /* single-ended samples need to first power up reference voltage;
  * we leave both ADC and VREF powered
@@ -152,6 +179,15 @@
 	struct spi_transfer	xfer[6];
 };
 
+static void ads7846_enable(struct ads7846 *ts);
+static void ads7846_disable(struct ads7846 *ts);
+
+static int device_suspended(struct device *dev)
+{
+	struct ads7846 *ts = dev_get_drvdata(dev);
+	return dev->power.power_state.event != PM_EVENT_ON || ts->disabled;
+}
+
 static int ads7846_read12_ser(struct device *dev, unsigned command)
 {
 	struct spi_device	*spi = to_spi_device(dev);
@@ -164,7 +200,7 @@
 	if (!req)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&req->msg.transfers);
+	spi_message_init(&req->msg);
 
 	/* activate reference, so it has time to settle; */
 	req->ref_on = REF_ON;
@@ -204,8 +240,10 @@
 	for (i = 0; i < 6; i++)
 		spi_message_add_tail(&req->xfer[i], &req->msg);
 
+	ts->irq_disabled = 1;
 	disable_irq(spi->irq);
 	status = spi_sync(spi, &req->msg);
+	ts->irq_disabled = 0;
 	enable_irq(spi->irq);
 
 	if (req->msg.status)
@@ -233,6 +271,52 @@
 SHOW(vaux)
 SHOW(vbatt)
 
+static int is_pen_down(struct device *dev)
+{
+	struct ads7846		*ts = dev_get_drvdata(dev);
+
+	return ts->pendown;
+}
+
+static ssize_t ads7846_pen_down_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", is_pen_down(dev));
+}
+
+static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
+
+static ssize_t ads7846_disable_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct ads7846	*ts = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", ts->disabled);
+}
+
+static ssize_t ads7846_disable_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct ads7846 *ts = dev_get_drvdata(dev);
+	char *endp;
+	int i;
+
+	i = simple_strtoul(buf, &endp, 10);
+	spin_lock_irq(&ts->lock);
+
+	if (i)
+		ads7846_disable(ts);
+	else
+		ads7846_enable(ts);
+
+	spin_unlock_irq(&ts->lock);
+
+	return count;
+}
+
+static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
+
 /*--------------------------------------------------------------------------*/
 
 /*
@@ -264,7 +348,7 @@
 	if (x == MAX_12BIT)
 		x = 0;
 
-	if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+	if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
 		/* compute touch pressure resistance using equation #2 */
 		Rt = z2;
 		Rt -= z1;
@@ -275,6 +359,14 @@
 	} else
 		Rt = 0;
 
+	/* Sample found inconsistent by debouncing or pressure is beyond
+	* the maximum. Don't report it to user space, repeat at least
+	* once more the measurement */
+	if (ts->tc.ignore || Rt > ts->pressure_max) {
+		mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+		return;
+	}
+
 	/* NOTE:  "pendown" is inferred from pressure; we don't rely on
 	 * being able to check nPENIRQ status, or "friendly" trigger modes
 	 * (both-edges is much better than just-falling or low-level).
@@ -296,11 +388,13 @@
 	if (Rt) {
 		input_report_abs(input_dev, ABS_X, x);
 		input_report_abs(input_dev, ABS_Y, y);
-		input_report_abs(input_dev, ABS_PRESSURE, Rt);
 		sync = 1;
 	}
-	if (sync)
+
+	if (sync) {
+		input_report_abs(input_dev, ABS_PRESSURE, Rt);
 		input_sync(input_dev);
+	}
 
 #ifdef	VERBOSE
 	if (Rt || ts->pendown)
@@ -308,80 +402,138 @@
 			x, y, Rt, Rt ? "" : " UP");
 #endif
 
-	/* don't retrigger while we're suspended */
 	spin_lock_irqsave(&ts->lock, flags);
 
 	ts->pendown = (Rt != 0);
-	ts->pending = 0;
-
-	if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
-		if (ts->pendown)
-			mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
-		else if (ts->irq_disabled) {
-			ts->irq_disabled = 0;
-			enable_irq(ts->spi->irq);
-		}
-	}
+	mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
 
 	spin_unlock_irqrestore(&ts->lock, flags);
 }
 
+static void ads7846_debounce(void *ads)
+{
+	struct ads7846		*ts = ads;
+	struct spi_message	*m;
+	struct spi_transfer	*t;
+	int			val;
+	int			status;
+
+	m = &ts->msg[ts->msg_idx];
+	t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+	val = (*(u16 *)t->rx_buf) >> 3;
+	if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
+		/* Repeat it, if this was the first read or the read
+		 * wasn't consistent enough. */
+		if (ts->read_cnt < ts->debounce_max) {
+			ts->last_read = val;
+			ts->read_cnt++;
+		} else {
+			/* Maximum number of debouncing reached and still
+			 * not enough number of consistent readings. Abort
+			 * the whole sample, repeat it in the next sampling
+			 * period.
+			 */
+			ts->tc.ignore = 1;
+			ts->read_cnt = 0;
+			/* Last message will contain ads7846_rx() as the
+			 * completion function.
+			 */
+			m = ts->last_msg;
+		}
+		/* Start over collecting consistent readings. */
+		ts->read_rep = 0;
+	} else {
+		if (++ts->read_rep > ts->debounce_rep) {
+			/* Got a good reading for this coordinate,
+			 * go for the next one. */
+			ts->tc.ignore = 0;
+			ts->msg_idx++;
+			ts->read_cnt = 0;
+			ts->read_rep = 0;
+			m++;
+		} else
+			/* Read more values that are consistent. */
+			ts->read_cnt++;
+	}
+	status = spi_async(ts->spi, m);
+	if (status)
+		dev_err(&ts->spi->dev, "spi_async --> %d\n",
+				status);
+}
+
 static void ads7846_timer(unsigned long handle)
 {
 	struct ads7846	*ts = (void *)handle;
 	int		status = 0;
-	unsigned long	flags;
 
-	spin_lock_irqsave(&ts->lock, flags);
-	if (!ts->pending) {
-		ts->pending = 1;
-		if (!ts->irq_disabled) {
-			ts->irq_disabled = 1;
-			disable_irq(ts->spi->irq);
+	spin_lock_irq(&ts->lock);
+
+	if (unlikely(ts->msg_idx && !ts->pendown)) {
+		/* measurment cycle ended */
+		if (!device_suspended(&ts->spi->dev)) {
+			ts->irq_disabled = 0;
+			enable_irq(ts->spi->irq);
 		}
-		status = spi_async(ts->spi, &ts->msg);
+		ts->pending = 0;
+		ts->msg_idx = 0;
+	} else {
+		/* pen is still down, continue with the measurement */
+		ts->msg_idx = 0;
+		status = spi_async(ts->spi, &ts->msg[0]);
 		if (status)
-			dev_err(&ts->spi->dev, "spi_async --> %d\n",
-					status);
+			dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
 	}
-	spin_unlock_irqrestore(&ts->lock, flags);
+
+	spin_unlock_irq(&ts->lock);
 }
 
 static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
 {
-	ads7846_timer((unsigned long) handle);
+	struct ads7846 *ts = handle;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ts->lock, flags);
+	if (likely(ts->get_pendown_state())) {
+		if (!ts->irq_disabled) {
+			/* REVISIT irq logic for many ARM chips has cloned a
+			 * bug wherein disabling an irq in its handler won't
+			 * work;(it's disabled lazily, and too late to work.
+			 * until all their irq logic is fixed, we must shadow
+			 * that state here.
+			 */
+			ts->irq_disabled = 1;
+			disable_irq(ts->spi->irq);
+			ts->pending = 1;
+			mod_timer(&ts->timer, jiffies);
+		}
+	}
+	spin_unlock_irqrestore(&ts->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
 /*--------------------------------------------------------------------------*/
 
-static int
-ads7846_suspend(struct spi_device *spi, pm_message_t message)
+/* Must be called with ts->lock held */
+static void ads7846_disable(struct ads7846 *ts)
 {
-	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
-	unsigned long	flags;
+	if (ts->disabled)
+		return;
 
-	spin_lock_irqsave(&ts->lock, flags);
-
-	spi->dev.power.power_state = message;
+	ts->disabled = 1;
 
 	/* are we waiting for IRQ, or polling? */
-	if (!ts->pendown) {
-		if (!ts->irq_disabled) {
-			ts->irq_disabled = 1;
-			disable_irq(ts->spi->irq);
-		}
+	if (!ts->pending) {
+		ts->irq_disabled = 1;
+		disable_irq(ts->spi->irq);
 	} else {
-		/* polling; force a final SPI completion;
-		 * that will clean things up neatly
+		/* the timer will run at least once more, and
+		 * leave everything in a clean state, IRQ disabled
 		 */
-		if (!ts->pending)
-			mod_timer(&ts->timer, jiffies);
-
-		while (ts->pendown || ts->pending) {
-			spin_unlock_irqrestore(&ts->lock, flags);
-			udelay(10);
-			spin_lock_irqsave(&ts->lock, flags);
+		while (ts->pending) {
+			spin_unlock_irq(&ts->lock);
+			msleep(1);
+			spin_lock_irq(&ts->lock);
 		}
 	}
 
@@ -389,17 +541,45 @@
 	 * leave it that way after every request
 	 */
 
-	spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+/* Must be called with ts->lock held */
+static void ads7846_enable(struct ads7846 *ts)
+{
+	if (!ts->disabled)
+		return;
+
+	ts->disabled = 0;
+	ts->irq_disabled = 0;
+	enable_irq(ts->spi->irq);
+}
+
+static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
+{
+	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+	spin_lock_irq(&ts->lock);
+
+	spi->dev.power.power_state = message;
+	ads7846_disable(ts);
+
+	spin_unlock_irq(&ts->lock);
+
 	return 0;
+
 }
 
 static int ads7846_resume(struct spi_device *spi)
 {
 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-	ts->irq_disabled = 0;
-	enable_irq(ts->spi->irq);
+	spin_lock_irq(&ts->lock);
+
 	spi->dev.power.power_state = PMSG_ON;
+	ads7846_enable(ts);
+
+	spin_unlock_irq(&ts->lock);
+
 	return 0;
 }
 
@@ -408,6 +588,7 @@
 	struct ads7846			*ts;
 	struct input_dev		*input_dev;
 	struct ads7846_platform_data	*pdata = spi->dev.platform_data;
+	struct spi_message		*m;
 	struct spi_transfer		*x;
 	int				err;
 
@@ -428,6 +609,11 @@
 		return -EINVAL;
 	}
 
+	if (pdata->get_pendown_state == NULL) {
+		dev_dbg(&spi->dev, "no get_pendown_state function?\n");
+		return -EINVAL;
+	}
+
 	/* We'd set the wordsize to 12 bits ... except that some controllers
 	 * will then treat the 8 bit command words as 12 bits (and drop the
 	 * four MSBs of the 12 bit result).  Result: inputs must be shifted
@@ -451,9 +637,21 @@
 	ts->timer.data = (unsigned long) ts;
 	ts->timer.function = ads7846_timer;
 
+	spin_lock_init(&ts->lock);
+
 	ts->model = pdata->model ? : 7846;
 	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
 	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+	ts->pressure_max = pdata->pressure_max ? : ~0;
+	if (pdata->debounce_max) {
+		ts->debounce_max = pdata->debounce_max;
+		ts->debounce_tol = pdata->debounce_tol;
+		ts->debounce_rep = pdata->debounce_rep;
+		if (ts->debounce_rep > ts->debounce_max + 1)
+			ts->debounce_rep = ts->debounce_max - 1;
+	} else
+		ts->debounce_tol = ~0;
+	ts->get_pendown_state = pdata->get_pendown_state;
 
 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
 
@@ -477,60 +675,100 @@
 	/* set up the transfers to read touchscreen state; this assumes we
 	 * use formula #2 for pressure, not #3.
 	 */
-	INIT_LIST_HEAD(&ts->msg.transfers);
+	m = &ts->msg[0];
 	x = ts->xfer;
 
+	spi_message_init(m);
+
 	/* y- still on; turn on only y+ (and ADC) */
 	ts->read_y = READ_Y;
 	x->tx_buf = &ts->read_y;
 	x->len = 1;
-	spi_message_add_tail(x, &ts->msg);
+	spi_message_add_tail(x, m);
 
 	x++;
 	x->rx_buf = &ts->tc.y;
 	x->len = 2;
-	spi_message_add_tail(x, &ts->msg);
+	spi_message_add_tail(x, m);
 
-	/* turn y+ off, x- on; we'll use formula #2 */
-	if (ts->model == 7846) {
-		x++;
-		ts->read_z1 = READ_Z1;
-		x->tx_buf = &ts->read_z1;
-		x->len = 1;
-		spi_message_add_tail(x, &ts->msg);
+	m->complete = ads7846_debounce;
+	m->context = ts;
 
-		x++;
-		x->rx_buf = &ts->tc.z1;
-		x->len = 2;
-		spi_message_add_tail(x, &ts->msg);
-
-		x++;
-		ts->read_z2 = READ_Z2;
-		x->tx_buf = &ts->read_z2;
-		x->len = 1;
-		spi_message_add_tail(x, &ts->msg);
-
-		x++;
-		x->rx_buf = &ts->tc.z2;
-		x->len = 2;
-		spi_message_add_tail(x, &ts->msg);
-	}
+	m++;
+	spi_message_init(m);
 
 	/* turn y- off, x+ on, then leave in lowpower */
 	x++;
 	ts->read_x = READ_X;
 	x->tx_buf = &ts->read_x;
 	x->len = 1;
-	spi_message_add_tail(x, &ts->msg);
+	spi_message_add_tail(x, m);
 
 	x++;
 	x->rx_buf = &ts->tc.x;
 	x->len = 2;
-	CS_CHANGE(*x);
-	spi_message_add_tail(x, &ts->msg);
+	spi_message_add_tail(x, m);
 
-	ts->msg.complete = ads7846_rx;
-	ts->msg.context = ts;
+	m->complete = ads7846_debounce;
+	m->context = ts;
+
+	/* turn y+ off, x- on; we'll use formula #2 */
+	if (ts->model == 7846) {
+		m++;
+		spi_message_init(m);
+
+		x++;
+		ts->read_z1 = READ_Z1;
+		x->tx_buf = &ts->read_z1;
+		x->len = 1;
+		spi_message_add_tail(x, m);
+
+		x++;
+		x->rx_buf = &ts->tc.z1;
+		x->len = 2;
+		spi_message_add_tail(x, m);
+
+		m->complete = ads7846_debounce;
+		m->context = ts;
+
+		m++;
+		spi_message_init(m);
+
+		x++;
+		ts->read_z2 = READ_Z2;
+		x->tx_buf = &ts->read_z2;
+		x->len = 1;
+		spi_message_add_tail(x, m);
+
+		x++;
+		x->rx_buf = &ts->tc.z2;
+		x->len = 2;
+		spi_message_add_tail(x, m);
+
+		m->complete = ads7846_debounce;
+		m->context = ts;
+	}
+
+	/* power down */
+	m++;
+	spi_message_init(m);
+
+	x++;
+	ts->pwrdown = PWRDOWN;
+	x->tx_buf = &ts->pwrdown;
+	x->len = 1;
+	spi_message_add_tail(x, m);
+
+	x++;
+	x->rx_buf = &ts->dummy;
+	x->len = 2;
+	CS_CHANGE(*x);
+	spi_message_add_tail(x, m);
+
+	m->complete = ads7846_rx;
+	m->context = ts;
+
+	ts->last_msg = m;
 
 	if (request_irq(spi->irq, ads7846_irq,
 			SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
@@ -559,13 +797,27 @@
 		device_create_file(&spi->dev, &dev_attr_vbatt);
 	device_create_file(&spi->dev, &dev_attr_vaux);
 
+	device_create_file(&spi->dev, &dev_attr_pen_down);
+
+	device_create_file(&spi->dev, &dev_attr_disable);
+
 	err = input_register_device(input_dev);
 	if (err)
-		goto err_free_irq;
+		goto err_remove_attr;
 
 	return 0;
 
- err_free_irq:
+ err_remove_attr:
+	device_remove_file(&spi->dev, &dev_attr_disable);
+	device_remove_file(&spi->dev, &dev_attr_pen_down);
+	if (ts->model == 7846) {
+		device_remove_file(&spi->dev, &dev_attr_temp1);
+		device_remove_file(&spi->dev, &dev_attr_temp0);
+	}
+	if (ts->model != 7845)
+		device_remove_file(&spi->dev, &dev_attr_vbatt);
+	device_remove_file(&spi->dev, &dev_attr_vaux);
+
 	free_irq(spi->irq, ts);
  err_free_mem:
 	input_free_device(input_dev);
@@ -577,20 +829,24 @@
 {
 	struct ads7846		*ts = dev_get_drvdata(&spi->dev);
 
-	ads7846_suspend(spi, PMSG_SUSPEND);
-	free_irq(ts->spi->irq, ts);
-	if (ts->irq_disabled)
-		enable_irq(ts->spi->irq);
+	input_unregister_device(ts->input);
 
+	ads7846_suspend(spi, PMSG_SUSPEND);
+
+	device_remove_file(&spi->dev, &dev_attr_disable);
+	device_remove_file(&spi->dev, &dev_attr_pen_down);
 	if (ts->model == 7846) {
-		device_remove_file(&spi->dev, &dev_attr_temp0);
 		device_remove_file(&spi->dev, &dev_attr_temp1);
+		device_remove_file(&spi->dev, &dev_attr_temp0);
 	}
 	if (ts->model != 7845)
 		device_remove_file(&spi->dev, &dev_attr_vbatt);
 	device_remove_file(&spi->dev, &dev_attr_vaux);
 
-	input_unregister_device(ts->input);
+	free_irq(ts->spi->irq, ts);
+	/* suspend left the IRQ disabled */
+	enable_irq(ts->spi->irq);
+
 	kfree(ts);
 
 	dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/include/linux/input.h b/include/linux/input.h
index b0e612d..50e338d 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -12,8 +12,6 @@
 #ifdef __KERNEL__
 #include <linux/time.h>
 #include <linux/list.h>
-#include <linux/device.h>
-#include <linux/mod_devicetable.h>
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
@@ -58,6 +56,8 @@
 
 #define EVIOCGVERSION		_IOR('E', 0x01, int)			/* get driver version */
 #define EVIOCGID		_IOR('E', 0x02, struct input_id)	/* get device ID */
+#define EVIOCGREP		_IOR('E', 0x03, int[2])			/* get repeat settings */
+#define EVIOCSREP		_IOW('E', 0x03, int[2])			/* set repeat settings */
 #define EVIOCGKEYCODE		_IOR('E', 0x04, int[2])			/* get keycode */
 #define EVIOCSKEYCODE		_IOW('E', 0x04, int[2])			/* set keycode */
 
@@ -577,15 +577,15 @@
  * Switch events
  */
 
-#define SW_0		0x00
-#define SW_1		0x01
-#define SW_2		0x02
-#define SW_3		0x03
-#define SW_4		0x04
-#define SW_5		0x05
-#define SW_6		0x06
-#define SW_7		0x07
-#define SW_MAX		0x0f
+#define SW_0			0x00
+#define SW_1			0x01
+#define SW_2			0x02
+#define SW_3			0x03
+#define SW_4			0x04
+#define SW_5			0x05
+#define SW_6			0x06
+#define SW_7			0x07
+#define SW_MAX			0x0f
 
 /*
  * Misc events
@@ -805,52 +805,16 @@
 
 #define FF_MAX		0x7f
 
-struct input_device_id {
-
-	kernel_ulong_t flags;
-
-	struct input_id id;
-
-	kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1];
-	kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1];
-
-	kernel_ulong_t driver_info;
-};
-
-/*
- * Structure for hotplug & device<->driver matching.
- */
-
-#define INPUT_DEVICE_ID_MATCH_BUS	1
-#define INPUT_DEVICE_ID_MATCH_VENDOR	2
-#define INPUT_DEVICE_ID_MATCH_PRODUCT	4
-#define INPUT_DEVICE_ID_MATCH_VERSION	8
-
-#define INPUT_DEVICE_ID_MATCH_EVBIT	0x010
-#define INPUT_DEVICE_ID_MATCH_KEYBIT	0x020
-#define INPUT_DEVICE_ID_MATCH_RELBIT	0x040
-#define INPUT_DEVICE_ID_MATCH_ABSBIT	0x080
-#define INPUT_DEVICE_ID_MATCH_MSCIT	0x100
-#define INPUT_DEVICE_ID_MATCH_LEDBIT	0x200
-#define INPUT_DEVICE_ID_MATCH_SNDBIT	0x400
-#define INPUT_DEVICE_ID_MATCH_FFBIT	0x800
-#define INPUT_DEVICE_ID_MATCH_SWBIT	0x1000
-
 #ifdef __KERNEL__
 
 /*
  * In-kernel definitions.
  */
 
+#include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/timer.h>
+#include <linux/mod_devicetable.h>
 
 #define NBITS(x) (((x)/BITS_PER_LONG)+1)
 #define BIT(x)	(1UL<<((x)%BITS_PER_LONG))
@@ -951,9 +915,49 @@
 };
 #define to_input_dev(d) container_of(d, struct input_dev, cdev)
 
-#define INPUT_DEVICE_ID_MATCH_DEVICE\
+/*
+ * Verify that we are in sync with input_device_id mod_devicetable.h #defines
+ */
+
+#if EV_MAX != INPUT_DEVICE_ID_EV_MAX
+#error "EV_MAX and INPUT_DEVICE_ID_EV_MAX do not match"
+#endif
+
+#if KEY_MAX != INPUT_DEVICE_ID_KEY_MAX
+#error "KEY_MAX and INPUT_DEVICE_ID_KEY_MAX do not match"
+#endif
+
+#if REL_MAX != INPUT_DEVICE_ID_REL_MAX
+#error "REL_MAX and INPUT_DEVICE_ID_REL_MAX do not match"
+#endif
+
+#if ABS_MAX != INPUT_DEVICE_ID_ABS_MAX
+#error "ABS_MAX and INPUT_DEVICE_ID_ABS_MAX do not match"
+#endif
+
+#if MSC_MAX != INPUT_DEVICE_ID_MSC_MAX
+#error "MSC_MAX and INPUT_DEVICE_ID_MSC_MAX do not match"
+#endif
+
+#if LED_MAX != INPUT_DEVICE_ID_LED_MAX
+#error "LED_MAX and INPUT_DEVICE_ID_LED_MAX do not match"
+#endif
+
+#if SND_MAX != INPUT_DEVICE_ID_SND_MAX
+#error "SND_MAX and INPUT_DEVICE_ID_SND_MAX do not match"
+#endif
+
+#if FF_MAX != INPUT_DEVICE_ID_FF_MAX
+#error "FF_MAX and INPUT_DEVICE_ID_FF_MAX do not match"
+#endif
+
+#if SW_MAX != INPUT_DEVICE_ID_SW_MAX
+#error "SW_MAX and INPUT_DEVICE_ID_SW_MAX do not match"
+#endif
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE \
 	(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
-#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
 	(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
 
 struct input_handle;
@@ -1016,7 +1020,8 @@
 
 static inline void input_free_device(struct input_dev *dev)
 {
-	input_put_device(dev);
+	if (dev)
+		input_put_device(dev);
 }
 
 int input_register_device(struct input_dev *);
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 7b08c11..f697770 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -249,4 +249,52 @@
 	__u16 id;
 };
 
+/* Input */
+#define INPUT_DEVICE_ID_EV_MAX		0x1f
+#define INPUT_DEVICE_ID_KEY_MAX		0x1ff
+#define INPUT_DEVICE_ID_REL_MAX		0x0f
+#define INPUT_DEVICE_ID_ABS_MAX		0x3f
+#define INPUT_DEVICE_ID_MSC_MAX		0x07
+#define INPUT_DEVICE_ID_LED_MAX		0x0f
+#define INPUT_DEVICE_ID_SND_MAX		0x07
+#define INPUT_DEVICE_ID_FF_MAX		0x7f
+#define INPUT_DEVICE_ID_SW_MAX		0x0f
+
+#define INPUT_DEVICE_ID_MATCH_BUS	1
+#define INPUT_DEVICE_ID_MATCH_VENDOR	2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT	4
+#define INPUT_DEVICE_ID_MATCH_VERSION	8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT	0x0010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT	0x0020
+#define INPUT_DEVICE_ID_MATCH_RELBIT	0x0040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT	0x0080
+#define INPUT_DEVICE_ID_MATCH_MSCIT	0x0100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT	0x0200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT	0x0400
+#define INPUT_DEVICE_ID_MATCH_FFBIT	0x0800
+#define INPUT_DEVICE_ID_MATCH_SWBIT	0x1000
+
+struct input_device_id {
+
+	kernel_ulong_t flags;
+
+	__u16 bustype;
+	__u16 vendor;
+	__u16 product;
+	__u16 version;
+
+	kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
+	kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
+
+	kernel_ulong_t driver_info;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
index 72261e0..adb3dafd 100644
--- a/include/linux/spi/ads7846.h
+++ b/include/linux/spi/ads7846.h
@@ -14,5 +14,12 @@
 	u16	x_min, x_max;
 	u16	y_min, y_max;
 	u16	pressure_min, pressure_max;
+
+	u16	debounce_max;		/* max number of additional readings
+					 * per sample */
+	u16	debounce_tol;		/* tolerance used for filtering */
+	u16	debounce_rep;		/* additional consecutive good readings
+					 * required after the first two */
+	int	(*get_pendown_state)(void);
 };
 
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 84e2120..37f67c2 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -374,10 +374,10 @@
 		     kernel_ulong_t *arr, unsigned int min, unsigned int max)
 {
 	unsigned int i;
-	for (i = min; i < max; i++) {
-		if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
-			sprintf(alias+strlen(alias), "%X,*", i);
-	}
+
+	for (i = min; i < max; i++)
+		if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+			sprintf(alias + strlen(alias), "%X,*", i);
 }
 
 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
@@ -386,39 +386,37 @@
 {
 	sprintf(alias, "input:");
 
-	ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype);
-	ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor);
-	ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT,
-	    id->id.product);
-	ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION,
-	    id->id.version);
+	ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
+	ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
+	ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
+	ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
 
 	sprintf(alias + strlen(alias), "-e*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
 		do_input(alias, id->evbit, 0, EV_MAX);
 	sprintf(alias + strlen(alias), "k*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
 		do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
 	sprintf(alias + strlen(alias), "r*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
 		do_input(alias, id->relbit, 0, REL_MAX);
 	sprintf(alias + strlen(alias), "a*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
 		do_input(alias, id->absbit, 0, ABS_MAX);
 	sprintf(alias + strlen(alias), "m*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
 		do_input(alias, id->mscbit, 0, MSC_MAX);
 	sprintf(alias + strlen(alias), "l*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
 		do_input(alias, id->ledbit, 0, LED_MAX);
 	sprintf(alias + strlen(alias), "s*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
 		do_input(alias, id->sndbit, 0, SND_MAX);
 	sprintf(alias + strlen(alias), "f*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
 		do_input(alias, id->ffbit, 0, FF_MAX);
 	sprintf(alias + strlen(alias), "w*");
-	if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
+	if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
 		do_input(alias, id->swbit, 0, SW_MAX);
 	return 1;
 }