Commit 1aae31c8 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
 "The main change is that we now publish "firmware ID" for the serio
  devices to help userspace figure out the kind of touchpads it is
  dealing with: i8042 will export PS/2 port's PNP IDs as firmware IDs.

  You will also get more quirks for Synaptics touchpads in various
  Lenovo laptops, a change to elantech driver to recognize even more
  models, and fixups to wacom and couple other drivers"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: elantech - add support for newer elantech touchpads
  Input: soc_button_array - fix a crash during rmmod
  Input: synaptics - add min/max quirk for ThinkPad T431s, L440, L540, S1 Yoga and X1
  Input: synaptics - report INPUT_PROP_TOPBUTTONPAD property
  Input: Add INPUT_PROP_TOPBUTTONPAD device property
  Input: i8042 - add firmware_id support
  Input: serio - add firmware_id sysfs attribute
  Input: wacom - handle 1024 pressure levels in wacom_tpc_pen
  Input: wacom - references to 'wacom->data' should use 'unsigned char*'
  Input: wacom - override 'pressure_max' with value from HID_USAGE_PRESSURE
  Input: wacom - use full 32-bit HID Usage value in switch statement
  Input: wacom - missed the last bit of expresskey for DTU-1031
  Input: ads7846 - fix device usage within attribute show
  Input: da9055_onkey - remove use of regmap_irq_get_virq()
parents 6db8148c ae4bedf0
...@@ -109,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev) ...@@ -109,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work); INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work);
irq = regmap_irq_get_virq(da9055->irq_data, irq);
err = request_threaded_irq(irq, NULL, da9055_onkey_irq, err = request_threaded_irq(irq, NULL, da9055_onkey_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"ONKEY", onkey); "ONKEY", onkey);
......
...@@ -169,6 +169,7 @@ static int soc_button_pnp_probe(struct pnp_dev *pdev, ...@@ -169,6 +169,7 @@ static int soc_button_pnp_probe(struct pnp_dev *pdev,
soc_button_remove(pdev); soc_button_remove(pdev);
return error; return error;
} }
continue;
} }
priv->children[i] = pd; priv->children[i] = pd;
......
...@@ -1353,6 +1353,7 @@ static int elantech_set_properties(struct elantech_data *etd) ...@@ -1353,6 +1353,7 @@ static int elantech_set_properties(struct elantech_data *etd)
case 6: case 6:
case 7: case 7:
case 8: case 8:
case 9:
etd->hw_version = 4; etd->hw_version = 4;
break; break;
default: default:
......
...@@ -117,6 +117,44 @@ void synaptics_reset(struct psmouse *psmouse) ...@@ -117,6 +117,44 @@ void synaptics_reset(struct psmouse *psmouse)
} }
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
/* This list has been kindly provided by Synaptics. */
static const char * const topbuttonpad_pnp_ids[] = {
"LEN0017",
"LEN0018",
"LEN0019",
"LEN0023",
"LEN002A",
"LEN002B",
"LEN002C",
"LEN002D",
"LEN002E",
"LEN0033", /* Helix */
"LEN0034", /* T431s, T540, X1 Carbon 2nd */
"LEN0035", /* X240 */
"LEN0036", /* T440 */
"LEN0037",
"LEN0038",
"LEN0041",
"LEN0042", /* Yoga */
"LEN0045",
"LEN0046",
"LEN0047",
"LEN0048",
"LEN0049",
"LEN2000",
"LEN2001",
"LEN2002",
"LEN2003",
"LEN2004", /* L440 */
"LEN2005",
"LEN2006",
"LEN2007",
"LEN2008",
"LEN2009",
"LEN200A",
"LEN200B",
NULL
};
/***************************************************************************** /*****************************************************************************
* Synaptics communications functions * Synaptics communications functions
...@@ -1255,8 +1293,10 @@ static void set_abs_position_params(struct input_dev *dev, ...@@ -1255,8 +1293,10 @@ static void set_abs_position_params(struct input_dev *dev,
input_abs_set_res(dev, y_code, priv->y_res); input_abs_set_res(dev, y_code, priv->y_res);
} }
static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) static void set_input_params(struct psmouse *psmouse,
struct synaptics_data *priv)
{ {
struct input_dev *dev = psmouse->dev;
int i; int i;
/* Things that apply to both modes */ /* Things that apply to both modes */
...@@ -1325,6 +1365,17 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) ...@@ -1325,6 +1365,17 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
/* See if this buttonpad has a top button area */
if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) {
for (i = 0; topbuttonpad_pnp_ids[i]; i++) {
if (strstr(psmouse->ps2dev.serio->firmware_id,
topbuttonpad_pnp_ids[i])) {
__set_bit(INPUT_PROP_TOPBUTTONPAD,
dev->propbit);
break;
}
}
}
/* Clickpads report only left button */ /* Clickpads report only left button */
__clear_bit(BTN_RIGHT, dev->keybit); __clear_bit(BTN_RIGHT, dev->keybit);
__clear_bit(BTN_MIDDLE, dev->keybit); __clear_bit(BTN_MIDDLE, dev->keybit);
...@@ -1514,6 +1565,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { ...@@ -1514,6 +1565,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
}, },
.driver_data = (int []){1232, 5710, 1156, 4696}, .driver_data = (int []){1232, 5710, 1156, 4696},
}, },
{
/* Lenovo ThinkPad T431s */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"),
},
.driver_data = (int []){1024, 5112, 2024, 4832},
},
{ {
/* Lenovo ThinkPad T440s */ /* Lenovo ThinkPad T440s */
.matches = { .matches = {
...@@ -1522,6 +1581,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { ...@@ -1522,6 +1581,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
}, },
.driver_data = (int []){1024, 5112, 2024, 4832}, .driver_data = (int []){1024, 5112, 2024, 4832},
}, },
{
/* Lenovo ThinkPad L440 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"),
},
.driver_data = (int []){1024, 5112, 2024, 4832},
},
{ {
/* Lenovo ThinkPad T540p */ /* Lenovo ThinkPad T540p */
.matches = { .matches = {
...@@ -1530,6 +1597,32 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { ...@@ -1530,6 +1597,32 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
}, },
.driver_data = (int []){1024, 5056, 2058, 4832}, .driver_data = (int []){1024, 5056, 2058, 4832},
}, },
{
/* Lenovo ThinkPad L540 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"),
},
.driver_data = (int []){1024, 5112, 2024, 4832},
},
{
/* Lenovo Yoga S1 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
"ThinkPad S1 Yoga"),
},
.driver_data = (int []){1232, 5710, 1156, 4696},
},
{
/* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION,
"ThinkPad X1 Carbon 2nd"),
},
.driver_data = (int []){1024, 5112, 2024, 4832},
},
#endif #endif
{ } { }
}; };
...@@ -1593,7 +1686,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) ...@@ -1593,7 +1686,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
priv->capabilities, priv->ext_cap, priv->ext_cap_0c, priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
priv->board_id, priv->firmware_id); priv->board_id, priv->firmware_id);
set_input_params(psmouse->dev, priv); set_input_params(psmouse, priv);
/* /*
* Encode touchpad model so that it can be used to set * Encode touchpad model so that it can be used to set
......
...@@ -702,6 +702,17 @@ static int i8042_pnp_aux_irq; ...@@ -702,6 +702,17 @@ static int i8042_pnp_aux_irq;
static char i8042_pnp_kbd_name[32]; static char i8042_pnp_kbd_name[32];
static char i8042_pnp_aux_name[32]; static char i8042_pnp_aux_name[32];
static void i8042_pnp_id_to_string(struct pnp_id *id, char *dst, int dst_size)
{
strlcpy(dst, "PNP:", dst_size);
while (id) {
strlcat(dst, " ", dst_size);
strlcat(dst, id->id, dst_size);
id = id->next;
}
}
static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did) static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
{ {
if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1) if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
...@@ -718,6 +729,8 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * ...@@ -718,6 +729,8 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name)); strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
} }
i8042_pnp_id_to_string(dev->id, i8042_kbd_firmware_id,
sizeof(i8042_kbd_firmware_id));
/* Keyboard ports are always supposed to be wakeup-enabled */ /* Keyboard ports are always supposed to be wakeup-enabled */
device_set_wakeup_enable(&dev->dev, true); device_set_wakeup_enable(&dev->dev, true);
...@@ -742,6 +755,8 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * ...@@ -742,6 +755,8 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name)); strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name)); strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
} }
i8042_pnp_id_to_string(dev->id, i8042_aux_firmware_id,
sizeof(i8042_aux_firmware_id));
i8042_pnp_aux_devices++; i8042_pnp_aux_devices++;
return 0; return 0;
......
...@@ -87,6 +87,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); ...@@ -87,6 +87,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
#endif #endif
static bool i8042_bypass_aux_irq_test; static bool i8042_bypass_aux_irq_test;
static char i8042_kbd_firmware_id[128];
static char i8042_aux_firmware_id[128];
#include "i8042.h" #include "i8042.h"
...@@ -1218,6 +1220,8 @@ static int __init i8042_create_kbd_port(void) ...@@ -1218,6 +1220,8 @@ static int __init i8042_create_kbd_port(void)
serio->dev.parent = &i8042_platform_device->dev; serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
strlcpy(serio->firmware_id, i8042_kbd_firmware_id,
sizeof(serio->firmware_id));
port->serio = serio; port->serio = serio;
port->irq = I8042_KBD_IRQ; port->irq = I8042_KBD_IRQ;
...@@ -1244,6 +1248,8 @@ static int __init i8042_create_aux_port(int idx) ...@@ -1244,6 +1248,8 @@ static int __init i8042_create_aux_port(int idx)
if (idx < 0) { if (idx < 0) {
strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name));
strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
strlcpy(serio->firmware_id, i8042_aux_firmware_id,
sizeof(serio->firmware_id));
serio->close = i8042_port_close; serio->close = i8042_port_close;
} else { } else {
snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx);
......
...@@ -451,6 +451,13 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute * ...@@ -451,6 +451,13 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *
return retval; return retval;
} }
static ssize_t firmware_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%s\n", serio->firmware_id);
}
static DEVICE_ATTR_RO(type); static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(proto); static DEVICE_ATTR_RO(proto);
static DEVICE_ATTR_RO(id); static DEVICE_ATTR_RO(id);
...@@ -473,12 +480,14 @@ static DEVICE_ATTR_RO(modalias); ...@@ -473,12 +480,14 @@ static DEVICE_ATTR_RO(modalias);
static DEVICE_ATTR_WO(drvctl); static DEVICE_ATTR_WO(drvctl);
static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL); static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode); static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
static DEVICE_ATTR_RO(firmware_id);
static struct attribute *serio_device_attrs[] = { static struct attribute *serio_device_attrs[] = {
&dev_attr_modalias.attr, &dev_attr_modalias.attr,
&dev_attr_description.attr, &dev_attr_description.attr,
&dev_attr_drvctl.attr, &dev_attr_drvctl.attr,
&dev_attr_bind_mode.attr, &dev_attr_bind_mode.attr,
&dev_attr_firmware_id.attr,
NULL NULL
}; };
...@@ -921,9 +930,14 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -921,9 +930,14 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto); SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id); SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra); SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
if (serio->firmware_id[0])
SERIO_ADD_UEVENT_VAR("SERIO_FIRMWARE_ID=%s",
serio->firmware_id);
return 0; return 0;
} }
#undef SERIO_ADD_UEVENT_VAR #undef SERIO_ADD_UEVENT_VAR
......
...@@ -22,23 +22,18 @@ ...@@ -22,23 +22,18 @@
#define HID_USAGE_PAGE_DIGITIZER 0x0d #define HID_USAGE_PAGE_DIGITIZER 0x0d
#define HID_USAGE_PAGE_DESKTOP 0x01 #define HID_USAGE_PAGE_DESKTOP 0x01
#define HID_USAGE 0x09 #define HID_USAGE 0x09
#define HID_USAGE_X 0x30 #define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
#define HID_USAGE_Y 0x31 #define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
#define HID_USAGE_X_TILT 0x3d #define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
#define HID_USAGE_Y_TILT 0x3e #define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
#define HID_USAGE_FINGER 0x22 #define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
#define HID_USAGE_STYLUS 0x20 #define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
#define HID_USAGE_CONTACTMAX 0x55 #define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
#define HID_COLLECTION 0xa1 #define HID_COLLECTION 0xa1
#define HID_COLLECTION_LOGICAL 0x02 #define HID_COLLECTION_LOGICAL 0x02
#define HID_COLLECTION_END 0xc0 #define HID_COLLECTION_END 0xc0
enum {
WCM_UNDEFINED = 0,
WCM_DESKTOP,
WCM_DIGITIZER,
};
struct hid_descriptor { struct hid_descriptor {
struct usb_descriptor_header header; struct usb_descriptor_header header;
__le16 bcdHID; __le16 bcdHID;
...@@ -305,7 +300,7 @@ static int wacom_parse_hid(struct usb_interface *intf, ...@@ -305,7 +300,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
char limit = 0; char limit = 0;
/* result has to be defined as int for some devices */ /* result has to be defined as int for some devices */
int result = 0, touch_max = 0; int result = 0, touch_max = 0;
int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; int i = 0, page = 0, finger = 0, pen = 0;
unsigned char *report; unsigned char *report;
report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
...@@ -332,134 +327,121 @@ static int wacom_parse_hid(struct usb_interface *intf, ...@@ -332,134 +327,121 @@ static int wacom_parse_hid(struct usb_interface *intf,
switch (report[i]) { switch (report[i]) {
case HID_USAGE_PAGE: case HID_USAGE_PAGE:
switch (report[i + 1]) { page = report[i + 1];
case HID_USAGE_PAGE_DIGITIZER: i++;
usage = WCM_DIGITIZER;
i++;
break;
case HID_USAGE_PAGE_DESKTOP:
usage = WCM_DESKTOP;
i++;
break;
}
break; break;
case HID_USAGE: case HID_USAGE:
switch (report[i + 1]) { switch (page << 16 | report[i + 1]) {
case HID_USAGE_X: case HID_USAGE_X:
if (usage == WCM_DESKTOP) { if (finger) {
if (finger) { features->device_type = BTN_TOOL_FINGER;
features->device_type = BTN_TOOL_FINGER; /* touch device at least supports one touch point */
/* touch device at least supports one touch point */ touch_max = 1;
touch_max = 1; switch (features->type) {
switch (features->type) { case TABLETPC2FG:
case TABLETPC2FG: features->pktlen = WACOM_PKGLEN_TPC2FG;
features->pktlen = WACOM_PKGLEN_TPC2FG; break;
break;
case MTSCREEN:
case MTSCREEN: case WACOM_24HDT:
case WACOM_24HDT: features->pktlen = WACOM_PKGLEN_MTOUCH;
features->pktlen = WACOM_PKGLEN_MTOUCH; break;
break;
case MTTPC:
case MTTPC: features->pktlen = WACOM_PKGLEN_MTTPC;
features->pktlen = WACOM_PKGLEN_MTTPC; break;
break;
case BAMBOO_PT:
case BAMBOO_PT: features->pktlen = WACOM_PKGLEN_BBTOUCH;
features->pktlen = WACOM_PKGLEN_BBTOUCH; break;
break;
default:
default: features->pktlen = WACOM_PKGLEN_GRAPHIRE;
features->pktlen = WACOM_PKGLEN_GRAPHIRE; break;
break; }
}
switch (features->type) {
switch (features->type) { case BAMBOO_PT:
case BAMBOO_PT: features->x_phy =
features->x_phy = get_unaligned_le16(&report[i + 5]);
get_unaligned_le16(&report[i + 5]); features->x_max =
features->x_max = get_unaligned_le16(&report[i + 8]);
get_unaligned_le16(&report[i + 8]); i += 15;
i += 15; break;
break;
case WACOM_24HDT:
case WACOM_24HDT:
features->x_max =
get_unaligned_le16(&report[i + 3]);
features->x_phy =
get_unaligned_le16(&report[i + 8]);
features->unit = report[i - 1];
features->unitExpo = report[i - 3];
i += 12;
break;
default:
features->x_max =
get_unaligned_le16(&report[i + 3]);
features->x_phy =
get_unaligned_le16(&report[i + 6]);
features->unit = report[i + 9];
features->unitExpo = report[i + 11];
i += 12;
break;
}
} else if (pen) {
/* penabled only accepts exact bytes of data */
if (features->type >= TABLETPC)
features->pktlen = WACOM_PKGLEN_GRAPHIRE;
features->device_type = BTN_TOOL_PEN;
features->x_max = features->x_max =
get_unaligned_le16(&report[i + 3]); get_unaligned_le16(&report[i + 3]);
i += 4; features->x_phy =
get_unaligned_le16(&report[i + 8]);
features->unit = report[i - 1];
features->unitExpo = report[i - 3];
i += 12;
break;
default:
features->x_max =
get_unaligned_le16(&report[i + 3]);
features->x_phy =
get_unaligned_le16(&report[i + 6]);
features->unit = report[i + 9];
features->unitExpo = report[i + 11];
i += 12;
break;
} }
} else if (pen) {
/* penabled only accepts exact bytes of data */
if (features->type >= TABLETPC)
features->pktlen = WACOM_PKGLEN_GRAPHIRE;
features->device_type = BTN_TOOL_PEN;
features->x_max =
get_unaligned_le16(&report[i + 3]);
i += 4;
} }
break; break;
case HID_USAGE_Y: case HID_USAGE_Y:
if (usage == WCM_DESKTOP) { if (finger) {
if (finger) { switch (features->type) {
switch (features->type) { case TABLETPC2FG:
case TABLETPC2FG: case MTSCREEN:
case MTSCREEN: case MTTPC:
case MTTPC: features->y_max =
features->y_max = get_unaligned_le16(&report[i + 3]);
get_unaligned_le16(&report[i + 3]); features->y_phy =
features->y_phy = get_unaligned_le16(&report[i + 6]);
get_unaligned_le16(&report[i + 6]); i += 7;
i += 7; break;
break;
case WACOM_24HDT:
case WACOM_24HDT: features->y_max =
features->y_max = get_unaligned_le16(&report[i + 3]);
get_unaligned_le16(&report[i + 3]); features->y_phy =
features->y_phy = get_unaligned_le16(&report[i - 2]);
get_unaligned_le16(&report[i - 2]); i += 7;
i += 7; break;
break;
case BAMBOO_PT:
case BAMBOO_PT: features->y_phy =
features->y_phy = get_unaligned_le16(&report[i + 3]);
get_unaligned_le16(&report[i + 3]); features->y_max =
features->y_max = get_unaligned_le16(&report[i + 6]);
get_unaligned_le16(&report[i + 6]); i += 12;
i += 12; break;
break;
default:
default:
features->y_max =
features->x_max;
features->y_phy =
get_unaligned_le16(&report[i + 3]);
i += 4;
break;
}
} else if (pen) {
features->y_max = features->y_max =
features->x_max;
features->y_phy =
get_unaligned_le16(&report[i + 3]); get_unaligned_le16(&report[i + 3]);
i += 4; i += 4;
break;
} }
} else if (pen) {
features->y_max =
get_unaligned_le16(&report[i + 3]);
i += 4;
} }
break; break;
...@@ -484,12 +466,20 @@ static int wacom_parse_hid(struct usb_interface *intf, ...@@ -484,12 +466,20 @@ static int wacom_parse_hid(struct usb_interface *intf,
wacom_retrieve_report_data(intf, features); wacom_retrieve_report_data(intf, features);
i++; i++;
break; break;
case HID_USAGE_PRESSURE:
if (pen) {
features->pressure_max =
get_unaligned_le16(&report[i + 3]);
i += 4;
}
break;
} }
break; break;
case HID_COLLECTION_END: case HID_COLLECTION_END:
/* reset UsagePage and Finger */ /* reset UsagePage and Finger */
finger = usage = 0; finger = page = 0;
break; break;
case HID_COLLECTION: case HID_COLLECTION:
......
...@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) ...@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom)
static int wacom_dtu_irq(struct wacom_wac *wacom) static int wacom_dtu_irq(struct wacom_wac *wacom)
{ {
struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data;
char *data = wacom->data;
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
int prox = data[1] & 0x20, pressure; int prox = data[1] & 0x20;
dev_dbg(input->dev.parent, dev_dbg(input->dev.parent,
"%s: received report #%d", __func__, data[0]); "%s: received report #%d", __func__, data[0]);
...@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) ...@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS2, data[1] & 0x10); input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
pressure = ((data[7] & 0x01) << 8) | data[6]; input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
if (pressure < 0)
pressure = features->pressure_max + pressure + 1;
input_report_abs(input, ABS_PRESSURE, pressure);
input_report_key(input, BTN_TOUCH, data[1] & 0x05); input_report_key(input, BTN_TOUCH, data[1] & 0x05);
if (!prox) /* out-prox */ if (!prox) /* out-prox */
wacom->id[0] = 0; wacom->id[0] = 0;
...@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2) ...@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2)
static int wacom_24hdt_irq(struct wacom_wac *wacom) static int wacom_24hdt_irq(struct wacom_wac *wacom)
{ {
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
char *data = wacom->data; unsigned char *data = wacom->data;
int i; int i;
int current_num_contacts = data[61]; int current_num_contacts = data[61];
int contacts_to_send = 0; int contacts_to_send = 0;
...@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) ...@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
static int wacom_mt_touch(struct wacom_wac *wacom) static int wacom_mt_touch(struct wacom_wac *wacom)
{ {
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
char *data = wacom->data; unsigned char *data = wacom->data;
int i; int i;
int current_num_contacts = data[2]; int current_num_contacts = data[2];
int contacts_to_send = 0; int contacts_to_send = 0;
...@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom) ...@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
{ {
char *data = wacom->data; unsigned char *data = wacom->data;
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
bool prox; bool prox;
int x = 0, y = 0; int x = 0, y = 0;
...@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) ...@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
static int wacom_tpc_pen(struct wacom_wac *wacom) static int wacom_tpc_pen(struct wacom_wac *wacom)
{ {
struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data;
char *data = wacom->data;
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
int pressure;
bool prox = data[1] & 0x20; bool prox = data[1] & 0x20;
if (!wacom->shared->stylus_in_proximity) /* first in prox */ if (!wacom->shared->stylus_in_proximity) /* first in prox */
...@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom) ...@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS2, data[1] & 0x10); input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
pressure = ((data[7] & 0x01) << 8) | data[6]; input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
if (pressure < 0)
pressure = features->pressure_max + pressure + 1;
input_report_abs(input, ABS_PRESSURE, pressure);
input_report_key(input, BTN_TOUCH, data[1] & 0x05); input_report_key(input, BTN_TOUCH, data[1] & 0x05);
input_report_key(input, wacom->tool[0], prox); input_report_key(input, wacom->tool[0], prox);
return 1; return 1;
...@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom) ...@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
{ {
char *data = wacom->data; unsigned char *data = wacom->data;
dev_dbg(wacom->input->dev.parent, dev_dbg(wacom->input->dev.parent,
"%s: received report #%d\n", __func__, data[0]); "%s: received report #%d\n", __func__, data[0]);
...@@ -1838,7 +1829,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, ...@@ -1838,7 +1829,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case DTU: case DTU:
if (features->type == DTUS) { if (features->type == DTUS) {
input_set_capability(input_dev, EV_MSC, MSC_SERIAL); input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
for (i = 0; i < 3; i++) for (i = 0; i < 4; i++)
__set_bit(BTN_0 + i, input_dev->keybit); __set_bit(BTN_0 + i, input_dev->keybit);
} }
__set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit);
......
...@@ -425,7 +425,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command) ...@@ -425,7 +425,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \ { \
struct ads7846 *ts = dev_get_drvdata(dev); \ struct ads7846 *ts = dev_get_drvdata(dev); \
ssize_t v = ads7846_read12_ser(dev, \ ssize_t v = ads7846_read12_ser(&ts->spi->dev, \
READ_12BIT_SER(var)); \ READ_12BIT_SER(var)); \
if (v < 0) \ if (v < 0) \
return v; \ return v; \
......
...@@ -23,6 +23,7 @@ struct serio { ...@@ -23,6 +23,7 @@ struct serio {
char name[32]; char name[32];
char phys[32]; char phys[32];
char firmware_id[128];
bool manual_bind; bool manual_bind;
......
...@@ -164,6 +164,7 @@ struct input_keymap_entry { ...@@ -164,6 +164,7 @@ struct input_keymap_entry {
#define INPUT_PROP_DIRECT 0x01 /* direct input devices */ #define INPUT_PROP_DIRECT 0x01 /* direct input devices */
#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */ #define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */ #define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_MAX 0x1f #define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment