diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-04-12 01:36:34 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-04-12 01:36:34 -0400 |
commit | 1b118799cceab69d80c162bc661c77fdc33dd756 (patch) | |
tree | f68d80aa0e1b649a85ab3d89f8b302df34ac0481 /drivers/input/mouse/lifebook.c | |
parent | e7afcd1bf784dde4cd6c6efbf9a4709626cc8e08 (diff) |
Input: lifebook - activate 6-byte protocol on select models
It appears that if we turn on 6-byte Lifebook protocol on
Panasonic CF-28 its touchpad is left alone and generates
standard 3-byte PS/2 data stream with relative packets
instead of being converted in 3-byte Lifebook protocol with
absolute coordinates - in other words what get what we need
to distinguish between touchscreen and touchpad.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse/lifebook.c')
-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; |