@@ -328,6 +328,24 @@ static void synaptics_pt_create(struct psmouse *psmouse)
* Functions to interpret the absolute mode packets
****************************************************************************/
+static void synaptics_check_clickpad(struct psmouse *psmouse)
+{
+ struct synaptics_data *priv = psmouse->private;
+ unsigned char ncap[3];
+
+ /* check the new capability bits only on known working devices */
+ if (SYN_CAP_PRODUCT_ID(priv->ext_cap) != 0xe4)
+ return;
+ if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB2, ncap))
+ return;
+ printk(KERN_INFO "Synaptics: newcap: %02x:%02x:%02x\n",
+ ncap[0], ncap[1], ncap[2]);
+ priv->clickpad = ((ncap[0] & 0x10) >> 4) | ((ncap[1] & 0x01) << 1);
+ if (priv->clickpad)
+ printk(KERN_INFO "Synaptics: Clickpad device detected: %d\n",
+ priv->clickpad);
+}
+
static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
{
memset(hw, 0, sizeof(struct synaptics_hw_state));
@@ -354,6 +372,13 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
hw->scroll = (signed char)(buf[1]);
}
+ if (priv->clickpad) {
+ /* clickpad reports only the middle button, report
+ * it as the left button
+ */
+ hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
+ }
+
if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
@@ -593,6 +618,11 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
dev->absres[ABS_X] = priv->x_res;
dev->absres[ABS_Y] = priv->y_res;
+
+ if (priv->clickpad) {
+ __clear_bit(BTN_RIGHT, dev->keybit); /* only left-button */
+ __clear_bit(BTN_MIDDLE, dev->keybit);
+ }
}
static void synaptics_disconnect(struct psmouse *psmouse)
@@ -702,6 +732,8 @@ int synaptics_init(struct psmouse *psmouse)
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
priv->model_id, priv->capabilities, priv->ext_cap);
+ synaptics_check_clickpad(psmouse);
+
set_input_params(psmouse->dev, priv);
/*
@@ -18,6 +18,7 @@
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08
#define SYN_QUE_EXT_CAPAB 0x09
+#define SYN_QUE_EXT_CAPAB2 0x0c
/* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
@@ -48,6 +49,7 @@
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
+#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
@@ -103,6 +105,8 @@ struct synaptics_data {
unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */
int scroll;
+
+ unsigned char clickpad;
};
void synaptics_module_init(void);