18491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff/*
28491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * USB Synaptics device driver
38491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
48491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *  Copyright (c) 2002 Rob Miller (rob@inpharmatica . co . uk)
58491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *  Copyright (c) 2003 Ron Lee (ron@debian.org)
68491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *	cPad driver for kernel 2.4
78491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
88491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *  Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de)
98491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *  Copyright (c) 2004 Ron Lee (ron@debian.org)
108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *	rewritten for kernel 2.6
118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *  cPad display character device part is not included. It can be found at
138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *  http://jan-steinhoff.de/linux/synaptics-usb.html
148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Bases on:	usb_skeleton.c v2.2 by Greg Kroah-Hartman
168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *		drivers/hid/usbhid/usbmouse.c by Vojtech Pavlik
178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *		drivers/input/mouse/synaptics.c by Peter Osterlund
188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * This program is free software; you can redistribute it and/or modify it
208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * under the terms of the GNU General Public License as published by the Free
218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Software Foundation; either version 2 of the License, or (at your option)
228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * any later version.
238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Trademarks are the property of their respective owners.
258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff */
268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff/*
288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * There are three different types of Synaptics USB devices: Touchpads,
298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * touchsticks (or trackpoints), and touchscreens. Touchpads are well supported
308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * by this driver, touchstick support has not been tested much yet, and
318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * touchscreens have not been tested at all.
328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *
338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * Up to three alternate settings are possible:
348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *	setting 0: one int endpoint for relative movement (used by usbhid.ko)
358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *	setting 1: one int endpoint for absolute finger position
368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *	setting 2 (cPad only): one int endpoint for absolute finger position and
378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff *		   two bulk endpoints for the display (in/out)
388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff * This driver uses setting 1.
398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff */
408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/kernel.h>
428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/init.h>
438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/slab.h>
448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/module.h>
458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/moduleparam.h>
468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/usb.h>
478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/input.h>
488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#include <linux/usb/input.h>
498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_VENDOR_ID_SYNAPTICS	0x06cb
518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_TP	0x0001	/* Synaptics USB TouchPad */
528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_INT_TP	0x0002	/* Integrated USB TouchPad */
538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_CPAD	0x0003	/* Synaptics cPad */
548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_TS	0x0006	/* Synaptics TouchScreen */
558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_STICK	0x0007	/* Synaptics USB Styk */
568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_WP	0x0008	/* Synaptics USB WheelPad */
578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_COMP_TP	0x0009	/* Composite USB TouchPad */
588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_WTP	0x0010	/* Wireless TouchPad */
598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_ID_SYNAPTICS_DPAD	0x0013	/* DisplayPad */
608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_TOUCHPAD			(1 << 0)
628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_STICK			(1 << 1)
638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_TOUCHSCREEN		(1 << 2)
648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_AUXDISPLAY		(1 << 3) /* For cPad */
658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_COMBO			(1 << 4) /* Composite device (TP + stick) */
668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_IO_ALWAYS		(1 << 5)
678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define USB_DEVICE_SYNAPTICS(prod, kind)		\
698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,		\
708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		   USB_DEVICE_ID_SYNAPTICS_##prod),	\
718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.driver_info = (kind),
728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define SYNUSB_RECV_SIZE	8
748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define XMIN_NOMINAL		1472
768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define XMAX_NOMINAL		5472
778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define YMIN_NOMINAL		1408
788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff#define YMAX_NOMINAL		4448
798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstruct synusb {
818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct usb_device *udev;
828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct usb_interface *intf;
838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct urb *urb;
848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned char *data;
858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	/* input device related data structures */
878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input;
888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	char name[128];
898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	char phys[64];
908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	/* characteristics of the device */
928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned long flags;
938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff};
948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_report_buttons(struct synusb *synusb)
968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04);
1008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01);
1018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02);
1028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
1038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_report_stick(struct synusb *synusb)
1058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
1068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
1078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int x, y;
1088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned int pressure;
1098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	pressure = synusb->data[6];
1118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7;
1128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7;
1138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (pressure > 0) {
1158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_rel(input_dev, REL_X, x);
1168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_rel(input_dev, REL_Y, -y);
1178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
1188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_abs(input_dev, ABS_PRESSURE, pressure);
1208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb_report_buttons(synusb);
1228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_sync(input_dev);
1248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
1258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_report_touchpad(struct synusb *synusb)
1278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
1288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
1298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned int num_fingers, tool_width;
1308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned int x, y;
1318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned int pressure, w;
1328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	pressure = synusb->data[6];
1348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	x = be16_to_cpup((__be16 *)&synusb->data[2]);
1358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	y = be16_to_cpup((__be16 *)&synusb->data[4]);
1368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	w = synusb->data[0] & 0x0f;
1378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (pressure > 0) {
1398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		num_fingers = 1;
1408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		tool_width = 5;
1418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		switch (w) {
1428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		case 0 ... 1:
1438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			num_fingers = 2 + w;
1448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			break;
1458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		case 2:	                /* pen, pretend its a finger */
1478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			break;
1488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		case 4 ... 15:
1508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			tool_width = w;
1518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			break;
1528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		}
1538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	} else {
1548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		num_fingers = 0;
1558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		tool_width = 0;
1568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
1578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	/*
1598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	 * Post events
1608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	 * BTN_TOUCH has to be first as mousedev relies on it when doing
1618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	 * absolute -> relative conversion
1628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	 */
1638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (pressure > 30)
1658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_key(input_dev, BTN_TOUCH, 1);
1668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (pressure < 25)
1678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_key(input_dev, BTN_TOUCH, 0);
1688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (num_fingers > 0) {
1708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_abs(input_dev, ABS_X, x);
1718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_abs(input_dev, ABS_Y,
1728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff				 YMAX_NOMINAL + YMIN_NOMINAL - y);
1738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
1748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_abs(input_dev, ABS_PRESSURE, pressure);
1768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width);
1778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1);
1798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
1808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
1818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb_report_buttons(synusb);
1838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_AUXDISPLAY)
1848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08);
1858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_sync(input_dev);
1878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
1888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_irq(struct urb *urb)
1908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
1918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = urb->context;
1928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int error;
1938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
1948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	/* Check our status in case we need to bail out early. */
1958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	switch (urb->status) {
1968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	case 0:
1978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		usb_mark_last_busy(synusb->udev);
1988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		break;
1998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	/* Device went away so don't keep trying to read from it. */
2018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	case -ECONNRESET:
2028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	case -ENOENT:
2038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	case -ESHUTDOWN:
2048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		return;
2058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	default:
2078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		goto resubmit;
2088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		break;
2098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
2108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_STICK)
2128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		synusb_report_stick(synusb);
2138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	else
2148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		synusb_report_touchpad(synusb);
2158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffresubmit:
2178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	error = usb_submit_urb(urb, GFP_ATOMIC);
2188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (error && error != -EPERM)
2198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		dev_err(&synusb->intf->dev,
2208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			"%s - usb_submit_urb failed with result: %d",
2218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			__func__, error);
2228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
2238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic struct usb_endpoint_descriptor *
2258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffsynusb_get_in_endpoint(struct usb_host_interface *iface)
2268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
2278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct usb_endpoint_descriptor *endpoint;
2298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int i;
2308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
2328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		endpoint = &iface->endpoint[i].desc;
2338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		if (usb_endpoint_is_int_in(endpoint)) {
2358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			/* we found our interrupt in endpoint */
2368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			return endpoint;
2378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		}
2388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
2398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return NULL;
2418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
2428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_open(struct input_dev *dev)
2448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
2458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = input_get_drvdata(dev);
2468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int retval;
2478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	retval = usb_autopm_get_interface(synusb->intf);
2498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (retval) {
2508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		dev_err(&synusb->intf->dev,
2518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			"%s - usb_autopm_get_interface failed, error: %d\n",
2528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			__func__, retval);
2538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		return retval;
2548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
2558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	retval = usb_submit_urb(synusb->urb, GFP_KERNEL);
2578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (retval) {
2588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		dev_err(&synusb->intf->dev,
2598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			"%s - usb_submit_urb failed, error: %d\n",
2608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			__func__, retval);
2618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		retval = -EIO;
2628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		goto out;
2638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
2648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->intf->needs_remote_wakeup = 1;
2668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffout:
2688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_autopm_put_interface(synusb->intf);
2698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return retval;
2708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
2718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_close(struct input_dev *dev)
2738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
2748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = input_get_drvdata(dev);
2758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int autopm_error;
2768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	autopm_error = usb_autopm_get_interface(synusb->intf);
2788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_kill_urb(synusb->urb);
2808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->intf->needs_remote_wakeup = 0;
2818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!autopm_error)
2838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		usb_autopm_put_interface(synusb->intf);
2848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
2858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_probe(struct usb_interface *intf,
2878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			const struct usb_device_id *id)
2888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
2898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct usb_device *udev = interface_to_usbdev(intf);
2908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct usb_endpoint_descriptor *ep;
2918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb;
2928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev;
2938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber;
2948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	unsigned int altsetting = min(intf->num_altsetting, 1U);
2958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int error;
2968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
2978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	error = usb_set_interface(udev, intf_num, altsetting);
2988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (error) {
2998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		dev_err(&udev->dev,
3008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			"Can not set alternate setting to %i, error: %i",
3018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			altsetting, error);
3028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		return error;
3038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	ep = synusb_get_in_endpoint(intf->cur_altsetting);
3068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!ep)
3078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		return -ENODEV;
3088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb = kzalloc(sizeof(*synusb), GFP_KERNEL);
3108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_dev = input_allocate_device();
3118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!synusb || !input_dev) {
3128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		error = -ENOMEM;
3138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		goto err_free_mem;
3148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->udev = udev;
3178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->intf = intf;
3188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->input = input_dev;
3198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->flags = id->driver_info;
3218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_COMBO) {
3228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		/*
3238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		 * This is a combo device, we need to set proper
3248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		 * capability, depending on the interface.
3258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		 */
3268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		synusb->flags |= intf_num == 1 ?
3278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff					SYNUSB_STICK : SYNUSB_TOUCHPAD;
3288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->urb = usb_alloc_urb(0, GFP_KERNEL);
3318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!synusb->urb) {
3328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		error = -ENOMEM;
3338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		goto err_free_mem;
3348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL,
3378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff					  &synusb->urb->transfer_dma);
3388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!synusb->data) {
3398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		error = -ENOMEM;
3408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		goto err_free_urb;
3418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_fill_int_urb(synusb->urb, udev,
3448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 usb_rcvintpipe(udev, ep->bEndpointAddress),
3458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 synusb->data, SYNUSB_RECV_SIZE,
3468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 synusb_irq, synusb,
3478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 ep->bInterval);
3488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
3498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (udev->manufacturer)
3518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		strlcpy(synusb->name, udev->manufacturer,
3528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			sizeof(synusb->name));
3538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (udev->product) {
3558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		if (udev->manufacturer)
3568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			strlcat(synusb->name, " ", sizeof(synusb->name));
3578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		strlcat(synusb->name, udev->product, sizeof(synusb->name));
3588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!strlen(synusb->name))
3618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		snprintf(synusb->name, sizeof(synusb->name),
3628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 "USB Synaptics Device %04x:%04x",
3638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 le16_to_cpu(udev->descriptor.idVendor),
3648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			 le16_to_cpu(udev->descriptor.idProduct));
3658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_STICK)
3678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		strlcat(synusb->name, " (Stick) ", sizeof(synusb->name));
3688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_make_path(udev, synusb->phys, sizeof(synusb->phys));
3708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	strlcat(synusb->phys, "/input0", sizeof(synusb->phys));
3718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_dev->name = synusb->name;
3738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_dev->phys = synusb->phys;
3748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_to_input_id(udev, &input_dev->id);
3758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_dev->dev.parent = &synusb->intf->dev;
3768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (!(synusb->flags & SYNUSB_IO_ALWAYS)) {
3788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_dev->open = synusb_open;
3798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_dev->close = synusb_close;
3808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
3818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_set_drvdata(input_dev, synusb);
3838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	__set_bit(EV_ABS, input_dev->evbit);
3858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	__set_bit(EV_KEY, input_dev->evbit);
3868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
3878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_STICK) {
3888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(EV_REL, input_dev->evbit);
3898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(REL_X, input_dev->relbit);
3908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(REL_Y, input_dev->relbit);
3918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0);
3928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	} else {
3938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_set_abs_params(input_dev, ABS_X,
3948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff				     XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
3958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_set_abs_params(input_dev, ABS_Y,
3968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff				     YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
3978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
3988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
3998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(BTN_TOUCH, input_dev->keybit);
4008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
4018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
4028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
4038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
4048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	__set_bit(BTN_LEFT, input_dev->keybit);
4068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	__set_bit(BTN_RIGHT, input_dev->keybit);
4078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	__set_bit(BTN_MIDDLE, input_dev->keybit);
4088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_set_intfdata(intf, synusb);
4108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_IO_ALWAYS) {
4128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		error = synusb_open(input_dev);
4138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		if (error)
4148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			goto err_free_dma;
4158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
4168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	error = input_register_device(input_dev);
4188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (error) {
4198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		dev_err(&udev->dev,
4208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			"Failed to register input device, error %d\n",
4218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			error);
4228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		goto err_stop_io;
4238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
4248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return 0;
4268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_stop_io:
4288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_IO_ALWAYS)
4298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		synusb_close(synusb->input);
4308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_free_dma:
4318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data,
4328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			  synusb->urb->transfer_dma);
4338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_free_urb:
4348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_free_urb(synusb->urb);
4358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhofferr_free_mem:
4368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_free_device(input_dev);
4378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	kfree(synusb);
4388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_set_intfdata(intf, NULL);
4398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return error;
4418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
4428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic void synusb_disconnect(struct usb_interface *intf)
4448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
4458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = usb_get_intfdata(intf);
4468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct usb_device *udev = interface_to_usbdev(intf);
4478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if (synusb->flags & SYNUSB_IO_ALWAYS)
4498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		synusb_close(synusb->input);
4508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4518491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	input_unregister_device(synusb->input);
4528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data,
4548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff			  synusb->urb->transfer_dma);
4558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_free_urb(synusb->urb);
4568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	kfree(synusb);
4578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4588491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_set_intfdata(intf, NULL);
4598491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
4608491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4618491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_suspend(struct usb_interface *intf, pm_message_t message)
4628491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
4638491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = usb_get_intfdata(intf);
4648491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
4658491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4668491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	mutex_lock(&input_dev->mutex);
4678491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_kill_urb(synusb->urb);
4688491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	mutex_unlock(&input_dev->mutex);
4698491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4708491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return 0;
4718491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
4728491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4738491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_resume(struct usb_interface *intf)
4748491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
4758491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = usb_get_intfdata(intf);
4768491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
4778491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int retval = 0;
4788491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4798491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	mutex_lock(&input_dev->mutex);
4808491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4818491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
4828491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	    usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
4838491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		retval = -EIO;
4848491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
4858491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4868491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	mutex_unlock(&input_dev->mutex);
4878491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4888491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return retval;
4898491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
4908491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4918491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_pre_reset(struct usb_interface *intf)
4928491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
4938491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = usb_get_intfdata(intf);
4948491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
4958491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4968491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	mutex_lock(&input_dev->mutex);
4978491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	usb_kill_urb(synusb->urb);
4988491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
4998491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return 0;
5008491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
5018491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5028491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_post_reset(struct usb_interface *intf)
5038491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
5048491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct synusb *synusb = usb_get_intfdata(intf);
5058491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	struct input_dev *input_dev = synusb->input;
5068491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	int retval = 0;
5078491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5088491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
5098491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	    usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
5108491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		retval = -EIO;
5118491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	}
5128491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5138491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	mutex_unlock(&input_dev->mutex);
5148491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5158491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return retval;
5168491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
5178491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5188491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic int synusb_reset_resume(struct usb_interface *intf)
5198491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff{
5208491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	return synusb_resume(intf);
5218491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff}
5228491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5238491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic struct usb_device_id synusb_idtable[] = {
5248491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) },
5258491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) },
5268491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(CPAD,
5278491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff		SYNUSB_TOUCHPAD | SYNUSB_AUXDISPLAY | SYNUSB_IO_ALWAYS) },
5288491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(TS, SYNUSB_TOUCHSCREEN) },
5298491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(STICK, SYNUSB_STICK) },
5308491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(WP, SYNUSB_TOUCHPAD) },
5318491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) },
5328491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) },
5338491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) },
5348491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	{ }
5358491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff};
5368491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_DEVICE_TABLE(usb, synusb_idtable);
5378491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5388491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoffstatic struct usb_driver synusb_driver = {
5398491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.name		= "synaptics_usb",
5408491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.probe		= synusb_probe,
5418491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.disconnect	= synusb_disconnect,
5428491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.id_table	= synusb_idtable,
5438491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.suspend	= synusb_suspend,
5448491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.resume		= synusb_resume,
5458491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.pre_reset	= synusb_pre_reset,
5468491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.post_reset	= synusb_post_reset,
5478491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.reset_resume	= synusb_reset_resume,
5488491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff	.supports_autosuspend = 1,
5498491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff};
5508491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5514a53383565e340254479ce4d47bc181884ddf6c3Dmitry Torokhovmodule_usb_driver(synusb_driver);
5528491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff
5538491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_AUTHOR("Rob Miller <rob@inpharmatica.co.uk>, "
5548491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff              "Ron Lee <ron@debian.org>, "
5558491ee1093c476ea3a9a19ab8593d8531cab40f7Jan Steinhoff              "Jan Steinhoff <cpad@jan-steinhoff.de>");
5568491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_DESCRIPTION("Synaptics USB device driver");
5578491ee1093c476ea3a9a19ab8593d8531cab40f7Jan SteinhoffMODULE_LICENSE("GPL");
558