aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/lifebook.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-04-12 01:36:34 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-04-12 01:36:34 -0400
commit1b118799cceab69d80c162bc661c77fdc33dd756 (patch)
treef68d80aa0e1b649a85ab3d89f8b302df34ac0481 /drivers/input/mouse/lifebook.c
parente7afcd1bf784dde4cd6c6efbf9a4709626cc8e08 (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.c78
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
31static unsigned char lifebook_use_6byte_proto;
32
33static int lifebook_set_6byte_proto(struct dmi_system_id *d)
34{
35 lifebook_use_6byte_proto = 1;
36 return 0;
37}
38
31static struct dmi_system_id lifebook_dmi_table[] = { 39static 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
79static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) 95static 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, &param, PSMOUSE_CMD_SETRES); 169 ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
124 170
125 return 0; 171 return 0;
@@ -163,6 +209,7 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
163int lifebook_init(struct psmouse *psmouse) 209int 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;