Commit c8c16e36 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:
 "An update to Synaptics PS/2 driver to handle "ForcePads" (currently
  found in HP EliteBook 1040 laptops), a change for Elan PS/2 driver to
  detect newer touchpads, bunch of devices get annotated as Trackpoint
  and/or Pointer to help userspace classify and handle them, plus
  assorted driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: serport - add compat handling for SPIOCSTYPE ioctl
  Input: atmel_mxt_ts - fix double free of input device
  Input: synaptics - add support for ForcePads
  Input: matrix_keypad - use request_any_context_irq()
  Input: atmel_mxt_ts - downgrade warning about empty interrupts
  Input: wm971x - fix typo in module parameter description
  Input: cap1106 - fix register definition
  Input: add missing POINTER / DIRECT properties to a bunch of drivers
  Input: add INPUT_PROP_POINTING_STICK property
  Input: elantech - fix detection of touchpad on ASUS s301l
parents 584f1ada a80d8b02
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
#define CAP1106_REG_SENSOR_CONFIG 0x22 #define CAP1106_REG_SENSOR_CONFIG 0x22
#define CAP1106_REG_SENSOR_CONFIG2 0x23 #define CAP1106_REG_SENSOR_CONFIG2 0x23
#define CAP1106_REG_SAMPLING_CONFIG 0x24 #define CAP1106_REG_SAMPLING_CONFIG 0x24
#define CAP1106_REG_CALIBRATION 0x25 #define CAP1106_REG_CALIBRATION 0x26
#define CAP1106_REG_INT_ENABLE 0x26 #define CAP1106_REG_INT_ENABLE 0x27
#define CAP1106_REG_REPEAT_RATE 0x28 #define CAP1106_REG_REPEAT_RATE 0x28
#define CAP1106_REG_MT_CONFIG 0x2a #define CAP1106_REG_MT_CONFIG 0x2a
#define CAP1106_REG_MT_PATTERN_CONFIG 0x2b #define CAP1106_REG_MT_PATTERN_CONFIG 0x2b
......
...@@ -332,23 +332,24 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev, ...@@ -332,23 +332,24 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev,
} }
if (pdata->clustered_irq > 0) { if (pdata->clustered_irq > 0) {
err = request_irq(pdata->clustered_irq, err = request_any_context_irq(pdata->clustered_irq,
matrix_keypad_interrupt, matrix_keypad_interrupt,
pdata->clustered_irq_flags, pdata->clustered_irq_flags,
"matrix-keypad", keypad); "matrix-keypad", keypad);
if (err) { if (err < 0) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Unable to acquire clustered interrupt\n"); "Unable to acquire clustered interrupt\n");
goto err_free_rows; goto err_free_rows;
} }
} else { } else {
for (i = 0; i < pdata->num_row_gpios; i++) { for (i = 0; i < pdata->num_row_gpios; i++) {
err = request_irq(gpio_to_irq(pdata->row_gpios[i]), err = request_any_context_irq(
gpio_to_irq(pdata->row_gpios[i]),
matrix_keypad_interrupt, matrix_keypad_interrupt,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING, IRQF_TRIGGER_FALLING,
"matrix-keypad", keypad); "matrix-keypad", keypad);
if (err) { if (err < 0) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Unable to acquire interrupt for GPIO line %i\n", "Unable to acquire interrupt for GPIO line %i\n",
pdata->row_gpios[i]); pdata->row_gpios[i]);
......
...@@ -2373,6 +2373,10 @@ int alps_init(struct psmouse *psmouse) ...@@ -2373,6 +2373,10 @@ int alps_init(struct psmouse *psmouse)
dev2->keybit[BIT_WORD(BTN_LEFT)] = dev2->keybit[BIT_WORD(BTN_LEFT)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
__set_bit(INPUT_PROP_POINTER, dev2->propbit);
if (priv->flags & ALPS_DUALPOINT)
__set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
if (input_register_device(priv->dev2)) if (input_register_device(priv->dev2))
goto init_fail; goto init_fail;
......
...@@ -1331,6 +1331,13 @@ static bool elantech_is_signature_valid(const unsigned char *param) ...@@ -1331,6 +1331,13 @@ static bool elantech_is_signature_valid(const unsigned char *param)
if (param[1] == 0) if (param[1] == 0)
return true; return true;
/*
* Some models have a revision higher then 20. Meaning param[2] may
* be 10 or 20, skip the rates check for these.
*/
if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40)
return true;
for (i = 0; i < ARRAY_SIZE(rates); i++) for (i = 0; i < ARRAY_SIZE(rates); i++)
if (param[2] == rates[i]) if (param[2] == rates[i])
return false; return false;
...@@ -1607,6 +1614,10 @@ int elantech_init(struct psmouse *psmouse) ...@@ -1607,6 +1614,10 @@ int elantech_init(struct psmouse *psmouse)
tp_dev->keybit[BIT_WORD(BTN_LEFT)] = tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
BIT_MASK(BTN_RIGHT); BIT_MASK(BTN_RIGHT);
__set_bit(INPUT_PROP_POINTER, tp_dev->propbit);
__set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit);
error = input_register_device(etd->tp_dev); error = input_register_device(etd->tp_dev);
if (error < 0) if (error < 0)
goto init_fail_tp_reg; goto init_fail_tp_reg;
......
...@@ -670,6 +670,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse) ...@@ -670,6 +670,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse)
__set_bit(REL_X, input_dev->relbit); __set_bit(REL_X, input_dev->relbit);
__set_bit(REL_Y, input_dev->relbit); __set_bit(REL_Y, input_dev->relbit);
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
psmouse->set_rate = psmouse_set_rate; psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution; psmouse->set_resolution = psmouse_set_resolution;
psmouse->poll = psmouse_poll; psmouse->poll = psmouse_poll;
......
...@@ -629,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], ...@@ -629,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
((buf[0] & 0x04) >> 1) | ((buf[0] & 0x04) >> 1) |
((buf[3] & 0x04) >> 2)); ((buf[3] & 0x04) >> 2));
if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
hw->w == 2) {
synaptics_parse_agm(buf, priv, hw);
return 1;
}
hw->x = (((buf[3] & 0x10) << 8) |
((buf[1] & 0x0f) << 8) |
buf[4]);
hw->y = (((buf[3] & 0x20) << 7) |
((buf[1] & 0xf0) << 4) |
buf[5]);
hw->z = buf[2];
hw->left = (buf[0] & 0x01) ? 1 : 0; hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0;
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) {
/*
* ForcePads, like Clickpads, use middle button
* bits to report primary button clicks.
* Unfortunately they report primary button not
* only when user presses on the pad above certain
* threshold, but also when there are more than one
* finger on the touchpad, which interferes with
* out multi-finger gestures.
*/
if (hw->z == 0) {
/* No contacts */
priv->press = priv->report_press = false;
} else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
/*
* Single-finger touch with pressure above
* the threshold. If pressure stays long
* enough, we'll start reporting primary
* button. We rely on the device continuing
* sending data even if finger does not
* move.
*/
if (!priv->press) {
priv->press_start = jiffies;
priv->press = true;
} else if (time_after(jiffies,
priv->press_start +
msecs_to_jiffies(50))) {
priv->report_press = true;
}
} else {
priv->press = false;
}
hw->left = priv->report_press;
} else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
/* /*
* Clickpad's button is transmitted as middle button, * Clickpad's button is transmitted as middle button,
* however, since it is primary button, we will report * however, since it is primary button, we will report
...@@ -651,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], ...@@ -651,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
} }
if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
hw->w == 2) {
synaptics_parse_agm(buf, priv, hw);
return 1;
}
hw->x = (((buf[3] & 0x10) << 8) |
((buf[1] & 0x0f) << 8) |
buf[4]);
hw->y = (((buf[3] & 0x20) << 7) |
((buf[1] & 0xf0) << 4) |
buf[5]);
hw->z = buf[2];
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
((buf[0] ^ buf[3]) & 0x02)) { ((buf[0] ^ buf[3]) & 0x02)) {
switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
......
...@@ -78,6 +78,11 @@ ...@@ -78,6 +78,11 @@
* 2 0x08 image sensor image sensor tracks 5 fingers, but only * 2 0x08 image sensor image sensor tracks 5 fingers, but only
* reports 2. * reports 2.
* 2 0x20 report min query 0x0f gives min coord reported * 2 0x20 report min query 0x0f gives min coord reported
* 2 0x80 forcepad forcepad is a variant of clickpad that
* does not have physical buttons but rather
* uses pressure above certain threshold to
* report primary clicks. Forcepads also have
* clickpad bit set.
*/ */
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */
#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */
...@@ -86,6 +91,7 @@ ...@@ -86,6 +91,7 @@
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)
#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400)
#define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800)
#define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000)
/* synaptics modes query bits */ /* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
...@@ -177,6 +183,11 @@ struct synaptics_data { ...@@ -177,6 +183,11 @@ struct synaptics_data {
*/ */
struct synaptics_hw_state agm; struct synaptics_hw_state agm;
bool agm_pending; /* new AGM packet received */ bool agm_pending; /* new AGM packet received */
/* ForcePad handling */
unsigned long press_start;
bool press;
bool report_press;
}; };
void synaptics_module_init(void); void synaptics_module_init(void);
......
...@@ -387,6 +387,7 @@ static int synusb_probe(struct usb_interface *intf, ...@@ -387,6 +387,7 @@ static int synusb_probe(struct usb_interface *intf,
__set_bit(EV_REL, input_dev->evbit); __set_bit(EV_REL, input_dev->evbit);
__set_bit(REL_X, input_dev->relbit); __set_bit(REL_X, input_dev->relbit);
__set_bit(REL_Y, input_dev->relbit); __set_bit(REL_Y, input_dev->relbit);
__set_bit(INPUT_PROP_POINTING_STICK, input_dev->propbit);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0);
} else { } else {
input_set_abs_params(input_dev, ABS_X, input_set_abs_params(input_dev, ABS_X,
...@@ -401,6 +402,11 @@ static int synusb_probe(struct usb_interface *intf, ...@@ -401,6 +402,11 @@ static int synusb_probe(struct usb_interface *intf,
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
} }
if (synusb->flags & SYNUSB_TOUCHSCREEN)
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
else
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
__set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit);
__set_bit(BTN_RIGHT, input_dev->keybit); __set_bit(BTN_RIGHT, input_dev->keybit);
__set_bit(BTN_MIDDLE, input_dev->keybit); __set_bit(BTN_MIDDLE, input_dev->keybit);
......
...@@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) ...@@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
if ((button_info & 0x0f) >= 3) if ((button_info & 0x0f) >= 3)
__set_bit(BTN_MIDDLE, psmouse->dev->keybit); __set_bit(BTN_MIDDLE, psmouse->dev->keybit);
__set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit);
__set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit);
trackpoint_defaults(psmouse->private); trackpoint_defaults(psmouse->private);
error = trackpoint_power_on_reset(&psmouse->ps2dev); error = trackpoint_power_on_reset(&psmouse->ps2dev);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/compat.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Input device TTY line discipline"); MODULE_DESCRIPTION("Input device TTY line discipline");
...@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u ...@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
return 0; return 0;
} }
static void serport_set_type(struct tty_struct *tty, unsigned long type)
{
struct serport *serport = tty->disc_data;
serport->id.proto = type & 0x000000ff;
serport->id.id = (type & 0x0000ff00) >> 8;
serport->id.extra = (type & 0x00ff0000) >> 16;
}
/* /*
* serport_ldisc_ioctl() allows to set the port protocol, and device ID * serport_ldisc_ioctl() allows to set the port protocol, and device ID
*/ */
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{ {
struct serport *serport = (struct serport*) tty->disc_data;
unsigned long type;
if (cmd == SPIOCSTYPE) { if (cmd == SPIOCSTYPE) {
unsigned long type;
if (get_user(type, (unsigned long __user *) arg)) if (get_user(type, (unsigned long __user *) arg))
return -EFAULT; return -EFAULT;
serport->id.proto = type & 0x000000ff; serport_set_type(tty, type);
serport->id.id = (type & 0x0000ff00) >> 8; return 0;
serport->id.extra = (type & 0x00ff0000) >> 16; }
return -EINVAL;
}
#ifdef CONFIG_COMPAT
#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
struct file *file,
unsigned int cmd, unsigned long arg)
{
if (cmd == COMPAT_SPIOCSTYPE) {
void __user *uarg = compat_ptr(arg);
compat_ulong_t compat_type;
if (get_user(compat_type, (compat_ulong_t __user *)uarg))
return -EFAULT;
serport_set_type(tty, compat_type);
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
} }
#endif
static void serport_ldisc_write_wakeup(struct tty_struct * tty) static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{ {
...@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = { ...@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = {
.close = serport_ldisc_close, .close = serport_ldisc_close,
.read = serport_ldisc_read, .read = serport_ldisc_read,
.ioctl = serport_ldisc_ioctl, .ioctl = serport_ldisc_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = serport_ldisc_compat_ioctl,
#endif
.receive_buf = serport_ldisc_receive, .receive_buf = serport_ldisc_receive,
.write_wakeup = serport_ldisc_write_wakeup .write_wakeup = serport_ldisc_write_wakeup
}; };
......
...@@ -837,7 +837,12 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) ...@@ -837,7 +837,12 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
count = data->msg_buf[0]; count = data->msg_buf[0];
if (count == 0) { if (count == 0) {
dev_warn(dev, "Interrupt triggered but zero messages\n"); /*
* This condition is caused by the CHG line being configured
* in Mode 0. It results in unnecessary I2C operations but it
* is benign.
*/
dev_dbg(dev, "Interrupt triggered but zero messages\n");
return IRQ_NONE; return IRQ_NONE;
} else if (count > data->max_reportid) { } else if (count > data->max_reportid) {
dev_err(dev, "T44 count %d exceeded max report id\n", count); dev_err(dev, "T44 count %d exceeded max report id\n", count);
...@@ -1374,11 +1379,16 @@ static int mxt_get_info(struct mxt_data *data) ...@@ -1374,11 +1379,16 @@ static int mxt_get_info(struct mxt_data *data)
return 0; return 0;
} }
static void mxt_free_object_table(struct mxt_data *data) static void mxt_free_input_device(struct mxt_data *data)
{ {
input_unregister_device(data->input_dev); if (data->input_dev) {
data->input_dev = NULL; input_unregister_device(data->input_dev);
data->input_dev = NULL;
}
}
static void mxt_free_object_table(struct mxt_data *data)
{
kfree(data->object_table); kfree(data->object_table);
data->object_table = NULL; data->object_table = NULL;
kfree(data->msg_buf); kfree(data->msg_buf);
...@@ -1957,11 +1967,13 @@ static int mxt_load_fw(struct device *dev, const char *fn) ...@@ -1957,11 +1967,13 @@ static int mxt_load_fw(struct device *dev, const char *fn)
ret = mxt_lookup_bootloader_address(data, 0); ret = mxt_lookup_bootloader_address(data, 0);
if (ret) if (ret)
goto release_firmware; goto release_firmware;
mxt_free_input_device(data);
mxt_free_object_table(data);
} else { } else {
enable_irq(data->irq); enable_irq(data->irq);
} }
mxt_free_object_table(data);
reinit_completion(&data->bl_completion); reinit_completion(&data->bl_completion);
ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
...@@ -2210,6 +2222,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -2210,6 +2222,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
return 0; return 0;
err_free_object: err_free_object:
mxt_free_input_device(data);
mxt_free_object_table(data); mxt_free_object_table(data);
err_free_irq: err_free_irq:
free_irq(client->irq, data); free_irq(client->irq, data);
...@@ -2224,7 +2237,7 @@ static int mxt_remove(struct i2c_client *client) ...@@ -2224,7 +2237,7 @@ static int mxt_remove(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
free_irq(data->irq, data); free_irq(data->irq, data);
input_unregister_device(data->input_dev); mxt_free_input_device(data);
mxt_free_object_table(data); mxt_free_object_table(data);
kfree(data); kfree(data);
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
*/ */
static int rpu = 8; static int rpu = 8;
module_param(rpu, int, 0); module_param(rpu, int, 0);
MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
/* /*
* Set current used for pressure measurement. * Set current used for pressure measurement.
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
*/ */
static int rpu = 8; static int rpu = 8;
module_param(rpu, int, 0); module_param(rpu, int, 0);
MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
/* /*
* Set current used for pressure measurement. * Set current used for pressure measurement.
......
...@@ -165,6 +165,7 @@ struct input_keymap_entry { ...@@ -165,6 +165,7 @@ struct input_keymap_entry {
#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_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
#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