diff options
| -rw-r--r-- | drivers/input/mouse/lifebook.c | 78 |
1 files changed, 65 insertions, 13 deletions
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 28d9770f5eb2..6ac7177e21cb 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
| @@ -28,6 +28,14 @@ static int lifebook_set_serio_phys(struct dmi_system_id *d) | |||
| 28 | return 0; | 28 | return 0; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | static unsigned char lifebook_use_6byte_proto; | ||
| 32 | |||
| 33 | static int lifebook_set_6byte_proto(struct dmi_system_id *d) | ||
| 34 | { | ||
| 35 | lifebook_use_6byte_proto = 1; | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 31 | static struct dmi_system_id lifebook_dmi_table[] = { | 39 | static struct dmi_system_id lifebook_dmi_table[] = { |
| 32 | { | 40 | { |
| 33 | .ident = "FLORA-ie 55mi", | 41 | .ident = "FLORA-ie 55mi", |
| @@ -68,6 +76,14 @@ static struct dmi_system_id lifebook_dmi_table[] = { | |||
| 68 | .driver_data = "isa0060/serio3", | 76 | .driver_data = "isa0060/serio3", |
| 69 | }, | 77 | }, |
| 70 | { | 78 | { |
| 79 | .ident = "Panasonic CF-28", | ||
| 80 | .matches = { | ||
| 81 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), | ||
| 82 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"), | ||
| 83 | }, | ||
| 84 | .callback = lifebook_set_6byte_proto, | ||
| 85 | }, | ||
| 86 | { | ||
| 71 | .ident = "Lifebook B142", | 87 | .ident = "Lifebook B142", |
| 72 | .matches = { | 88 | .matches = { |
| 73 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), | 89 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), |
| @@ -78,23 +94,53 @@ static struct dmi_system_id lifebook_dmi_table[] = { | |||
| 78 | 94 | ||
| 79 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | 95 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) |
| 80 | { | 96 | { |
| 81 | unsigned char *packet = psmouse->packet; | ||
| 82 | struct input_dev *dev = psmouse->dev; | 97 | struct input_dev *dev = psmouse->dev; |
| 98 | unsigned char *packet = psmouse->packet; | ||
| 99 | int relative_packet = packet[0] & 0x08; | ||
| 83 | 100 | ||
| 84 | if (psmouse->pktcnt != 3) | 101 | if (relative_packet || !lifebook_use_6byte_proto) { |
| 85 | return PSMOUSE_GOOD_DATA; | 102 | if (psmouse->pktcnt != 3) |
| 86 | 103 | return PSMOUSE_GOOD_DATA; | |
| 87 | /* calculate X and Y */ | ||
| 88 | if ((packet[0] & 0x08) == 0x00) { | ||
| 89 | input_report_abs(dev, ABS_X, | ||
| 90 | (packet[1] | ((packet[0] & 0x30) << 4))); | ||
| 91 | input_report_abs(dev, ABS_Y, | ||
| 92 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | ||
| 93 | } else { | 104 | } else { |
| 105 | switch (psmouse->pktcnt) { | ||
| 106 | case 1: | ||
| 107 | return (packet[0] & 0xf8) == 0x00 ? | ||
| 108 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | ||
| 109 | case 2: | ||
| 110 | return PSMOUSE_GOOD_DATA; | ||
| 111 | case 3: | ||
| 112 | return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ? | ||
| 113 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | ||
| 114 | case 4: | ||
| 115 | return (packet[3] & 0xf8) == 0xc0 ? | ||
| 116 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | ||
| 117 | case 5: | ||
| 118 | return (packet[4] & 0xc0) == (packet[2] & 0xc0) ? | ||
| 119 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | ||
| 120 | case 6: | ||
| 121 | if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0)) | ||
| 122 | return PSMOUSE_BAD_DATA; | ||
| 123 | if ((packet[5] & 0xc0) != (packet[1] & 0xc0)) | ||
| 124 | return PSMOUSE_BAD_DATA; | ||
| 125 | break; /* report data */ | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | if (relative_packet) { | ||
| 94 | input_report_rel(dev, REL_X, | 130 | input_report_rel(dev, REL_X, |
| 95 | ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); | 131 | ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); |
| 96 | input_report_rel(dev, REL_Y, | 132 | input_report_rel(dev, REL_Y, |
| 97 | -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); | 133 | -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); |
| 134 | } else if (lifebook_use_6byte_proto) { | ||
| 135 | input_report_abs(dev, ABS_X, | ||
| 136 | ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); | ||
| 137 | input_report_abs(dev, ABS_Y, | ||
| 138 | 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f))); | ||
| 139 | } else { | ||
| 140 | input_report_abs(dev, ABS_X, | ||
| 141 | (packet[1] | ((packet[0] & 0x30) << 4))); | ||
| 142 | input_report_abs(dev, ABS_Y, | ||
| 143 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | ||
| 98 | } | 144 | } |
| 99 | 145 | ||
| 100 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 146 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
| @@ -119,7 +165,7 @@ static int lifebook_absolute_mode(struct psmouse *psmouse) | |||
| 119 | you leave this call out the touchsreen will never send | 165 | you leave this call out the touchsreen will never send |
| 120 | absolute coordinates | 166 | absolute coordinates |
| 121 | */ | 167 | */ |
| 122 | param = 0x07; | 168 | param = lifebook_use_6byte_proto ? 0x08 : 0x07; |
| 123 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); | 169 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); |
| 124 | 170 | ||
| 125 | return 0; | 171 | return 0; |
| @@ -163,6 +209,7 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties) | |||
| 163 | int lifebook_init(struct psmouse *psmouse) | 209 | int lifebook_init(struct psmouse *psmouse) |
| 164 | { | 210 | { |
| 165 | struct input_dev *input_dev = psmouse->dev; | 211 | struct input_dev *input_dev = psmouse->dev; |
| 212 | int max_coord = lifebook_use_6byte_proto ? 1024 : 4096; | ||
| 166 | 213 | ||
| 167 | if (lifebook_absolute_mode(psmouse)) | 214 | if (lifebook_absolute_mode(psmouse)) |
| 168 | return -1; | 215 | return -1; |
| @@ -171,13 +218,18 @@ int lifebook_init(struct psmouse *psmouse) | |||
| 171 | input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | 218 | input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); |
| 172 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 219 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
| 173 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | 220 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); |
| 174 | input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0); | 221 | input_set_abs_params(input_dev, ABS_X, 0, max_coord, 0, 0); |
| 175 | input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0); | 222 | input_set_abs_params(input_dev, ABS_Y, 0, max_coord, 0, 0); |
| 176 | 223 | ||
| 177 | psmouse->protocol_handler = lifebook_process_byte; | 224 | psmouse->protocol_handler = lifebook_process_byte; |
| 178 | psmouse->set_resolution = lifebook_set_resolution; | 225 | psmouse->set_resolution = lifebook_set_resolution; |
| 179 | psmouse->disconnect = lifebook_disconnect; | 226 | psmouse->disconnect = lifebook_disconnect; |
| 180 | psmouse->reconnect = lifebook_absolute_mode; | 227 | psmouse->reconnect = lifebook_absolute_mode; |
| 228 | |||
| 229 | /* | ||
| 230 | * Use packet size = 3 even when using 6-byte protocol because | ||
| 231 | * that's what POLL will return on Lifebooks (according to spec). | ||
| 232 | */ | ||
| 181 | psmouse->pktsize = 3; | 233 | psmouse->pktsize = 3; |
| 182 | 234 | ||
| 183 | return 0; | 235 | return 0; |
