25-akpm/drivers/input/mouse/synaptics.c | 90 ++++++++++++++++++++++++++++---- 25-akpm/drivers/input/mouse/synaptics.h | 12 ++++ 2 files changed, 92 insertions(+), 10 deletions(-) diff -puN drivers/input/mouse/synaptics.c~p00003_synaptics-multi-button drivers/input/mouse/synaptics.c --- 25/drivers/input/mouse/synaptics.c~p00003_synaptics-multi-button Tue Jul 29 14:57:02 2003 +++ 25-akpm/drivers/input/mouse/synaptics.c Tue Jul 29 14:57:02 2003 @@ -106,16 +106,25 @@ static int synaptics_model_id(struct psm * Read the capability-bits from the touchpad * see also the SYN_CAP_* macros */ -static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability) +static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability, unsigned long int *ext_cap) { unsigned char cap[3]; if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) return -1; *capability = (cap[0]<<16) | (cap[1]<<8) | cap[2]; - if (SYN_CAP_VALID(*capability)) - return 0; - return -1; + *ext_cap = 0; + if (!SYN_CAP_VALID(*capability)) + return -1; + + if (SYN_EXT_CAP_REQUESTS(*capability)) { + if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { + printk(KERN_ERR "Synaptics claims to have extended capabilities," + " but I'm not able to read them."); + } else + *ext_cap = (cap[0]<<16) | (cap[1]<<8) | cap[2]; + } + return 0; } /* @@ -146,7 +155,6 @@ static void print_ident(struct synaptics printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity)); printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity)); - if (SYN_MODEL_ROT180(priv->model_id)) printk(KERN_INFO " 180 degree mounted touchpad\n"); if (SYN_MODEL_PORTRAIT(priv->model_id)) @@ -159,7 +167,10 @@ static void print_ident(struct synaptics if (SYN_CAP_EXTENDED(priv->capabilities)) { printk(KERN_INFO " Touchpad has extended capability bits\n"); - if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) + printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n", + (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))); + else if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) printk(KERN_INFO " -> four buttons\n"); if (SYN_CAP_MULTIFINGER(priv->capabilities)) printk(KERN_INFO " -> multifinger detection\n"); @@ -180,7 +191,7 @@ static int query_hardware(struct psmouse return -1; if (synaptics_model_id(psmouse, &priv->model_id)) return -1; - if (synaptics_capability(psmouse, &priv->capabilities)) + if (synaptics_capability(psmouse, &priv->capabilities, &priv->ext_cap)) return -1; if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE | @@ -243,7 +254,24 @@ int synaptics_init(struct psmouse *psmou set_bit(BTN_RIGHT, psmouse->dev.keybit); set_bit(BTN_FORWARD, psmouse->dev.keybit); set_bit(BTN_BACK, psmouse->dev.keybit); - + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) + switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { + default: + printk(KERN_ERR "This touchpad reports more than 8 multi-buttons, don't know how to handle.\n"); + case 8: + set_bit(BTN_7, psmouse->dev.keybit); + set_bit(BTN_6, psmouse->dev.keybit); + case 6: + set_bit(BTN_5, psmouse->dev.keybit); + set_bit(BTN_4, psmouse->dev.keybit); + case 4: + set_bit(BTN_3, psmouse->dev.keybit); + set_bit(BTN_2, psmouse->dev.keybit); + case 2: + set_bit(BTN_1, psmouse->dev.keybit); + set_bit(BTN_0, psmouse->dev.keybit); + break; + } clear_bit(EV_REL, psmouse->dev.evbit); clear_bit(REL_X, psmouse->dev.relbit); clear_bit(REL_Y, psmouse->dev.relbit); @@ -289,7 +317,14 @@ static void synaptics_parse_hw_state(str hw->right = (buf[0] & 0x2) ? 1 : 0; hw->up = 0; hw->down = 0; - + hw->b0 = 0; + hw->b1 = 0; + hw->b2 = 0; + hw->b3 = 0; + hw->b4 = 0; + hw->b5 = 0; + hw->b6 = 0; + hw->b7 = 0; if (SYN_CAP_EXTENDED(priv->capabilities) && (SYN_CAP_FOUR_BUTTON(priv->capabilities))) { hw->up = ((buf[3] & 0x01)) ? 1 : 0; @@ -299,6 +334,24 @@ static void synaptics_parse_hw_state(str if (hw->right) hw->down = !hw->down; } + if (buf[3] == 0xC2 && SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) { + switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { + default: + ; /* we did comment while initialising... */ + case 8: + hw->b7 = ((buf[5] & 0x08)) ? 1 : 0; + hw->b6 = ((buf[4] & 0x08)) ? 1 : 0; + case 6: + hw->b5 = ((buf[5] & 0x04)) ? 1 : 0; + hw->b4 = ((buf[4] & 0x04)) ? 1 : 0; + case 4: + hw->b3 = ((buf[5] & 0x02)) ? 1 : 0; + hw->b2 = ((buf[4] & 0x02)) ? 1 : 0; + case 2: + hw->b1 = ((buf[5] & 0x01)) ? 1 : 0; + hw->b0 = ((buf[4] & 0x01)) ? 1 : 0; + } + } } /* @@ -350,7 +403,24 @@ static void synaptics_process_packet(str 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_MULTI_BUTTON_NO(priv->ext_cap)) + switch(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { + default: + ; /* we did comment while initialising... */ + 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); } diff -puN drivers/input/mouse/synaptics.h~p00003_synaptics-multi-button drivers/input/mouse/synaptics.h --- 25/drivers/input/mouse/synaptics.h~p00003_synaptics-multi-button Tue Jul 29 14:57:02 2003 +++ 25-akpm/drivers/input/mouse/synaptics.h Tue Jul 29 14:57:02 2003 @@ -22,6 +22,7 @@ extern void synaptics_disconnect(struct #define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06 #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 #define SYN_QUE_RESOLUTION 0x08 +#define SYN_QUE_EXT_CAPAB 0x09 /* synatics modes */ #define SYN_BIT_ABSOLUTE_MODE (1 << 7) @@ -47,6 +48,8 @@ extern void synaptics_disconnect(struct #define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) +#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1) +#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) /* synaptics modes query bits */ #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) @@ -75,12 +78,21 @@ struct synaptics_hw_state { int right; int up; int down; + int b0; + int b1; + int b2; + int b3; + int b4; + int b5; + int b6; + int b7; }; struct synaptics_data { /* Data read from the touchpad */ unsigned long int model_id; /* Model-ID */ unsigned long int capabilities; /* Capabilities */ + unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int identity; /* Identification */ /* Data for normal processing */ _