e293be
centosplus patch (bug#10447)
e293be
support for touchpad and fn key support for MacBookPro 12,1
e293be
e293be
https://kernel.googlesource.com/pub/scm/linux/kernel/git/groeck/linux-staging/+/dbe08116b87cdc2217f11a78b5b70e29068b7efd%5E1..dbe08116b87cdc2217f11a78b5b70e29068b7efd/
e293be
e293be
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
e293be
e293be
Pull input fixes from Dmitry Torokhov:
e293be
 "The main change is support for keyboards and touchpads found in 2015
e293be
  editions of Macbooks"
e293be
e293be
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
e293be
  Revert "Input: zforce - don't overwrite the stack"
e293be
  Input: bcm5974 - add support for the 2015 Macbook Pro
e293be
  HID: apple: Add support for the 2015 Macbook Pro
e293be
  Input: bcm5974 - prepare for a new trackpad generation
e293be
  Input: synaptics - dump ext10 capabilities as well
e293be
e293be
Applied-by Akemi Yagi <toracat@centos.org>
e293be
e293be
--- a/drivers/hid/hid-apple.c	2016-01-23 00:53:07.000000000 -0800
e293be
+++ b/drivers/hid/hid-apple.c	2016-03-08 12:41:27.147368677 -0800
e293be
@@ -552,6 +552,12 @@ static const struct hid_device_id apple_
e293be
 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
e293be
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
e293be
+		.driver_data = APPLE_HAS_FN },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
e293be
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
e293be
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
e293be
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
e293be
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
e293be
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
e293be
--- a/drivers/hid/hid-core.c	2016-01-23 00:53:07.000000000 -0800
e293be
+++ b/drivers/hid/hid-core.c	2016-03-08 12:45:44.846880469 -0800
e293be
@@ -1643,6 +1643,9 @@ static const struct hid_device_id hid_ha
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
e293be
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
e293be
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
e293be
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
e293be
@@ -2284,6 +2287,9 @@ static const struct hid_device_id hid_mo
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
e293be
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
e293be
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
e293be
 	{ }
e293be
--- a/drivers/hid/hid-ids.h	2016-01-23 00:53:07.000000000 -0800
e293be
+++ b/drivers/hid/hid-ids.h	2016-03-08 12:48:25.532198900 -0800
e293be
@@ -138,6 +138,9 @@
e293be
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI	0x0290
e293be
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO	0x0291
e293be
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS	0x0292
e293be
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI	0x0272
e293be
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO		0x0273
e293be
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS		0x0274
e293be
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
e293be
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
e293be
 #define USB_DEVICE_ID_APPLE_IRCONTROL	0x8240
e293be
--- a/drivers/input/mouse/bcm5974.c	2016-01-23 00:53:07.000000000 -0800
e293be
+++ b/drivers/input/mouse/bcm5974.c	2016-03-08 13:37:14.906154047 -0800
e293be
@@ -2,6 +2,7 @@
e293be
  * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver
e293be
  *
e293be
  * Copyright (C) 2008	   Henrik Rydberg (rydberg@euromail.se)
e293be
+ * Copyright (C) 2015      John Horan (knasher@gmail.com)
e293be
  *
e293be
  * The USB initialization and package decoding was made by
e293be
  * Scott Shawcroft as part of the touchd user-space driver project:
e293be
@@ -92,6 +93,10 @@
e293be
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI	0x0290
e293be
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO	0x0291
e293be
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS	0x0292
e293be
+/* MacbookPro12,1 (2015) */
e293be
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI	0x0272
e293be
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO	0x0273
e293be
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS	0x0274
e293be
 
e293be
 #define BCM5974_DEVICE(prod) {					\
e293be
 	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\
e293be
@@ -153,6 +158,10 @@ static const struct usb_device_id bcm597
e293be
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
e293be
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
e293be
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
e293be
+	/* MacbookPro12,1 */
e293be
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
e293be
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
e293be
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
e293be
 	/* Terminating entry */
e293be
 	{}
e293be
 };
e293be
@@ -181,21 +190,47 @@ struct bt_data {
e293be
 enum tp_type {
e293be
 	TYPE1,			/* plain trackpad */
e293be
 	TYPE2,			/* button integrated in trackpad */
e293be
-	TYPE3			/* additional header fields since June 2013 */
e293be
+	TYPE3,			/* additional header fields since June 2013 */
e293be
+	TYPE4			/* additional header field for pressure data */
e293be
 };
e293be
 
e293be
 /* trackpad finger data offsets, le16-aligned */
e293be
-#define FINGER_TYPE1		(13 * sizeof(__le16))
e293be
-#define FINGER_TYPE2		(15 * sizeof(__le16))
e293be
-#define FINGER_TYPE3		(19 * sizeof(__le16))
e293be
+#define HEADER_TYPE1		(13 * sizeof(__le16))
e293be
+#define HEADER_TYPE2		(15 * sizeof(__le16))
e293be
+#define HEADER_TYPE3		(19 * sizeof(__le16))
e293be
+#define HEADER_TYPE4		(23 * sizeof(__le16))
e293be
 
e293be
 /* trackpad button data offsets */
e293be
+#define BUTTON_TYPE1		0
e293be
 #define BUTTON_TYPE2		15
e293be
 #define BUTTON_TYPE3		23
e293be
+#define BUTTON_TYPE4		31
e293be
 
e293be
 /* list of device capability bits */
e293be
 #define HAS_INTEGRATED_BUTTON	1
e293be
 
e293be
+/* trackpad finger data block size */
e293be
+#define FSIZE_TYPE1		(14 * sizeof(__le16))
e293be
+#define FSIZE_TYPE2		(14 * sizeof(__le16))
e293be
+#define FSIZE_TYPE3		(14 * sizeof(__le16))
e293be
+#define FSIZE_TYPE4		(15 * sizeof(__le16))
e293be
+
e293be
+/* offset from header to finger struct */
e293be
+#define DELTA_TYPE1		(0 * sizeof(__le16))
e293be
+#define DELTA_TYPE2		(0 * sizeof(__le16))
e293be
+#define DELTA_TYPE3		(0 * sizeof(__le16))
e293be
+#define DELTA_TYPE4		(1 * sizeof(__le16))
e293be
+
e293be
+/* usb control message mode switch data */
e293be
+#define USBMSG_TYPE1		8, 0x300, 0, 0, 0x1, 0x8
e293be
+#define USBMSG_TYPE2		8, 0x300, 0, 0, 0x1, 0x8
e293be
+#define USBMSG_TYPE3		8, 0x300, 0, 0, 0x1, 0x8
e293be
+#define USBMSG_TYPE4		2, 0x302, 2, 1, 0x1, 0x0
e293be
+
e293be
+/* Wellspring initialization constants */
e293be
+#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID		1
e293be
+#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID	9
e293be
+
e293be
 /* trackpad finger structure, le16-aligned */
e293be
 struct tp_finger {
e293be
 	__le16 origin;		/* zero when switching track finger */
e293be
@@ -208,14 +243,13 @@ struct tp_finger {
e293be
 	__le16 orientation;	/* 16384 when point, else 15 bit angle */
e293be
 	__le16 touch_major;	/* touch area, major axis */
e293be
 	__le16 touch_minor;	/* touch area, minor axis */
e293be
-	__le16 unused[3];	/* zeros */
e293be
+	__le16 unused[2];	/* zeros */
e293be
+	__le16 pressure;	/* pressure on forcetouch touchpad */
e293be
 	__le16 multi;		/* one finger: varies, more fingers: constant */
e293be
 } __attribute__((packed,aligned(2)));
e293be
 
e293be
 /* trackpad finger data size, empirically at least ten fingers */
e293be
 #define MAX_FINGERS		16
e293be
-#define SIZEOF_FINGER		sizeof(struct tp_finger)
e293be
-#define SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
e293be
 #define MAX_FINGER_ORIENTATION	16384
e293be
 
e293be
 /* device-specific parameters */
e293be
@@ -233,8 +267,17 @@ struct bcm5974_config {
e293be
 	int bt_datalen;		/* data length of the button interface */
e293be
 	int tp_ep;		/* the endpoint of the trackpad interface */
e293be
 	enum tp_type tp_type;	/* type of trackpad interface */
e293be
-	int tp_offset;		/* offset to trackpad finger data */
e293be
+	int tp_header;		/* bytes in header block */
e293be
 	int tp_datalen;		/* data length of the trackpad interface */
e293be
+	int tp_button;		/* offset to button data */
e293be
+	int tp_fsize;		/* bytes in single finger block */
e293be
+	int tp_delta;		/* offset from header to finger struct */
e293be
+	int um_size;		/* usb control message length */
e293be
+	int um_req_val;		/* usb control message value */
e293be
+	int um_req_idx;		/* usb control message index */
e293be
+	int um_switch_idx;	/* usb control message mode switch index */
e293be
+	int um_switch_on;	/* usb control message mode switch on */
e293be
+	int um_switch_off;	/* usb control message mode switch off */
e293be
 	struct bcm5974_param p;	/* finger pressure limits */
e293be
 	struct bcm5974_param w;	/* finger width limits */
e293be
 	struct bcm5974_param x;	/* horizontal limits */
e293be
@@ -260,6 +303,24 @@ struct bcm5974 {
e293be
 	int slots[MAX_FINGERS];				/* slot assignments */
e293be
 };
e293be
 
e293be
+/* trackpad finger block data, le16-aligned */
e293be
+static const struct tp_finger *get_tp_finger(const struct bcm5974 *dev, int i)
e293be
+{
e293be
+	const struct bcm5974_config *c = &dev->cfg;
e293be
+	u8 *f_base = dev->tp_data + c->tp_header + c->tp_delta;
e293be
+
e293be
+	return (const struct tp_finger *)(f_base + i * c->tp_fsize);
e293be
+}
e293be
+
e293be
+#define DATAFORMAT(type)				\
e293be
+	type,						\
e293be
+	HEADER_##type,					\
e293be
+	HEADER_##type + (MAX_FINGERS) * (FSIZE_##type),	\
e293be
+	BUTTON_##type,					\
e293be
+	FSIZE_##type,					\
e293be
+	DELTA_##type,					\
e293be
+	USBMSG_##type
e293be
+
e293be
 /* logical signal quality */
e293be
 #define SN_PRESSURE	45		/* pressure signal-to-noise ratio */
e293be
 #define SN_WIDTH	25		/* width signal-to-noise ratio */
e293be
@@ -274,7 +335,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
e293be
 		0,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE1),
e293be
 		{ SN_PRESSURE, 0, 256 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4824, 5342 },
e293be
@@ -287,7 +348,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
e293be
 		0,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE1),
e293be
 		{ SN_PRESSURE, 0, 256 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4824, 4824 },
e293be
@@ -300,7 +361,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4460, 5166 },
e293be
@@ -313,7 +374,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4620, 5140 },
e293be
@@ -326,7 +387,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4616, 5112 },
e293be
@@ -339,7 +400,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4415, 5050 },
e293be
@@ -352,7 +413,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING6_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4620, 5140 },
e293be
@@ -365,7 +426,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4750, 5280 },
e293be
@@ -378,7 +439,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4620, 5140 },
e293be
@@ -391,7 +452,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4750, 5280 },
e293be
@@ -404,7 +465,7 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0x84, sizeof(struct bt_data),
e293be
-		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
e293be
+		0x81, DATAFORMAT(TYPE2),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4750, 5280 },
e293be
@@ -417,13 +478,26 @@ static const struct bcm5974_config bcm59
e293be
 		USB_DEVICE_ID_APPLE_WELLSPRING8_JIS,
e293be
 		HAS_INTEGRATED_BUTTON,
e293be
 		0, sizeof(struct bt_data),
e293be
-		0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS,
e293be
+		0x83, DATAFORMAT(TYPE3),
e293be
 		{ SN_PRESSURE, 0, 300 },
e293be
 		{ SN_WIDTH, 0, 2048 },
e293be
 		{ SN_COORD, -4620, 5140 },
e293be
 		{ SN_COORD, -150, 6600 },
e293be
 		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
e293be
 	},
e293be
+	{
e293be
+		USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI,
e293be
+		USB_DEVICE_ID_APPLE_WELLSPRING9_ISO,
e293be
+		USB_DEVICE_ID_APPLE_WELLSPRING9_JIS,
e293be
+		HAS_INTEGRATED_BUTTON,
e293be
+		0, sizeof(struct bt_data),
e293be
+		0x83, DATAFORMAT(TYPE4),
e293be
+		{ SN_PRESSURE, 0, 300 },
e293be
+		{ SN_WIDTH, 0, 2048 },
e293be
+		{ SN_COORD, -4828, 5345 },
e293be
+		{ SN_COORD, -203, 6803 },
e293be
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
e293be
+	},
e293be
 	{}
e293be
 };
e293be
 
e293be
@@ -550,19 +624,18 @@ static int report_tp_state(struct bcm597
e293be
 	struct input_dev *input = dev->input;
e293be
 	int raw_n, i, n = 0;
e293be
 
e293be
-	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
e293be
+	if (size < c->tp_header || (size - c->tp_header) % c->tp_fsize != 0)
e293be
 		return -EIO;
e293be
 
e293be
-	/* finger data, le16-aligned */
e293be
-	f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
e293be
-	raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
e293be
+	raw_n = (size - c->tp_header) / c->tp_fsize;
e293be
 
e293be
 	for (i = 0; i < raw_n; i++) {
e293be
-		if (raw2int(f[i].touch_major) == 0)
e293be
+		f = get_tp_finger(dev, i);
e293be
+		if (raw2int(f->touch_major) == 0)
e293be
 			continue;
e293be
-		dev->pos[n].x = raw2int(f[i].abs_x);
e293be
-		dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y);
e293be
-		dev->index[n++] = &f[i];
e293be
+		dev->pos[n].x = raw2int(f->abs_x);
e293be
+		dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y);
e293be
+		dev->index[n++] = f;
e293be
 	}
e293be
 
e293be
 	input_mt_assign_slots(input, dev->slots, dev->pos, n);
e293be
@@ -573,32 +646,22 @@ static int report_tp_state(struct bcm597
e293be
 
e293be
 	input_mt_sync_frame(input);
e293be
 
e293be
-	report_synaptics_data(input, c, f, raw_n);
e293be
+	report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n);
e293be
 
e293be
-	/* type 2 reports button events via ibt only */
e293be
-	if (c->tp_type == TYPE2) {
e293be
-		int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
e293be
+	/* later types report button events via integrated button only */
e293be
+	if (c->caps & HAS_INTEGRATED_BUTTON) {
e293be
+		int ibt = raw2int(dev->tp_data[c->tp_button]);
e293be
 		input_report_key(input, BTN_LEFT, ibt);
e293be
 	}
e293be
 
e293be
-	if (c->tp_type == TYPE3)
e293be
-		input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]);
e293be
-
e293be
 	input_sync(input);
e293be
 
e293be
 	return 0;
e293be
 }
e293be
 
e293be
-/* Wellspring initialization constants */
e293be
-#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID		1
e293be
-#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID	9
e293be
-#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE		0x300
e293be
-#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX		0
e293be
-#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE		0x01
e293be
-#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE		0x08
e293be
-
e293be
 static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
e293be
 {
e293be
+	const struct bcm5974_config *c = &dev->cfg;
e293be
 	int retval = 0, size;
e293be
 	char *data;
e293be
 
e293be
@@ -606,7 +669,7 @@ static int bcm5974_wellspring_mode(struc
e293be
 	if (dev->cfg.tp_type == TYPE3)
e293be
 		return 0;
e293be
 
e293be
-	data = kmalloc(8, GFP_KERNEL);
e293be
+	data = kmalloc(c->um_size, GFP_KERNEL);
e293be
 	if (!data) {
e293be
 		dev_err(&dev->intf->dev, "out of memory\n");
e293be
 		retval = -ENOMEM;
e293be
@@ -617,28 +680,24 @@ static int bcm5974_wellspring_mode(struc
e293be
 	size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
e293be
 			BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
e293be
 			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
e293be
-			BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
e293be
-			BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
e293be
+			c->um_req_val, c->um_req_idx, data, c->um_size, 5000);
e293be
 
e293be
-	if (size != 8) {
e293be
+	if (size != c->um_size) {
e293be
 		dev_err(&dev->intf->dev, "could not read from device\n");
e293be
 		retval = -EIO;
e293be
 		goto out;
e293be
 	}
e293be
 
e293be
 	/* apply the mode switch */
e293be
-	data[0] = on ?
e293be
-		BCM5974_WELLSPRING_MODE_VENDOR_VALUE :
e293be
-		BCM5974_WELLSPRING_MODE_NORMAL_VALUE;
e293be
+	data[c->um_switch_idx] = on ? c->um_switch_on : c->um_switch_off;
e293be
 
e293be
 	/* write configuration */
e293be
 	size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
e293be
 			BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
e293be
 			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
e293be
-			BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
e293be
-			BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
e293be
+			c->um_req_val, c->um_req_idx, data, c->um_size, 5000);
e293be
 
e293be
-	if (size != 8) {
e293be
+	if (size != c->um_size) {
e293be
 		dev_err(&dev->intf->dev, "could not write to device\n");
e293be
 		retval = -EIO;
e293be
 		goto out;