From 148c1c8ad3c4170186ebe6ea5900adde27d2a0e7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 1 Jul 2013 11:47:51 -0700 Subject: Input: bcm5974 - add support for the 2013 MacBook Air The June 2013 Macbook Air (13'') has a new trackpad protocol; four new values are inserted in the header, and the mode switch is no longer needed. This patch adds support for the new devices. Cc: stable@vger.kernel.org Reported-and-tested-by: Brad Ford Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2baff1b79a55..4ef4d5e198ae 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -88,6 +88,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a #define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b +/* MacbookAir6,2 (unibody, June 2013) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0291 +#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0292 +#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0293 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -145,6 +149,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), + /* MacbookAir6,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS), /* Terminating entry */ {} }; @@ -172,15 +180,18 @@ struct bt_data { /* trackpad header types */ enum tp_type { TYPE1, /* plain trackpad */ - TYPE2 /* button integrated in trackpad */ + TYPE2, /* button integrated in trackpad */ + TYPE3 /* additional header fields since June 2013 */ }; /* trackpad finger data offsets, le16-aligned */ #define FINGER_TYPE1 (13 * sizeof(__le16)) #define FINGER_TYPE2 (15 * sizeof(__le16)) +#define FINGER_TYPE3 (19 * sizeof(__le16)) /* trackpad button data offsets */ #define BUTTON_TYPE2 15 +#define BUTTON_TYPE3 23 /* list of device capability bits */ #define HAS_INTEGRATED_BUTTON 1 @@ -400,6 +411,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { { SN_COORD, -150, 6730 }, { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING8_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING8_JIS, + HAS_INTEGRATED_BUTTON, + 0, sizeof(struct bt_data), + 0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS, + { SN_PRESSURE, 0, 300 }, + { SN_WIDTH, 0, 2048 }, + { SN_COORD, -4620, 5140 }, + { SN_COORD, -150, 6600 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, {} }; @@ -557,6 +581,9 @@ static int report_tp_state(struct bcm5974 *dev, int size) input_report_key(input, BTN_LEFT, ibt); } + if (c->tp_type == TYPE3) + input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]); + input_sync(input); return 0; @@ -572,9 +599,14 @@ static int report_tp_state(struct bcm5974 *dev, int size) static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) { - char *data = kmalloc(8, GFP_KERNEL); int retval = 0, size; + char *data; + + /* Type 3 does not require a mode switch */ + if (dev->cfg.tp_type == TYPE3) + return 0; + data = kmalloc(8, GFP_KERNEL); if (!data) { dev_err(&dev->intf->dev, "out of memory\n"); retval = -ENOMEM; -- cgit v1.2.3 From acc0444bf83ea559fa84b527b1f49cf20b0df253 Mon Sep 17 00:00:00 2001 From: Matteo Delfino Date: Thu, 15 Aug 2013 00:09:41 -0700 Subject: Input: elantech - fix packet check for v3 and v4 hardware The signatures of v3 and v4 packets change depending on the value of a hardware flag called 'crc_enabled'. The packet type detection must change accordingly. This patch also restores a consistency check for v4 packets inadvertently removed by commit: 9eebed7de660c0b5ab129a9de4f89d20b60de68c Input: elantech - fix for newer hardware versions (v7) A note about the naming convention: v3 hardware is associated with IC body v5 while v4 hardware is associated with IC body v6 and v7. The above commit refers to IC body v7, not to v7 hardware. Tested on Samsung NP730U3E (fw = 0x675f05, ICv7, crc_enabled = 1) Tested-by: Giovanni Frigione Signed-off-by: Matteo Delfino Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 44 ++++++++++++++++++++++++++++++++++++++---- drivers/input/mouse/elantech.h | 1 + 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 57b2637e153a..8551dcaf24db 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -672,6 +672,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) */ static int elantech_packet_check_v3(struct psmouse *psmouse) { + struct elantech_data *etd = psmouse->private; const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; unsigned char *packet = psmouse->packet; @@ -682,19 +683,48 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) return PACKET_DEBOUNCE; - if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) - return PACKET_V3_HEAD; + /* + * If the hardware flag 'crc_enabled' is set the packets have + * different signatures. + */ + if (etd->crc_enabled) { + if ((packet[3] & 0x09) == 0x08) + return PACKET_V3_HEAD; + + if ((packet[3] & 0x09) == 0x09) + return PACKET_V3_TAIL; + } else { + if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) + return PACKET_V3_HEAD; - if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) - return PACKET_V3_TAIL; + if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) + return PACKET_V3_TAIL; + } return PACKET_UNKNOWN; } static int elantech_packet_check_v4(struct psmouse *psmouse) { + struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; unsigned char packet_type = packet[3] & 0x03; + bool sanity_check; + + /* + * Sanity check based on the constant bits of a packet. + * The constant bits change depending on the value of + * the hardware flag 'crc_enabled' but are the same for + * every packet, regardless of the type. + */ + if (etd->crc_enabled) + sanity_check = ((packet[3] & 0x08) == 0x00); + else + sanity_check = ((packet[0] & 0x0c) == 0x04 && + (packet[3] & 0x1c) == 0x10); + + if (!sanity_check) + return PACKET_UNKNOWN; switch (packet_type) { case 0: @@ -1313,6 +1343,12 @@ static int elantech_set_properties(struct elantech_data *etd) etd->reports_pressure = true; } + /* + * The signatures of v3 and v4 packets change depending on the + * value of this hardware flag. + */ + etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000); + return 0; } diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 46db3be45ac9..036a04abaef7 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -129,6 +129,7 @@ struct elantech_data { bool paritycheck; bool jumpy_cursor; bool reports_pressure; + bool crc_enabled; unsigned char hw_version; unsigned int fw_version; unsigned int single_finger_reports; -- cgit v1.2.3