Commit 1a9e9e7c authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Vojtech Pavlik

Input: synaptics driver cleanup

       - pack all button data in 2 bytes instead of 48
       - adjust the way we extract button data
       - query extended capabilities if SYN_EXT_CAP_REQUESTS >= 1
         (was == 1) according to Synaptics' addendum to the interfacing
         guide
       - do not announce or report BTN_BACK/BTN_FORWARD unless touchpad
         has SYN_CAP_FOUR_BUTTON in its capability flags
parent 85e0dd48
...@@ -118,17 +118,31 @@ static int synaptics_capability(struct psmouse *psmouse) ...@@ -118,17 +118,31 @@ static int synaptics_capability(struct psmouse *psmouse)
if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
return -1; return -1;
priv->capabilities = (cap[0]<<16) | (cap[1]<<8) | cap[2]; priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
priv->ext_cap = 0; priv->ext_cap = 0;
if (!SYN_CAP_VALID(priv->capabilities)) if (!SYN_CAP_VALID(priv->capabilities))
return -1; return -1;
if (SYN_EXT_CAP_REQUESTS(priv->capabilities)) { /*
* Unless capExtended is set the rest of the flags should be ignored
*/
if (!SYN_CAP_EXTENDED(priv->capabilities))
priv->capabilities = 0;
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
printk(KERN_ERR "Synaptics claims to have extended capabilities," printk(KERN_ERR "Synaptics claims to have extended capabilities,"
" but I'm not able to read them."); " but I'm not able to read them.");
} else } else {
priv->ext_cap = (cap[0]<<16) | (cap[1]<<8) | cap[2]; priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
/*
* if nExtBtn is greater than 8 it should be considered
* invalid and treated as 0
*/
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
priv->ext_cap &= 0xff0fff;
}
} }
return 0; return 0;
} }
...@@ -167,11 +181,10 @@ static void print_ident(struct synaptics_data *priv) ...@@ -167,11 +181,10 @@ static void print_ident(struct synaptics_data *priv)
if (SYN_CAP_EXTENDED(priv->capabilities)) { if (SYN_CAP_EXTENDED(priv->capabilities)) {
printk(KERN_INFO " Touchpad has extended capability bits\n"); printk(KERN_INFO " Touchpad has extended capability bits\n");
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) <= 8)
printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n", printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n",
(int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))); (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)));
else if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
printk(KERN_INFO " -> four buttons\n"); printk(KERN_INFO " -> four buttons\n");
if (SYN_CAP_MULTIFINGER(priv->capabilities)) if (SYN_CAP_MULTIFINGER(priv->capabilities))
printk(KERN_INFO " -> multifinger detection\n"); printk(KERN_INFO " -> multifinger detection\n");
...@@ -312,6 +325,8 @@ static inline void set_abs_params(struct input_dev *dev, int axis, int min, int ...@@ -312,6 +325,8 @@ static inline void set_abs_params(struct input_dev *dev, int axis, int min, int
static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
{ {
int i;
set_bit(EV_ABS, dev->evbit); set_bit(EV_ABS, dev->evbit);
set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
...@@ -326,32 +341,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) ...@@ -326,32 +341,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
set_bit(BTN_LEFT, dev->keybit); set_bit(BTN_LEFT, dev->keybit);
set_bit(BTN_RIGHT, dev->keybit); set_bit(BTN_RIGHT, dev->keybit);
set_bit(BTN_FORWARD, dev->keybit);
set_bit(BTN_BACK, dev->keybit); if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) { set_bit(BTN_FORWARD, dev->keybit);
switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { set_bit(BTN_BACK, dev->keybit);
default:
/*
* if nExtBtn is greater than 8 it should be considered
* invalid and treated as 0
*/
break;
case 8:
set_bit(BTN_7, dev->keybit);
set_bit(BTN_6, dev->keybit);
case 6:
set_bit(BTN_5, dev->keybit);
set_bit(BTN_4, dev->keybit);
case 4:
set_bit(BTN_3, dev->keybit);
set_bit(BTN_2, dev->keybit);
case 2:
set_bit(BTN_1, dev->keybit);
set_bit(BTN_0, dev->keybit);
break;
}
} }
for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
set_bit(BTN_0 + i, dev->keybit);
clear_bit(EV_REL, dev->evbit); clear_bit(EV_REL, dev->evbit);
clear_bit(REL_X, dev->relbit); clear_bit(REL_X, dev->relbit);
clear_bit(REL_Y, dev->relbit); clear_bit(REL_Y, dev->relbit);
...@@ -385,8 +383,8 @@ static int synaptics_reconnect(struct psmouse *psmouse) ...@@ -385,8 +383,8 @@ static int synaptics_reconnect(struct psmouse *psmouse)
if (old_priv.identity != priv->identity || if (old_priv.identity != priv->identity ||
old_priv.model_id != priv->model_id || old_priv.model_id != priv->model_id ||
old_priv.capabilities != priv->capabilities || old_priv.capabilities != priv->capabilities ||
old_priv.ext_cap != priv->ext_cap) old_priv.ext_cap != priv->ext_cap)
return -1; return -1;
if (synaptics_set_mode(psmouse, 0)) { if (synaptics_set_mode(psmouse, 0)) {
printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
...@@ -432,8 +430,8 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -432,8 +430,8 @@ int synaptics_init(struct psmouse *psmouse)
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities)) if (SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse); synaptics_pt_create(psmouse);
print_ident(priv); print_ident(priv);
set_input_params(&psmouse->dev, priv); set_input_params(&psmouse->dev, priv);
...@@ -471,17 +469,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data ...@@ -471,17 +469,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
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_EXTENDED(priv->capabilities) &&
(SYN_CAP_FOUR_BUTTON(priv->capabilities))) { if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
hw->up = ((buf[3] & 0x01)) ? 1 : 0; hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
if (hw->left) hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
hw->up = !hw->up;
hw->down = ((buf[3] & 0x02)) ? 1 : 0;
if (hw->right)
hw->down = !hw->down;
} }
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
((buf[3] & 2) ? !hw->right : hw->right)) { ((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) {
default: default:
/* /*
...@@ -490,17 +485,17 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data ...@@ -490,17 +485,17 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
*/ */
break; break;
case 8: case 8:
hw->b7 = ((buf[5] & 0x08)) ? 1 : 0; hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
hw->b6 = ((buf[4] & 0x08)) ? 1 : 0; hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
case 6: case 6:
hw->b5 = ((buf[5] & 0x04)) ? 1 : 0; hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
hw->b4 = ((buf[4] & 0x04)) ? 1 : 0; hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
case 4: case 4:
hw->b3 = ((buf[5] & 0x02)) ? 1 : 0; hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
hw->b2 = ((buf[4] & 0x02)) ? 1 : 0; hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
case 2: case 2:
hw->b1 = ((buf[5] & 0x01)) ? 1 : 0; hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
hw->b0 = ((buf[4] & 0x01)) ? 1 : 0; hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
} }
} }
} else { } else {
...@@ -525,6 +520,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) ...@@ -525,6 +520,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct synaptics_hw_state hw; struct synaptics_hw_state hw;
int num_fingers; int num_fingers;
int finger_width; int finger_width;
int i;
synaptics_parse_hw_state(psmouse->packet, priv, &hw); synaptics_parse_hw_state(psmouse->packet, priv, &hw);
...@@ -570,32 +566,17 @@ static void synaptics_process_packet(struct psmouse *psmouse) ...@@ -570,32 +566,17 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
input_report_key(dev, BTN_LEFT, hw.left); input_report_key(dev, BTN_LEFT, hw.left);
input_report_key(dev, BTN_RIGHT, hw.right); input_report_key(dev, BTN_RIGHT, hw.right);
input_report_key(dev, BTN_FORWARD, hw.up);
input_report_key(dev, BTN_BACK, hw.down); if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) input_report_key(dev, BTN_FORWARD, hw.up);
switch(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { input_report_key(dev, BTN_BACK, hw.down);
default: }
/*
* if nExtBtn is greater than 8 it should be considered for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
* invalid and treated as 0 input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
*/
break;
case 8:
input_report_key(dev, BTN_7, hw.b7);
input_report_key(dev, BTN_6, hw.b6);
case 6:
input_report_key(dev, BTN_5, hw.b5);
input_report_key(dev, BTN_4, hw.b4);
case 4:
input_report_key(dev, BTN_3, hw.b3);
input_report_key(dev, BTN_2, hw.b2);
case 2:
input_report_key(dev, BTN_1, hw.b1);
input_report_key(dev, BTN_0, hw.b0);
break;
}
input_sync(dev); input_sync(dev);
} }
......
...@@ -50,7 +50,7 @@ extern void synaptics_reset(struct psmouse *psmouse); ...@@ -50,7 +50,7 @@ extern void synaptics_reset(struct psmouse *psmouse);
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1) #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
/* synaptics modes query bits */ /* synaptics modes query bits */
...@@ -86,18 +86,11 @@ struct synaptics_hw_state { ...@@ -86,18 +86,11 @@ struct synaptics_hw_state {
int y; int y;
int z; int z;
int w; int w;
int left; unsigned int left:1;
int right; unsigned int right:1;
int up; unsigned int up:1;
int down; unsigned int down:1;
int b0; unsigned char ext_buttons;
int b1;
int b2;
int b3;
int b4;
int b5;
int b6;
int b7;
}; };
struct synaptics_data { struct synaptics_data {
......
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