diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-01-07 01:34:59 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-01-07 01:34:59 -0500 |
commit | 554738da71004d96e06fb75f4772dfc3b0f47810 (patch) | |
tree | 149a96ce3727025d3b9260961ec94ba8306db278 /drivers/input/touchscreen | |
parent | 7b4b30689d688d9ca2e5c3859db6bbe1c35e6014 (diff) | |
parent | a6d38f889750ed6290728a19d9dad577b147c6d0 (diff) |
Merge branch 'next' into for-linus
Conflicts:
include/linux/input.h
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 22 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/bu21013_ts.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/qt602240_ts.c | 21 | ||||
-rw-r--r-- | drivers/input/touchscreen/st1232.c | 274 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom_w8001.c | 71 |
6 files changed, 346 insertions, 45 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 06ea8da95c62..07ac77d393a4 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -659,17 +659,17 @@ config TOUCHSCREEN_PCAP | |||
659 | To compile this driver as a module, choose M here: the | 659 | To compile this driver as a module, choose M here: the |
660 | module will be called pcap_ts. | 660 | module will be called pcap_ts. |
661 | 661 | ||
662 | config TOUCHSCREEN_TPS6507X | 662 | config TOUCHSCREEN_ST1232 |
663 | tristate "TPS6507x based touchscreens" | 663 | tristate "Sitronix ST1232 touchscreen controllers" |
664 | depends on I2C | 664 | depends on I2C |
665 | help | 665 | help |
666 | Say Y here if you have a TPS6507x based touchscreen | 666 | Say Y here if you want to support Sitronix ST1232 |
667 | controller. | 667 | touchscreen controller. |
668 | 668 | ||
669 | If unsure, say N. | 669 | If unsure, say N. |
670 | 670 | ||
671 | To compile this driver as a module, choose M here: the | 671 | To compile this driver as a module, choose M here: the |
672 | module will be called tps6507x_ts. | 672 | module will be called st1232_ts. |
673 | 673 | ||
674 | config TOUCHSCREEN_STMPE | 674 | config TOUCHSCREEN_STMPE |
675 | tristate "STMicroelectronics STMPE touchscreens" | 675 | tristate "STMicroelectronics STMPE touchscreens" |
@@ -681,4 +681,16 @@ config TOUCHSCREEN_STMPE | |||
681 | To compile this driver as a module, choose M here: the | 681 | To compile this driver as a module, choose M here: the |
682 | module will be called stmpe-ts. | 682 | module will be called stmpe-ts. |
683 | 683 | ||
684 | config TOUCHSCREEN_TPS6507X | ||
685 | tristate "TPS6507x based touchscreens" | ||
686 | depends on I2C | ||
687 | help | ||
688 | Say Y here if you have a TPS6507x based touchscreen | ||
689 | controller. | ||
690 | |||
691 | If unsure, say N. | ||
692 | |||
693 | To compile this driver as a module, choose M here: the | ||
694 | module will be called tps6507x_ts. | ||
695 | |||
684 | endif | 696 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7cc1b4f4b677..718bcc814952 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | |||
39 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 39 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
40 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o | 40 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o |
41 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 41 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
42 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | ||
42 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 43 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
43 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | 44 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o |
44 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 45 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 2ca9e5d66460..f7fa9ef4cd65 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c | |||
@@ -365,7 +365,7 @@ static int bu21013_init_chip(struct bu21013_ts_data *data) | |||
365 | } | 365 | } |
366 | 366 | ||
367 | retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG, | 367 | retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG, |
368 | BU21013_TH_OFF_4 || BU21013_TH_OFF_3); | 368 | BU21013_TH_OFF_4 | BU21013_TH_OFF_3); |
369 | if (retval < 0) { | 369 | if (retval < 0) { |
370 | dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n"); | 370 | dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n"); |
371 | return retval; | 371 | return retval; |
diff --git a/drivers/input/touchscreen/qt602240_ts.c b/drivers/input/touchscreen/qt602240_ts.c index 66b26ad3032a..4dcb0e872f6a 100644 --- a/drivers/input/touchscreen/qt602240_ts.c +++ b/drivers/input/touchscreen/qt602240_ts.c | |||
@@ -969,7 +969,7 @@ static int qt602240_initialize(struct qt602240_data *data) | |||
969 | return error; | 969 | return error; |
970 | 970 | ||
971 | data->object_table = kcalloc(info->object_num, | 971 | data->object_table = kcalloc(info->object_num, |
972 | sizeof(struct qt602240_data), | 972 | sizeof(struct qt602240_object), |
973 | GFP_KERNEL); | 973 | GFP_KERNEL); |
974 | if (!data->object_table) { | 974 | if (!data->object_table) { |
975 | dev_err(&client->dev, "Failed to allocate memory\n"); | 975 | dev_err(&client->dev, "Failed to allocate memory\n"); |
@@ -1324,8 +1324,9 @@ static int __devexit qt602240_remove(struct i2c_client *client) | |||
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | #ifdef CONFIG_PM | 1326 | #ifdef CONFIG_PM |
1327 | static int qt602240_suspend(struct i2c_client *client, pm_message_t mesg) | 1327 | static int qt602240_suspend(struct device *dev) |
1328 | { | 1328 | { |
1329 | struct i2c_client *client = to_i2c_client(dev); | ||
1329 | struct qt602240_data *data = i2c_get_clientdata(client); | 1330 | struct qt602240_data *data = i2c_get_clientdata(client); |
1330 | struct input_dev *input_dev = data->input_dev; | 1331 | struct input_dev *input_dev = data->input_dev; |
1331 | 1332 | ||
@@ -1339,8 +1340,9 @@ static int qt602240_suspend(struct i2c_client *client, pm_message_t mesg) | |||
1339 | return 0; | 1340 | return 0; |
1340 | } | 1341 | } |
1341 | 1342 | ||
1342 | static int qt602240_resume(struct i2c_client *client) | 1343 | static int qt602240_resume(struct device *dev) |
1343 | { | 1344 | { |
1345 | struct i2c_client *client = to_i2c_client(dev); | ||
1344 | struct qt602240_data *data = i2c_get_clientdata(client); | 1346 | struct qt602240_data *data = i2c_get_clientdata(client); |
1345 | struct input_dev *input_dev = data->input_dev; | 1347 | struct input_dev *input_dev = data->input_dev; |
1346 | 1348 | ||
@@ -1359,9 +1361,11 @@ static int qt602240_resume(struct i2c_client *client) | |||
1359 | 1361 | ||
1360 | return 0; | 1362 | return 0; |
1361 | } | 1363 | } |
1362 | #else | 1364 | |
1363 | #define qt602240_suspend NULL | 1365 | static const struct dev_pm_ops qt602240_pm_ops = { |
1364 | #define qt602240_resume NULL | 1366 | .suspend = qt602240_suspend, |
1367 | .resume = qt602240_resume, | ||
1368 | }; | ||
1365 | #endif | 1369 | #endif |
1366 | 1370 | ||
1367 | static const struct i2c_device_id qt602240_id[] = { | 1371 | static const struct i2c_device_id qt602240_id[] = { |
@@ -1374,11 +1378,12 @@ static struct i2c_driver qt602240_driver = { | |||
1374 | .driver = { | 1378 | .driver = { |
1375 | .name = "qt602240_ts", | 1379 | .name = "qt602240_ts", |
1376 | .owner = THIS_MODULE, | 1380 | .owner = THIS_MODULE, |
1381 | #ifdef CONFIG_PM | ||
1382 | .pm = &qt602240_pm_ops, | ||
1383 | #endif | ||
1377 | }, | 1384 | }, |
1378 | .probe = qt602240_probe, | 1385 | .probe = qt602240_probe, |
1379 | .remove = __devexit_p(qt602240_remove), | 1386 | .remove = __devexit_p(qt602240_remove), |
1380 | .suspend = qt602240_suspend, | ||
1381 | .resume = qt602240_resume, | ||
1382 | .id_table = qt602240_id, | 1387 | .id_table = qt602240_id, |
1383 | }; | 1388 | }; |
1384 | 1389 | ||
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c new file mode 100644 index 000000000000..4ab371358b33 --- /dev/null +++ b/drivers/input/touchscreen/st1232.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* | ||
2 | * ST1232 Touchscreen Controller Driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Renesas Solutions Corp. | ||
5 | * Tony SIM <chinyeow.sim.xt@renesas.com> | ||
6 | * | ||
7 | * Using code from: | ||
8 | * - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c | ||
9 | * Copyright (C) 2007 Google, Inc. | ||
10 | * | ||
11 | * This software is licensed under the terms of the GNU General Public | ||
12 | * License version 2, as published by the Free Software Foundation, and | ||
13 | * may be copied, distributed, and modified under those terms. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/types.h> | ||
28 | |||
29 | #define ST1232_TS_NAME "st1232-ts" | ||
30 | |||
31 | #define MIN_X 0x00 | ||
32 | #define MIN_Y 0x00 | ||
33 | #define MAX_X 0x31f /* (800 - 1) */ | ||
34 | #define MAX_Y 0x1df /* (480 - 1) */ | ||
35 | #define MAX_AREA 0xff | ||
36 | #define MAX_FINGERS 2 | ||
37 | |||
38 | struct st1232_ts_finger { | ||
39 | u16 x; | ||
40 | u16 y; | ||
41 | u8 t; | ||
42 | bool is_valid; | ||
43 | }; | ||
44 | |||
45 | struct st1232_ts_data { | ||
46 | struct i2c_client *client; | ||
47 | struct input_dev *input_dev; | ||
48 | struct st1232_ts_finger finger[MAX_FINGERS]; | ||
49 | }; | ||
50 | |||
51 | static int st1232_ts_read_data(struct st1232_ts_data *ts) | ||
52 | { | ||
53 | struct st1232_ts_finger *finger = ts->finger; | ||
54 | struct i2c_client *client = ts->client; | ||
55 | struct i2c_msg msg[2]; | ||
56 | int error; | ||
57 | u8 start_reg; | ||
58 | u8 buf[10]; | ||
59 | |||
60 | /* read touchscreen data from ST1232 */ | ||
61 | msg[0].addr = client->addr; | ||
62 | msg[0].flags = 0; | ||
63 | msg[0].len = 1; | ||
64 | msg[0].buf = &start_reg; | ||
65 | start_reg = 0x10; | ||
66 | |||
67 | msg[1].addr = ts->client->addr; | ||
68 | msg[1].flags = I2C_M_RD; | ||
69 | msg[1].len = sizeof(buf); | ||
70 | msg[1].buf = buf; | ||
71 | |||
72 | error = i2c_transfer(client->adapter, msg, 2); | ||
73 | if (error < 0) | ||
74 | return error; | ||
75 | |||
76 | /* get "valid" bits */ | ||
77 | finger[0].is_valid = buf[2] >> 7; | ||
78 | finger[1].is_valid = buf[5] >> 7; | ||
79 | |||
80 | /* get xy coordinate */ | ||
81 | if (finger[0].is_valid) { | ||
82 | finger[0].x = ((buf[2] & 0x0070) << 4) | buf[3]; | ||
83 | finger[0].y = ((buf[2] & 0x0007) << 8) | buf[4]; | ||
84 | finger[0].t = buf[8]; | ||
85 | } | ||
86 | |||
87 | if (finger[1].is_valid) { | ||
88 | finger[1].x = ((buf[5] & 0x0070) << 4) | buf[6]; | ||
89 | finger[1].y = ((buf[5] & 0x0007) << 8) | buf[7]; | ||
90 | finger[1].t = buf[9]; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) | ||
97 | { | ||
98 | struct st1232_ts_data *ts = dev_id; | ||
99 | struct st1232_ts_finger *finger = ts->finger; | ||
100 | struct input_dev *input_dev = ts->input_dev; | ||
101 | int count = 0; | ||
102 | int i, ret; | ||
103 | |||
104 | ret = st1232_ts_read_data(ts); | ||
105 | if (ret < 0) | ||
106 | goto end; | ||
107 | |||
108 | /* multi touch protocol */ | ||
109 | for (i = 0; i < MAX_FINGERS; i++) { | ||
110 | if (!finger[i].is_valid) | ||
111 | continue; | ||
112 | |||
113 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t); | ||
114 | input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x); | ||
115 | input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y); | ||
116 | input_mt_sync(input_dev); | ||
117 | count++; | ||
118 | } | ||
119 | |||
120 | /* SYN_MT_REPORT only if no contact */ | ||
121 | if (!count) | ||
122 | input_mt_sync(input_dev); | ||
123 | |||
124 | /* SYN_REPORT */ | ||
125 | input_sync(input_dev); | ||
126 | |||
127 | end: | ||
128 | return IRQ_HANDLED; | ||
129 | } | ||
130 | |||
131 | static int __devinit st1232_ts_probe(struct i2c_client *client, | ||
132 | const struct i2c_device_id *id) | ||
133 | { | ||
134 | struct st1232_ts_data *ts; | ||
135 | struct input_dev *input_dev; | ||
136 | int error; | ||
137 | |||
138 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
139 | dev_err(&client->dev, "need I2C_FUNC_I2C\n"); | ||
140 | return -EIO; | ||
141 | } | ||
142 | |||
143 | if (!client->irq) { | ||
144 | dev_err(&client->dev, "no IRQ?\n"); | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | |||
148 | |||
149 | ts = kzalloc(sizeof(struct st1232_ts_data), GFP_KERNEL); | ||
150 | input_dev = input_allocate_device(); | ||
151 | if (!ts || !input_dev) { | ||
152 | error = -ENOMEM; | ||
153 | goto err_free_mem; | ||
154 | } | ||
155 | |||
156 | ts->client = client; | ||
157 | ts->input_dev = input_dev; | ||
158 | |||
159 | input_dev->name = "st1232-touchscreen"; | ||
160 | input_dev->id.bustype = BUS_I2C; | ||
161 | input_dev->dev.parent = &client->dev; | ||
162 | |||
163 | __set_bit(EV_SYN, input_dev->evbit); | ||
164 | __set_bit(EV_KEY, input_dev->evbit); | ||
165 | __set_bit(EV_ABS, input_dev->evbit); | ||
166 | |||
167 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0); | ||
168 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0); | ||
169 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0); | ||
170 | |||
171 | error = request_threaded_irq(client->irq, NULL, st1232_ts_irq_handler, | ||
172 | IRQF_ONESHOT, client->name, ts); | ||
173 | if (error) { | ||
174 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
175 | goto err_free_mem; | ||
176 | } | ||
177 | |||
178 | error = input_register_device(ts->input_dev); | ||
179 | if (error) { | ||
180 | dev_err(&client->dev, "Unable to register %s input device\n", | ||
181 | input_dev->name); | ||
182 | goto err_free_irq; | ||
183 | } | ||
184 | |||
185 | i2c_set_clientdata(client, ts); | ||
186 | device_init_wakeup(&client->dev, 1); | ||
187 | |||
188 | return 0; | ||
189 | |||
190 | err_free_irq: | ||
191 | free_irq(client->irq, ts); | ||
192 | err_free_mem: | ||
193 | input_free_device(input_dev); | ||
194 | kfree(ts); | ||
195 | return error; | ||
196 | } | ||
197 | |||
198 | static int __devexit st1232_ts_remove(struct i2c_client *client) | ||
199 | { | ||
200 | struct st1232_ts_data *ts = i2c_get_clientdata(client); | ||
201 | |||
202 | device_init_wakeup(&client->dev, 0); | ||
203 | free_irq(client->irq, ts); | ||
204 | input_unregister_device(ts->input_dev); | ||
205 | kfree(ts); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | #ifdef CONFIG_PM | ||
211 | static int st1232_ts_suspend(struct device *dev) | ||
212 | { | ||
213 | struct i2c_client *client = to_i2c_client(dev); | ||
214 | |||
215 | if (device_may_wakeup(&client->dev)) | ||
216 | enable_irq_wake(client->irq); | ||
217 | else | ||
218 | disable_irq(client->irq); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int st1232_ts_resume(struct device *dev) | ||
224 | { | ||
225 | struct i2c_client *client = to_i2c_client(dev); | ||
226 | |||
227 | if (device_may_wakeup(&client->dev)) | ||
228 | disable_irq_wake(client->irq); | ||
229 | else | ||
230 | enable_irq(client->irq); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static const struct dev_pm_ops st1232_ts_pm_ops = { | ||
236 | .suspend = st1232_ts_suspend, | ||
237 | .resume = st1232_ts_resume, | ||
238 | }; | ||
239 | #endif | ||
240 | |||
241 | static const struct i2c_device_id st1232_ts_id[] = { | ||
242 | { ST1232_TS_NAME, 0 }, | ||
243 | { } | ||
244 | }; | ||
245 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); | ||
246 | |||
247 | static struct i2c_driver st1232_ts_driver = { | ||
248 | .probe = st1232_ts_probe, | ||
249 | .remove = __devexit_p(st1232_ts_remove), | ||
250 | .id_table = st1232_ts_id, | ||
251 | .driver = { | ||
252 | .name = ST1232_TS_NAME, | ||
253 | .owner = THIS_MODULE, | ||
254 | #ifdef CONFIG_PM | ||
255 | .pm = &st1232_ts_pm_ops, | ||
256 | #endif | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | static int __init st1232_ts_init(void) | ||
261 | { | ||
262 | return i2c_add_driver(&st1232_ts_driver); | ||
263 | } | ||
264 | module_init(st1232_ts_init); | ||
265 | |||
266 | static void __exit st1232_ts_exit(void) | ||
267 | { | ||
268 | i2c_del_driver(&st1232_ts_driver); | ||
269 | } | ||
270 | module_exit(st1232_ts_exit); | ||
271 | |||
272 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); | ||
273 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); | ||
274 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9ae4c7b16ba7..8ed53aded2d3 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -15,10 +15,11 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input/mt.h> |
19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/delay.h> | ||
22 | 23 | ||
23 | #define DRIVER_DESC "Wacom W8001 serial touchscreen driver" | 24 | #define DRIVER_DESC "Wacom W8001 serial touchscreen driver" |
24 | 25 | ||
@@ -37,6 +38,7 @@ MODULE_LICENSE("GPL"); | |||
37 | 38 | ||
38 | #define W8001_QUERY_PACKET 0x20 | 39 | #define W8001_QUERY_PACKET 0x20 |
39 | 40 | ||
41 | #define W8001_CMD_STOP '0' | ||
40 | #define W8001_CMD_START '1' | 42 | #define W8001_CMD_START '1' |
41 | #define W8001_CMD_QUERY '*' | 43 | #define W8001_CMD_QUERY '*' |
42 | #define W8001_CMD_TOUCHQUERY '%' | 44 | #define W8001_CMD_TOUCHQUERY '%' |
@@ -48,8 +50,6 @@ MODULE_LICENSE("GPL"); | |||
48 | #define W8001_PKTLEN_TPCCTL 11 /* control packet */ | 50 | #define W8001_PKTLEN_TPCCTL 11 /* control packet */ |
49 | #define W8001_PKTLEN_TOUCH2FG 13 | 51 | #define W8001_PKTLEN_TOUCH2FG 13 |
50 | 52 | ||
51 | #define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */ | ||
52 | |||
53 | struct w8001_coord { | 53 | struct w8001_coord { |
54 | u8 rdy; | 54 | u8 rdy; |
55 | u8 tsw; | 55 | u8 tsw; |
@@ -87,7 +87,6 @@ struct w8001 { | |||
87 | char phys[32]; | 87 | char phys[32]; |
88 | int type; | 88 | int type; |
89 | unsigned int pktlen; | 89 | unsigned int pktlen; |
90 | int trkid[2]; | ||
91 | }; | 90 | }; |
92 | 91 | ||
93 | static void parse_data(u8 *data, struct w8001_coord *coord) | 92 | static void parse_data(u8 *data, struct w8001_coord *coord) |
@@ -116,28 +115,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord) | |||
116 | 115 | ||
117 | static void parse_touch(struct w8001 *w8001) | 116 | static void parse_touch(struct w8001 *w8001) |
118 | { | 117 | { |
119 | static int trkid; | ||
120 | struct input_dev *dev = w8001->dev; | 118 | struct input_dev *dev = w8001->dev; |
121 | unsigned char *data = w8001->data; | 119 | unsigned char *data = w8001->data; |
122 | int i; | 120 | int i; |
123 | 121 | ||
124 | for (i = 0; i < 2; i++) { | 122 | for (i = 0; i < 2; i++) { |
125 | input_mt_slot(dev, i); | 123 | bool touch = data[0] & (1 << i); |
126 | 124 | ||
127 | if (data[0] & (1 << i)) { | 125 | input_mt_slot(dev, i); |
126 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch); | ||
127 | if (touch) { | ||
128 | int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); | 128 | int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); |
129 | int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); | 129 | int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); |
130 | /* data[5,6] and [11,12] is finger capacity */ | 130 | /* data[5,6] and [11,12] is finger capacity */ |
131 | 131 | ||
132 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 132 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
133 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | 133 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
134 | input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER); | ||
135 | if (w8001->trkid[i] < 0) | ||
136 | w8001->trkid[i] = trkid++ & MAX_TRACKING_ID; | ||
137 | } else { | ||
138 | w8001->trkid[i] = -1; | ||
139 | } | 134 | } |
140 | input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]); | ||
141 | } | 135 | } |
142 | 136 | ||
143 | input_sync(dev); | 137 | input_sync(dev); |
@@ -287,24 +281,46 @@ static int w8001_setup(struct w8001 *w8001) | |||
287 | struct w8001_coord coord; | 281 | struct w8001_coord coord; |
288 | int error; | 282 | int error; |
289 | 283 | ||
290 | error = w8001_command(w8001, W8001_CMD_QUERY, true); | 284 | error = w8001_command(w8001, W8001_CMD_STOP, false); |
291 | if (error) | 285 | if (error) |
292 | return error; | 286 | return error; |
293 | 287 | ||
294 | parse_data(w8001->response, &coord); | 288 | msleep(250); /* wait 250ms before querying the device */ |
295 | 289 | ||
296 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | 290 | /* penabled? */ |
297 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | 291 | error = w8001_command(w8001, W8001_CMD_QUERY, true); |
298 | input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); | 292 | if (!error) { |
299 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | 293 | __set_bit(BTN_TOOL_PEN, dev->keybit); |
300 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | 294 | __set_bit(BTN_TOOL_RUBBER, dev->keybit); |
295 | __set_bit(BTN_STYLUS, dev->keybit); | ||
296 | __set_bit(BTN_STYLUS2, dev->keybit); | ||
297 | parse_data(w8001->response, &coord); | ||
298 | |||
299 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | ||
300 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | ||
301 | input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); | ||
302 | if (coord.tilt_x && coord.tilt_y) { | ||
303 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | ||
304 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | ||
305 | } | ||
306 | } | ||
301 | 307 | ||
308 | /* Touch enabled? */ | ||
302 | error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true); | 309 | error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true); |
303 | if (!error) { | 310 | |
311 | /* | ||
312 | * Some non-touch devices may reply to the touch query. But their | ||
313 | * second byte is empty, which indicates touch is not supported. | ||
314 | */ | ||
315 | if (!error && w8001->response[1]) { | ||
304 | struct w8001_touch_query touch; | 316 | struct w8001_touch_query touch; |
305 | 317 | ||
306 | parse_touchquery(w8001->response, &touch); | 318 | parse_touchquery(w8001->response, &touch); |
307 | 319 | ||
320 | input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); | ||
321 | input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); | ||
322 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | ||
323 | |||
308 | switch (touch.sensor_id) { | 324 | switch (touch.sensor_id) { |
309 | case 0: | 325 | case 0: |
310 | case 2: | 326 | case 2: |
@@ -318,15 +334,13 @@ static int w8001_setup(struct w8001 *w8001) | |||
318 | case 5: | 334 | case 5: |
319 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; | 335 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; |
320 | 336 | ||
321 | input_mt_create_slots(dev, 2); | 337 | input_mt_init_slots(dev, 2); |
322 | input_set_abs_params(dev, ABS_MT_TRACKING_ID, | ||
323 | 0, MAX_TRACKING_ID, 0, 0); | ||
324 | input_set_abs_params(dev, ABS_MT_POSITION_X, | 338 | input_set_abs_params(dev, ABS_MT_POSITION_X, |
325 | 0, touch.x, 0, 0); | 339 | 0, touch.x, 0, 0); |
326 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | 340 | input_set_abs_params(dev, ABS_MT_POSITION_Y, |
327 | 0, touch.y, 0, 0); | 341 | 0, touch.y, 0, 0); |
328 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, | 342 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, |
329 | 0, 0, 0, 0); | 343 | 0, MT_TOOL_MAX, 0, 0); |
330 | break; | 344 | break; |
331 | } | 345 | } |
332 | } | 346 | } |
@@ -372,7 +386,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
372 | w8001->serio = serio; | 386 | w8001->serio = serio; |
373 | w8001->id = serio->id.id; | 387 | w8001->id = serio->id.id; |
374 | w8001->dev = input_dev; | 388 | w8001->dev = input_dev; |
375 | w8001->trkid[0] = w8001->trkid[1] = -1; | ||
376 | init_completion(&w8001->cmd_done); | 389 | init_completion(&w8001->cmd_done); |
377 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 390 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
378 | 391 | ||
@@ -385,11 +398,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
385 | input_dev->dev.parent = &serio->dev; | 398 | input_dev->dev.parent = &serio->dev; |
386 | 399 | ||
387 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 400 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
388 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 401 | __set_bit(BTN_TOUCH, input_dev->keybit); |
389 | input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN); | ||
390 | input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER); | ||
391 | input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS); | ||
392 | input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2); | ||
393 | 402 | ||
394 | serio_set_drvdata(serio, w8001); | 403 | serio_set_drvdata(serio, w8001); |
395 | err = serio_open(serio, drv); | 404 | err = serio_open(serio, drv); |