diff options
Diffstat (limited to 'drivers/input/tablet')
-rw-r--r-- | drivers/input/tablet/Kconfig | 11 | ||||
-rw-r--r-- | drivers/input/tablet/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/tablet/hanwang.c | 446 | ||||
-rw-r--r-- | drivers/input/tablet/wacom.h | 1 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 77 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 253 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.h | 15 |
7 files changed, 766 insertions, 38 deletions
diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig index effb49ea24aa..58a87755b936 100644 --- a/drivers/input/tablet/Kconfig +++ b/drivers/input/tablet/Kconfig | |||
@@ -49,6 +49,17 @@ config TABLET_USB_GTCO | |||
49 | To compile this driver as a module, choose M here: the | 49 | To compile this driver as a module, choose M here: the |
50 | module will be called gtco. | 50 | module will be called gtco. |
51 | 51 | ||
52 | config TABLET_USB_HANWANG | ||
53 | tristate "Hanwang Art Master III tablet support (USB)" | ||
54 | depends on USB_ARCH_HAS_HCD | ||
55 | select USB | ||
56 | help | ||
57 | Say Y here if you want to use the USB version of the Hanwang Art | ||
58 | Master III tablet. | ||
59 | |||
60 | To compile this driver as a module, choose M here: the | ||
61 | module will be called hanwang. | ||
62 | |||
52 | config TABLET_USB_KBTAB | 63 | config TABLET_USB_KBTAB |
53 | tristate "KB Gear JamStudio tablet support (USB)" | 64 | tristate "KB Gear JamStudio tablet support (USB)" |
54 | depends on USB_ARCH_HAS_HCD | 65 | depends on USB_ARCH_HAS_HCD |
diff --git a/drivers/input/tablet/Makefile b/drivers/input/tablet/Makefile index ce8b9a9cfa40..3f6c25220638 100644 --- a/drivers/input/tablet/Makefile +++ b/drivers/input/tablet/Makefile | |||
@@ -8,5 +8,6 @@ wacom-objs := wacom_wac.o wacom_sys.o | |||
8 | obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o | 8 | obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o |
9 | obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o | 9 | obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o |
10 | obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o | 10 | obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o |
11 | obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o | ||
11 | obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o | 12 | obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o |
12 | obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o | 13 | obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o |
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c new file mode 100644 index 000000000000..6504b627b234 --- /dev/null +++ b/drivers/input/tablet/hanwang.c | |||
@@ -0,0 +1,446 @@ | |||
1 | /* | ||
2 | * USB Hanwang tablet support | ||
3 | * | ||
4 | * Copyright (c) 2010 Xing Wei <weixing@hanwang.com.cn> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/types.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/usb/input.h> | ||
31 | |||
32 | #define DRIVER_AUTHOR "Xing Wei <weixing@hanwang.com.cn>" | ||
33 | #define DRIVER_DESC "USB Hanwang tablet driver" | ||
34 | #define DRIVER_LICENSE "GPL" | ||
35 | |||
36 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
37 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
38 | MODULE_LICENSE(DRIVER_LICENSE); | ||
39 | |||
40 | #define USB_VENDOR_ID_HANWANG 0x0b57 | ||
41 | #define HANWANG_TABLET_INT_CLASS 0x0003 | ||
42 | #define HANWANG_TABLET_INT_SUB_CLASS 0x0001 | ||
43 | #define HANWANG_TABLET_INT_PROTOCOL 0x0002 | ||
44 | |||
45 | #define ART_MASTER_PKGLEN_MAX 10 | ||
46 | |||
47 | /* device IDs */ | ||
48 | #define STYLUS_DEVICE_ID 0x02 | ||
49 | #define TOUCH_DEVICE_ID 0x03 | ||
50 | #define CURSOR_DEVICE_ID 0x06 | ||
51 | #define ERASER_DEVICE_ID 0x0A | ||
52 | #define PAD_DEVICE_ID 0x0F | ||
53 | |||
54 | /* match vendor and interface info */ | ||
55 | #define HANWANG_TABLET_DEVICE(vend, cl, sc, pr) \ | ||
56 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR \ | ||
57 | | USB_DEVICE_ID_MATCH_INT_INFO, \ | ||
58 | .idVendor = (vend), \ | ||
59 | .bInterfaceClass = (cl), \ | ||
60 | .bInterfaceSubClass = (sc), \ | ||
61 | .bInterfaceProtocol = (pr) | ||
62 | |||
63 | enum hanwang_tablet_type { | ||
64 | HANWANG_ART_MASTER_III, | ||
65 | HANWANG_ART_MASTER_HD, | ||
66 | }; | ||
67 | |||
68 | struct hanwang { | ||
69 | unsigned char *data; | ||
70 | dma_addr_t data_dma; | ||
71 | struct input_dev *dev; | ||
72 | struct usb_device *usbdev; | ||
73 | struct urb *irq; | ||
74 | const struct hanwang_features *features; | ||
75 | unsigned int current_tool; | ||
76 | unsigned int current_id; | ||
77 | char name[64]; | ||
78 | char phys[32]; | ||
79 | }; | ||
80 | |||
81 | struct hanwang_features { | ||
82 | unsigned short pid; | ||
83 | char *name; | ||
84 | enum hanwang_tablet_type type; | ||
85 | int pkg_len; | ||
86 | int max_x; | ||
87 | int max_y; | ||
88 | int max_tilt_x; | ||
89 | int max_tilt_y; | ||
90 | int max_pressure; | ||
91 | }; | ||
92 | |||
93 | static const struct hanwang_features features_array[] = { | ||
94 | { 0x8528, "Hanwang Art Master III 0906", HANWANG_ART_MASTER_III, | ||
95 | ART_MASTER_PKGLEN_MAX, 0x5757, 0x3692, 0x3f, 0x7f, 2048 }, | ||
96 | { 0x8529, "Hanwang Art Master III 0604", HANWANG_ART_MASTER_III, | ||
97 | ART_MASTER_PKGLEN_MAX, 0x3d84, 0x2672, 0x3f, 0x7f, 2048 }, | ||
98 | { 0x852a, "Hanwang Art Master III 1308", HANWANG_ART_MASTER_III, | ||
99 | ART_MASTER_PKGLEN_MAX, 0x7f00, 0x4f60, 0x3f, 0x7f, 2048 }, | ||
100 | { 0x8401, "Hanwang Art Master HD 5012", HANWANG_ART_MASTER_HD, | ||
101 | ART_MASTER_PKGLEN_MAX, 0x678e, 0x4150, 0x3f, 0x7f, 1024 }, | ||
102 | }; | ||
103 | |||
104 | static const int hw_eventtypes[] = { | ||
105 | EV_KEY, EV_ABS, EV_MSC, | ||
106 | }; | ||
107 | |||
108 | static const int hw_absevents[] = { | ||
109 | ABS_X, ABS_Y, ABS_TILT_X, ABS_TILT_Y, ABS_WHEEL, | ||
110 | ABS_RX, ABS_RY, ABS_PRESSURE, ABS_MISC, | ||
111 | }; | ||
112 | |||
113 | static const int hw_btnevents[] = { | ||
114 | BTN_STYLUS, BTN_STYLUS2, BTN_TOOL_PEN, BTN_TOOL_RUBBER, | ||
115 | BTN_TOOL_MOUSE, BTN_TOOL_FINGER, | ||
116 | BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8, | ||
117 | }; | ||
118 | |||
119 | static const int hw_mscevents[] = { | ||
120 | MSC_SERIAL, | ||
121 | }; | ||
122 | |||
123 | static void hanwang_parse_packet(struct hanwang *hanwang) | ||
124 | { | ||
125 | unsigned char *data = hanwang->data; | ||
126 | struct input_dev *input_dev = hanwang->dev; | ||
127 | struct usb_device *dev = hanwang->usbdev; | ||
128 | enum hanwang_tablet_type type = hanwang->features->type; | ||
129 | int i; | ||
130 | u16 x, y, p; | ||
131 | |||
132 | switch (data[0]) { | ||
133 | case 0x02: /* data packet */ | ||
134 | switch (data[1]) { | ||
135 | case 0x80: /* tool prox out */ | ||
136 | hanwang->current_id = 0; | ||
137 | input_report_key(input_dev, hanwang->current_tool, 0); | ||
138 | break; | ||
139 | |||
140 | case 0xc2: /* first time tool prox in */ | ||
141 | switch (data[3] & 0xf0) { | ||
142 | case 0x20: /* art_master III */ | ||
143 | case 0x30: /* art_master_HD */ | ||
144 | hanwang->current_id = STYLUS_DEVICE_ID; | ||
145 | hanwang->current_tool = BTN_TOOL_PEN; | ||
146 | input_report_key(input_dev, BTN_TOOL_PEN, 1); | ||
147 | break; | ||
148 | case 0xa0: /* art_master III */ | ||
149 | case 0xb0: /* art_master_HD */ | ||
150 | hanwang->current_id = ERASER_DEVICE_ID; | ||
151 | hanwang->current_tool = BTN_TOOL_RUBBER; | ||
152 | input_report_key(input_dev, BTN_TOOL_RUBBER, 1); | ||
153 | break; | ||
154 | default: | ||
155 | hanwang->current_id = 0; | ||
156 | dev_dbg(&dev->dev, | ||
157 | "unknown tablet tool %02x ", data[0]); | ||
158 | break; | ||
159 | } | ||
160 | break; | ||
161 | |||
162 | default: /* tool data packet */ | ||
163 | x = (data[2] << 8) | data[3]; | ||
164 | y = (data[4] << 8) | data[5]; | ||
165 | |||
166 | switch (type) { | ||
167 | case HANWANG_ART_MASTER_III: | ||
168 | p = (data[6] << 3) | | ||
169 | ((data[7] & 0xc0) >> 5) | | ||
170 | (data[1] & 0x01); | ||
171 | break; | ||
172 | |||
173 | case HANWANG_ART_MASTER_HD: | ||
174 | p = (data[7] >> 6) | (data[6] << 2); | ||
175 | break; | ||
176 | |||
177 | default: | ||
178 | p = 0; | ||
179 | break; | ||
180 | } | ||
181 | |||
182 | input_report_abs(input_dev, ABS_X, | ||
183 | le16_to_cpup((__le16 *)&x)); | ||
184 | input_report_abs(input_dev, ABS_Y, | ||
185 | le16_to_cpup((__le16 *)&y)); | ||
186 | input_report_abs(input_dev, ABS_PRESSURE, | ||
187 | le16_to_cpup((__le16 *)&p)); | ||
188 | input_report_abs(input_dev, ABS_TILT_X, data[7] & 0x3f); | ||
189 | input_report_abs(input_dev, ABS_TILT_Y, data[8] & 0x7f); | ||
190 | input_report_key(input_dev, BTN_STYLUS, data[1] & 0x02); | ||
191 | input_report_key(input_dev, BTN_STYLUS2, data[1] & 0x04); | ||
192 | break; | ||
193 | } | ||
194 | input_report_abs(input_dev, ABS_MISC, hanwang->current_id); | ||
195 | input_event(input_dev, EV_MSC, MSC_SERIAL, | ||
196 | hanwang->features->pid); | ||
197 | break; | ||
198 | |||
199 | case 0x0c: | ||
200 | /* roll wheel */ | ||
201 | hanwang->current_id = PAD_DEVICE_ID; | ||
202 | |||
203 | switch (type) { | ||
204 | case HANWANG_ART_MASTER_III: | ||
205 | input_report_key(input_dev, BTN_TOOL_FINGER, data[1] || | ||
206 | data[2] || data[3]); | ||
207 | input_report_abs(input_dev, ABS_WHEEL, data[1]); | ||
208 | input_report_key(input_dev, BTN_0, data[2]); | ||
209 | for (i = 0; i < 8; i++) | ||
210 | input_report_key(input_dev, | ||
211 | BTN_1 + i, data[3] & (1 << i)); | ||
212 | break; | ||
213 | |||
214 | case HANWANG_ART_MASTER_HD: | ||
215 | input_report_key(input_dev, BTN_TOOL_FINGER, data[1] || | ||
216 | data[2] || data[3] || data[4] || | ||
217 | data[5] || data[6]); | ||
218 | input_report_abs(input_dev, ABS_RX, | ||
219 | ((data[1] & 0x1f) << 8) | data[2]); | ||
220 | input_report_abs(input_dev, ABS_RY, | ||
221 | ((data[3] & 0x1f) << 8) | data[4]); | ||
222 | input_report_key(input_dev, BTN_0, data[5] & 0x01); | ||
223 | for (i = 0; i < 4; i++) { | ||
224 | input_report_key(input_dev, | ||
225 | BTN_1 + i, data[5] & (1 << i)); | ||
226 | input_report_key(input_dev, | ||
227 | BTN_5 + i, data[6] & (1 << i)); | ||
228 | } | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | input_report_abs(input_dev, ABS_MISC, hanwang->current_id); | ||
233 | input_event(input_dev, EV_MSC, MSC_SERIAL, 0xffffffff); | ||
234 | break; | ||
235 | |||
236 | default: | ||
237 | dev_dbg(&dev->dev, "error packet %02x ", data[0]); | ||
238 | break; | ||
239 | } | ||
240 | |||
241 | input_sync(input_dev); | ||
242 | } | ||
243 | |||
244 | static void hanwang_irq(struct urb *urb) | ||
245 | { | ||
246 | struct hanwang *hanwang = urb->context; | ||
247 | struct usb_device *dev = hanwang->usbdev; | ||
248 | int retval; | ||
249 | |||
250 | switch (urb->status) { | ||
251 | case 0: | ||
252 | /* success */; | ||
253 | hanwang_parse_packet(hanwang); | ||
254 | break; | ||
255 | case -ECONNRESET: | ||
256 | case -ENOENT: | ||
257 | case -ESHUTDOWN: | ||
258 | /* this urb is terminated, clean up */ | ||
259 | dev_err(&dev->dev, "%s - urb shutting down with status: %d", | ||
260 | __func__, urb->status); | ||
261 | return; | ||
262 | default: | ||
263 | dev_err(&dev->dev, "%s - nonzero urb status received: %d", | ||
264 | __func__, urb->status); | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
269 | if (retval) | ||
270 | dev_err(&dev->dev, "%s - usb_submit_urb failed with result %d", | ||
271 | __func__, retval); | ||
272 | } | ||
273 | |||
274 | static int hanwang_open(struct input_dev *dev) | ||
275 | { | ||
276 | struct hanwang *hanwang = input_get_drvdata(dev); | ||
277 | |||
278 | hanwang->irq->dev = hanwang->usbdev; | ||
279 | if (usb_submit_urb(hanwang->irq, GFP_KERNEL)) | ||
280 | return -EIO; | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void hanwang_close(struct input_dev *dev) | ||
286 | { | ||
287 | struct hanwang *hanwang = input_get_drvdata(dev); | ||
288 | |||
289 | usb_kill_urb(hanwang->irq); | ||
290 | } | ||
291 | |||
292 | static bool get_features(struct usb_device *dev, struct hanwang *hanwang) | ||
293 | { | ||
294 | int i; | ||
295 | |||
296 | for (i = 0; i < ARRAY_SIZE(features_array); i++) { | ||
297 | if (le16_to_cpu(dev->descriptor.idProduct) == | ||
298 | features_array[i].pid) { | ||
299 | hanwang->features = &features_array[i]; | ||
300 | return true; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | return false; | ||
305 | } | ||
306 | |||
307 | |||
308 | static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
309 | { | ||
310 | struct usb_device *dev = interface_to_usbdev(intf); | ||
311 | struct usb_endpoint_descriptor *endpoint; | ||
312 | struct hanwang *hanwang; | ||
313 | struct input_dev *input_dev; | ||
314 | int error; | ||
315 | int i; | ||
316 | |||
317 | hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL); | ||
318 | input_dev = input_allocate_device(); | ||
319 | if (!hanwang || !input_dev) { | ||
320 | error = -ENOMEM; | ||
321 | goto fail1; | ||
322 | } | ||
323 | |||
324 | if (!get_features(dev, hanwang)) { | ||
325 | error = -ENXIO; | ||
326 | goto fail1; | ||
327 | } | ||
328 | |||
329 | hanwang->data = usb_alloc_coherent(dev, hanwang->features->pkg_len, | ||
330 | GFP_KERNEL, &hanwang->data_dma); | ||
331 | if (!hanwang->data) { | ||
332 | error = -ENOMEM; | ||
333 | goto fail1; | ||
334 | } | ||
335 | |||
336 | hanwang->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
337 | if (!hanwang->irq) { | ||
338 | error = -ENOMEM; | ||
339 | goto fail2; | ||
340 | } | ||
341 | |||
342 | hanwang->usbdev = dev; | ||
343 | hanwang->dev = input_dev; | ||
344 | |||
345 | usb_make_path(dev, hanwang->phys, sizeof(hanwang->phys)); | ||
346 | strlcat(hanwang->phys, "/input0", sizeof(hanwang->phys)); | ||
347 | |||
348 | strlcpy(hanwang->name, hanwang->features->name, sizeof(hanwang->name)); | ||
349 | input_dev->name = hanwang->name; | ||
350 | input_dev->phys = hanwang->phys; | ||
351 | usb_to_input_id(dev, &input_dev->id); | ||
352 | input_dev->dev.parent = &intf->dev; | ||
353 | |||
354 | input_set_drvdata(input_dev, hanwang); | ||
355 | |||
356 | input_dev->open = hanwang_open; | ||
357 | input_dev->close = hanwang_close; | ||
358 | |||
359 | for (i = 0; i < ARRAY_SIZE(hw_eventtypes); ++i) | ||
360 | __set_bit(hw_eventtypes[i], input_dev->evbit); | ||
361 | |||
362 | for (i = 0; i < ARRAY_SIZE(hw_absevents); ++i) | ||
363 | __set_bit(hw_absevents[i], input_dev->absbit); | ||
364 | |||
365 | for (i = 0; i < ARRAY_SIZE(hw_btnevents); ++i) | ||
366 | __set_bit(hw_btnevents[i], input_dev->keybit); | ||
367 | |||
368 | for (i = 0; i < ARRAY_SIZE(hw_mscevents); ++i) | ||
369 | __set_bit(hw_mscevents[i], input_dev->mscbit); | ||
370 | |||
371 | input_set_abs_params(input_dev, ABS_X, | ||
372 | 0, hanwang->features->max_x, 4, 0); | ||
373 | input_set_abs_params(input_dev, ABS_Y, | ||
374 | 0, hanwang->features->max_y, 4, 0); | ||
375 | input_set_abs_params(input_dev, ABS_TILT_X, | ||
376 | 0, hanwang->features->max_tilt_x, 0, 0); | ||
377 | input_set_abs_params(input_dev, ABS_TILT_Y, | ||
378 | 0, hanwang->features->max_tilt_y, 0, 0); | ||
379 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
380 | 0, hanwang->features->max_pressure, 0, 0); | ||
381 | |||
382 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
383 | usb_fill_int_urb(hanwang->irq, dev, | ||
384 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
385 | hanwang->data, hanwang->features->pkg_len, | ||
386 | hanwang_irq, hanwang, endpoint->bInterval); | ||
387 | hanwang->irq->transfer_dma = hanwang->data_dma; | ||
388 | hanwang->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
389 | |||
390 | error = input_register_device(hanwang->dev); | ||
391 | if (error) | ||
392 | goto fail3; | ||
393 | |||
394 | usb_set_intfdata(intf, hanwang); | ||
395 | |||
396 | return 0; | ||
397 | |||
398 | fail3: usb_free_urb(hanwang->irq); | ||
399 | fail2: usb_free_coherent(dev, hanwang->features->pkg_len, | ||
400 | hanwang->data, hanwang->data_dma); | ||
401 | fail1: input_free_device(input_dev); | ||
402 | kfree(hanwang); | ||
403 | return error; | ||
404 | |||
405 | } | ||
406 | |||
407 | static void hanwang_disconnect(struct usb_interface *intf) | ||
408 | { | ||
409 | struct hanwang *hanwang = usb_get_intfdata(intf); | ||
410 | |||
411 | input_unregister_device(hanwang->dev); | ||
412 | usb_free_urb(hanwang->irq); | ||
413 | usb_free_coherent(interface_to_usbdev(intf), | ||
414 | hanwang->features->pkg_len, hanwang->data, | ||
415 | hanwang->data_dma); | ||
416 | kfree(hanwang); | ||
417 | usb_set_intfdata(intf, NULL); | ||
418 | } | ||
419 | |||
420 | static const struct usb_device_id hanwang_ids[] = { | ||
421 | { HANWANG_TABLET_DEVICE(USB_VENDOR_ID_HANWANG, HANWANG_TABLET_INT_CLASS, | ||
422 | HANWANG_TABLET_INT_SUB_CLASS, HANWANG_TABLET_INT_PROTOCOL) }, | ||
423 | {} | ||
424 | }; | ||
425 | |||
426 | MODULE_DEVICE_TABLE(usb, hanwang_ids); | ||
427 | |||
428 | static struct usb_driver hanwang_driver = { | ||
429 | .name = "hanwang", | ||
430 | .probe = hanwang_probe, | ||
431 | .disconnect = hanwang_disconnect, | ||
432 | .id_table = hanwang_ids, | ||
433 | }; | ||
434 | |||
435 | static int __init hanwang_init(void) | ||
436 | { | ||
437 | return usb_register(&hanwang_driver); | ||
438 | } | ||
439 | |||
440 | static void __exit hanwang_exit(void) | ||
441 | { | ||
442 | usb_deregister(&hanwang_driver); | ||
443 | } | ||
444 | |||
445 | module_init(hanwang_init); | ||
446 | module_exit(hanwang_exit); | ||
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 284dfaab6b8c..de5adb109030 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -118,6 +118,7 @@ struct wacom { | |||
118 | extern const struct usb_device_id wacom_ids[]; | 118 | extern const struct usb_device_id wacom_ids[]; |
119 | 119 | ||
120 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); | 120 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); |
121 | void wacom_setup_device_quirks(struct wacom_features *features); | ||
121 | void wacom_setup_input_capabilities(struct input_dev *input_dev, | 122 | void wacom_setup_input_capabilities(struct input_dev *input_dev, |
122 | struct wacom_wac *wacom_wac); | 123 | struct wacom_wac *wacom_wac); |
123 | #endif | 124 | #endif |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b35876ee6908..fc381498b798 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -120,14 +120,16 @@ static int wacom_open(struct input_dev *dev) | |||
120 | 120 | ||
121 | out: | 121 | out: |
122 | mutex_unlock(&wacom->lock); | 122 | mutex_unlock(&wacom->lock); |
123 | if (retval) | 123 | usb_autopm_put_interface(wacom->intf); |
124 | usb_autopm_put_interface(wacom->intf); | ||
125 | return retval; | 124 | return retval; |
126 | } | 125 | } |
127 | 126 | ||
128 | static void wacom_close(struct input_dev *dev) | 127 | static void wacom_close(struct input_dev *dev) |
129 | { | 128 | { |
130 | struct wacom *wacom = input_get_drvdata(dev); | 129 | struct wacom *wacom = input_get_drvdata(dev); |
130 | int autopm_error; | ||
131 | |||
132 | autopm_error = usb_autopm_get_interface(wacom->intf); | ||
131 | 133 | ||
132 | mutex_lock(&wacom->lock); | 134 | mutex_lock(&wacom->lock); |
133 | usb_kill_urb(wacom->irq); | 135 | usb_kill_urb(wacom->irq); |
@@ -135,7 +137,8 @@ static void wacom_close(struct input_dev *dev) | |||
135 | wacom->intf->needs_remote_wakeup = 0; | 137 | wacom->intf->needs_remote_wakeup = 0; |
136 | mutex_unlock(&wacom->lock); | 138 | mutex_unlock(&wacom->lock); |
137 | 139 | ||
138 | usb_autopm_put_interface(wacom->intf); | 140 | if (!autopm_error) |
141 | usb_autopm_put_interface(wacom->intf); | ||
139 | } | 142 | } |
140 | 143 | ||
141 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, | 144 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, |
@@ -196,17 +199,30 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
196 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 199 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
197 | features->device_type = BTN_TOOL_TRIPLETAP; | 200 | features->device_type = BTN_TOOL_TRIPLETAP; |
198 | } | 201 | } |
199 | features->x_max = | 202 | if (features->type == BAMBOO_PT) { |
200 | get_unaligned_le16(&report[i + 3]); | 203 | /* need to reset back */ |
201 | features->x_phy = | 204 | features->pktlen = WACOM_PKGLEN_BBTOUCH; |
202 | get_unaligned_le16(&report[i + 6]); | 205 | features->device_type = BTN_TOOL_TRIPLETAP; |
203 | features->unit = report[i + 9]; | 206 | features->x_phy = |
204 | features->unitExpo = report[i + 11]; | 207 | get_unaligned_le16(&report[i + 5]); |
205 | i += 12; | 208 | features->x_max = |
209 | get_unaligned_le16(&report[i + 8]); | ||
210 | i += 15; | ||
211 | } else { | ||
212 | features->x_max = | ||
213 | get_unaligned_le16(&report[i + 3]); | ||
214 | features->x_phy = | ||
215 | get_unaligned_le16(&report[i + 6]); | ||
216 | features->unit = report[i + 9]; | ||
217 | features->unitExpo = report[i + 11]; | ||
218 | i += 12; | ||
219 | } | ||
206 | } else if (pen) { | 220 | } else if (pen) { |
207 | /* penabled only accepts exact bytes of data */ | 221 | /* penabled only accepts exact bytes of data */ |
208 | if (features->type == TABLETPC2FG) | 222 | if (features->type == TABLETPC2FG) |
209 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | 223 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; |
224 | if (features->type == BAMBOO_PT) | ||
225 | features->pktlen = WACOM_PKGLEN_BBFUN; | ||
210 | features->device_type = BTN_TOOL_PEN; | 226 | features->device_type = BTN_TOOL_PEN; |
211 | features->x_max = | 227 | features->x_max = |
212 | get_unaligned_le16(&report[i + 3]); | 228 | get_unaligned_le16(&report[i + 3]); |
@@ -235,6 +251,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
235 | features->y_phy = | 251 | features->y_phy = |
236 | get_unaligned_le16(&report[i + 6]); | 252 | get_unaligned_le16(&report[i + 6]); |
237 | i += 7; | 253 | i += 7; |
254 | } else if (features->type == BAMBOO_PT) { | ||
255 | /* need to reset back */ | ||
256 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | ||
257 | features->device_type = BTN_TOOL_TRIPLETAP; | ||
258 | features->y_phy = | ||
259 | get_unaligned_le16(&report[i + 3]); | ||
260 | features->y_max = | ||
261 | get_unaligned_le16(&report[i + 6]); | ||
262 | i += 12; | ||
238 | } else { | 263 | } else { |
239 | features->y_max = | 264 | features->y_max = |
240 | features->x_max; | 265 | features->x_max; |
@@ -246,6 +271,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
246 | /* penabled only accepts exact bytes of data */ | 271 | /* penabled only accepts exact bytes of data */ |
247 | if (features->type == TABLETPC2FG) | 272 | if (features->type == TABLETPC2FG) |
248 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | 273 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; |
274 | if (features->type == BAMBOO_PT) | ||
275 | features->pktlen = WACOM_PKGLEN_BBFUN; | ||
249 | features->device_type = BTN_TOOL_PEN; | 276 | features->device_type = BTN_TOOL_PEN; |
250 | features->y_max = | 277 | features->y_max = |
251 | get_unaligned_le16(&report[i + 3]); | 278 | get_unaligned_le16(&report[i + 3]); |
@@ -296,8 +323,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
296 | if (!rep_data) | 323 | if (!rep_data) |
297 | return error; | 324 | return error; |
298 | 325 | ||
299 | /* ask to report tablet data if it is 2FGT or not a Tablet PC */ | 326 | /* ask to report tablet data if it is 2FGT Tablet PC or |
300 | if (features->device_type == BTN_TOOL_TRIPLETAP) { | 327 | * not a Tablet PC */ |
328 | if (features->type == TABLETPC2FG) { | ||
301 | do { | 329 | do { |
302 | rep_data[0] = 3; | 330 | rep_data[0] = 3; |
303 | rep_data[1] = 4; | 331 | rep_data[1] = 4; |
@@ -309,7 +337,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
309 | WAC_HID_FEATURE_REPORT, report_id, | 337 | WAC_HID_FEATURE_REPORT, report_id, |
310 | rep_data, 3); | 338 | rep_data, 3); |
311 | } while ((error < 0 || rep_data[1] != 4) && limit++ < 5); | 339 | } while ((error < 0 || rep_data[1] != 4) && limit++ < 5); |
312 | } else if (features->type != TABLETPC && features->type != TABLETPC2FG) { | 340 | } else if (features->type != TABLETPC) { |
313 | do { | 341 | do { |
314 | rep_data[0] = 2; | 342 | rep_data[0] = 2; |
315 | rep_data[1] = 2; | 343 | rep_data[1] = 2; |
@@ -334,11 +362,16 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | |||
334 | struct usb_host_interface *interface = intf->cur_altsetting; | 362 | struct usb_host_interface *interface = intf->cur_altsetting; |
335 | struct hid_descriptor *hid_desc; | 363 | struct hid_descriptor *hid_desc; |
336 | 364 | ||
337 | /* default device to penabled */ | 365 | /* default features */ |
338 | features->device_type = BTN_TOOL_PEN; | 366 | features->device_type = BTN_TOOL_PEN; |
339 | 367 | features->x_fuzz = 4; | |
340 | /* only Tablet PCs need to retrieve the info */ | 368 | features->y_fuzz = 4; |
341 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG)) | 369 | features->pressure_fuzz = 0; |
370 | features->distance_fuzz = 0; | ||
371 | |||
372 | /* only Tablet PCs and Bamboo P&T need to retrieve the info */ | ||
373 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && | ||
374 | (features->type != BAMBOO_PT)) | ||
342 | goto out; | 375 | goto out; |
343 | 376 | ||
344 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | 377 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { |
@@ -353,12 +386,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | |||
353 | if (error) | 386 | if (error) |
354 | goto out; | 387 | goto out; |
355 | 388 | ||
356 | /* touch device found but size is not defined. use default */ | ||
357 | if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { | ||
358 | features->x_max = 1023; | ||
359 | features->y_max = 1023; | ||
360 | } | ||
361 | |||
362 | out: | 389 | out: |
363 | return error; | 390 | return error; |
364 | } | 391 | } |
@@ -494,9 +521,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
494 | if (error) | 521 | if (error) |
495 | goto fail2; | 522 | goto fail2; |
496 | 523 | ||
524 | wacom_setup_device_quirks(features); | ||
525 | |||
497 | strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); | 526 | strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); |
498 | 527 | ||
499 | if (features->type == TABLETPC || features->type == TABLETPC2FG) { | 528 | if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { |
500 | /* Append the device type to the name */ | 529 | /* Append the device type to the name */ |
501 | strlcat(wacom_wac->name, | 530 | strlcat(wacom_wac->name, |
502 | features->device_type == BTN_TOOL_PEN ? | 531 | features->device_type == BTN_TOOL_PEN ? |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 47fd7a041c52..b3252ef1e279 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -857,6 +857,134 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
857 | return retval; | 857 | return retval; |
858 | } | 858 | } |
859 | 859 | ||
860 | static int wacom_bpt_touch(struct wacom_wac *wacom) | ||
861 | { | ||
862 | struct wacom_features *features = &wacom->features; | ||
863 | struct input_dev *input = wacom->input; | ||
864 | unsigned char *data = wacom->data; | ||
865 | int sp = 0, sx = 0, sy = 0, count = 0; | ||
866 | int i; | ||
867 | |||
868 | for (i = 0; i < 2; i++) { | ||
869 | int p = data[9 * i + 2]; | ||
870 | input_mt_slot(input, i); | ||
871 | /* | ||
872 | * Touch events need to be disabled while stylus is | ||
873 | * in proximity because user's hand is resting on touchpad | ||
874 | * and sending unwanted events. User expects tablet buttons | ||
875 | * to continue working though. | ||
876 | */ | ||
877 | if (p && !wacom->shared->stylus_in_proximity) { | ||
878 | int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; | ||
879 | int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; | ||
880 | if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { | ||
881 | x <<= 5; | ||
882 | y <<= 5; | ||
883 | } | ||
884 | input_report_abs(input, ABS_MT_PRESSURE, p); | ||
885 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
886 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
887 | if (wacom->id[i] < 0) | ||
888 | wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID; | ||
889 | if (!count++) | ||
890 | sp = p, sx = x, sy = y; | ||
891 | } else { | ||
892 | wacom->id[i] = -1; | ||
893 | } | ||
894 | input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]); | ||
895 | } | ||
896 | |||
897 | input_report_key(input, BTN_TOUCH, count > 0); | ||
898 | input_report_key(input, BTN_TOOL_FINGER, count == 1); | ||
899 | input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2); | ||
900 | |||
901 | input_report_abs(input, ABS_PRESSURE, sp); | ||
902 | input_report_abs(input, ABS_X, sx); | ||
903 | input_report_abs(input, ABS_Y, sy); | ||
904 | |||
905 | input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); | ||
906 | input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); | ||
907 | input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); | ||
908 | input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0); | ||
909 | |||
910 | input_sync(input); | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static int wacom_bpt_pen(struct wacom_wac *wacom) | ||
916 | { | ||
917 | struct input_dev *input = wacom->input; | ||
918 | unsigned char *data = wacom->data; | ||
919 | int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; | ||
920 | |||
921 | /* | ||
922 | * Similar to Graphire protocol, data[1] & 0x20 is proximity and | ||
923 | * data[1] & 0x18 is tool ID. 0x30 is safety check to ignore | ||
924 | * 2 unused tool ID's. | ||
925 | */ | ||
926 | prox = (data[1] & 0x30) == 0x30; | ||
927 | |||
928 | /* | ||
929 | * All reports shared between PEN and RUBBER tool must be | ||
930 | * forced to a known starting value (zero) when transitioning to | ||
931 | * out-of-prox. | ||
932 | * | ||
933 | * If not reset then, to userspace, it will look like lost events | ||
934 | * if new tool comes in-prox with same values as previous tool sent. | ||
935 | * | ||
936 | * Hardware does report zero in most out-of-prox cases but not all. | ||
937 | */ | ||
938 | if (prox) { | ||
939 | if (!wacom->shared->stylus_in_proximity) { | ||
940 | if (data[1] & 0x08) { | ||
941 | wacom->tool[0] = BTN_TOOL_RUBBER; | ||
942 | wacom->id[0] = ERASER_DEVICE_ID; | ||
943 | } else { | ||
944 | wacom->tool[0] = BTN_TOOL_PEN; | ||
945 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
946 | } | ||
947 | wacom->shared->stylus_in_proximity = true; | ||
948 | } | ||
949 | x = le16_to_cpup((__le16 *)&data[2]); | ||
950 | y = le16_to_cpup((__le16 *)&data[4]); | ||
951 | p = le16_to_cpup((__le16 *)&data[6]); | ||
952 | d = data[8]; | ||
953 | pen = data[1] & 0x01; | ||
954 | btn1 = data[1] & 0x02; | ||
955 | btn2 = data[1] & 0x04; | ||
956 | } | ||
957 | |||
958 | input_report_key(input, BTN_TOUCH, pen); | ||
959 | input_report_key(input, BTN_STYLUS, btn1); | ||
960 | input_report_key(input, BTN_STYLUS2, btn2); | ||
961 | |||
962 | input_report_abs(input, ABS_X, x); | ||
963 | input_report_abs(input, ABS_Y, y); | ||
964 | input_report_abs(input, ABS_PRESSURE, p); | ||
965 | input_report_abs(input, ABS_DISTANCE, d); | ||
966 | |||
967 | if (!prox) { | ||
968 | wacom->id[0] = 0; | ||
969 | wacom->shared->stylus_in_proximity = false; | ||
970 | } | ||
971 | |||
972 | input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */ | ||
973 | input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */ | ||
974 | |||
975 | return 1; | ||
976 | } | ||
977 | |||
978 | static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) | ||
979 | { | ||
980 | if (len == WACOM_PKGLEN_BBTOUCH) | ||
981 | return wacom_bpt_touch(wacom); | ||
982 | else if (len == WACOM_PKGLEN_BBFUN) | ||
983 | return wacom_bpt_pen(wacom); | ||
984 | |||
985 | return 0; | ||
986 | } | ||
987 | |||
860 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | 988 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) |
861 | { | 989 | { |
862 | bool sync; | 990 | bool sync; |
@@ -902,6 +1030,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
902 | sync = wacom_tpc_irq(wacom_wac, len); | 1030 | sync = wacom_tpc_irq(wacom_wac, len); |
903 | break; | 1031 | break; |
904 | 1032 | ||
1033 | case BAMBOO_PT: | ||
1034 | sync = wacom_bpt_irq(wacom_wac, len); | ||
1035 | break; | ||
1036 | |||
905 | default: | 1037 | default: |
906 | sync = false; | 1038 | sync = false; |
907 | break; | 1039 | break; |
@@ -911,26 +1043,17 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
911 | input_sync(wacom_wac->input); | 1043 | input_sync(wacom_wac->input); |
912 | } | 1044 | } |
913 | 1045 | ||
914 | static void wacom_setup_intuos(struct wacom_wac *wacom_wac) | 1046 | static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) |
915 | { | 1047 | { |
916 | struct input_dev *input_dev = wacom_wac->input; | 1048 | struct input_dev *input_dev = wacom_wac->input; |
917 | 1049 | ||
918 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); | 1050 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); |
919 | input_set_capability(input_dev, EV_REL, REL_WHEEL); | ||
920 | |||
921 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
922 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
923 | __set_bit(BTN_MIDDLE, input_dev->keybit); | ||
924 | __set_bit(BTN_SIDE, input_dev->keybit); | ||
925 | __set_bit(BTN_EXTRA, input_dev->keybit); | ||
926 | 1051 | ||
927 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | 1052 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
928 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 1053 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
929 | __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); | ||
930 | __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); | 1054 | __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); |
931 | __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); | 1055 | __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); |
932 | __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); | 1056 | __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); |
933 | __set_bit(BTN_TOOL_LENS, input_dev->keybit); | ||
934 | __set_bit(BTN_STYLUS, input_dev->keybit); | 1057 | __set_bit(BTN_STYLUS, input_dev->keybit); |
935 | __set_bit(BTN_STYLUS2, input_dev->keybit); | 1058 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
936 | 1059 | ||
@@ -939,10 +1062,55 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac) | |||
939 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | 1062 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); |
940 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | 1063 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); |
941 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | 1064 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); |
1065 | } | ||
1066 | |||
1067 | static void wacom_setup_intuos(struct wacom_wac *wacom_wac) | ||
1068 | { | ||
1069 | struct input_dev *input_dev = wacom_wac->input; | ||
1070 | |||
1071 | input_set_capability(input_dev, EV_REL, REL_WHEEL); | ||
1072 | |||
1073 | wacom_setup_cintiq(wacom_wac); | ||
1074 | |||
1075 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
1076 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
1077 | __set_bit(BTN_MIDDLE, input_dev->keybit); | ||
1078 | __set_bit(BTN_SIDE, input_dev->keybit); | ||
1079 | __set_bit(BTN_EXTRA, input_dev->keybit); | ||
1080 | __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); | ||
1081 | __set_bit(BTN_TOOL_LENS, input_dev->keybit); | ||
1082 | |||
942 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | 1083 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); |
943 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | 1084 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); |
944 | } | 1085 | } |
945 | 1086 | ||
1087 | void wacom_setup_device_quirks(struct wacom_features *features) | ||
1088 | { | ||
1089 | |||
1090 | /* touch device found but size is not defined. use default */ | ||
1091 | if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { | ||
1092 | features->x_max = 1023; | ||
1093 | features->y_max = 1023; | ||
1094 | } | ||
1095 | |||
1096 | /* these device have multiple inputs */ | ||
1097 | if (features->type == TABLETPC || features->type == TABLETPC2FG || | ||
1098 | features->type == BAMBOO_PT) | ||
1099 | features->quirks |= WACOM_QUIRK_MULTI_INPUT; | ||
1100 | |||
1101 | /* quirks for bamboo touch */ | ||
1102 | if (features->type == BAMBOO_PT && | ||
1103 | features->device_type == BTN_TOOL_TRIPLETAP) { | ||
1104 | features->x_max <<= 5; | ||
1105 | features->y_max <<= 5; | ||
1106 | features->x_fuzz <<= 5; | ||
1107 | features->y_fuzz <<= 5; | ||
1108 | features->pressure_max = 256; | ||
1109 | features->pressure_fuzz = 16; | ||
1110 | features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES; | ||
1111 | } | ||
1112 | } | ||
1113 | |||
946 | void wacom_setup_input_capabilities(struct input_dev *input_dev, | 1114 | void wacom_setup_input_capabilities(struct input_dev *input_dev, |
947 | struct wacom_wac *wacom_wac) | 1115 | struct wacom_wac *wacom_wac) |
948 | { | 1116 | { |
@@ -953,9 +1121,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
953 | 1121 | ||
954 | __set_bit(BTN_TOUCH, input_dev->keybit); | 1122 | __set_bit(BTN_TOUCH, input_dev->keybit); |
955 | 1123 | ||
956 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); | 1124 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, |
957 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); | 1125 | features->x_fuzz, 0); |
958 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); | 1126 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, |
1127 | features->y_fuzz, 0); | ||
1128 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, | ||
1129 | features->pressure_fuzz, 0); | ||
959 | 1130 | ||
960 | __set_bit(ABS_MISC, input_dev->absbit); | 1131 | __set_bit(ABS_MISC, input_dev->absbit); |
961 | 1132 | ||
@@ -1005,9 +1176,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1005 | __set_bit(BTN_9, input_dev->keybit); | 1176 | __set_bit(BTN_9, input_dev->keybit); |
1006 | /* fall through */ | 1177 | /* fall through */ |
1007 | 1178 | ||
1179 | case CINTIQ: | ||
1180 | for (i = 0; i < 8; i++) | ||
1181 | __set_bit(BTN_0 + i, input_dev->keybit); | ||
1182 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
1183 | |||
1184 | input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); | ||
1185 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); | ||
1186 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
1187 | wacom_setup_cintiq(wacom_wac); | ||
1188 | break; | ||
1189 | |||
1008 | case INTUOS3: | 1190 | case INTUOS3: |
1009 | case INTUOS3L: | 1191 | case INTUOS3L: |
1010 | case CINTIQ: | ||
1011 | __set_bit(BTN_4, input_dev->keybit); | 1192 | __set_bit(BTN_4, input_dev->keybit); |
1012 | __set_bit(BTN_5, input_dev->keybit); | 1193 | __set_bit(BTN_5, input_dev->keybit); |
1013 | __set_bit(BTN_6, input_dev->keybit); | 1194 | __set_bit(BTN_6, input_dev->keybit); |
@@ -1078,6 +1259,38 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1078 | case PENPARTNER: | 1259 | case PENPARTNER: |
1079 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | 1260 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
1080 | break; | 1261 | break; |
1262 | |||
1263 | case BAMBOO_PT: | ||
1264 | __clear_bit(ABS_MISC, input_dev->absbit); | ||
1265 | |||
1266 | if (features->device_type == BTN_TOOL_TRIPLETAP) { | ||
1267 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
1268 | __set_bit(BTN_FORWARD, input_dev->keybit); | ||
1269 | __set_bit(BTN_BACK, input_dev->keybit); | ||
1270 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
1271 | |||
1272 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
1273 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
1274 | |||
1275 | input_mt_create_slots(input_dev, 2); | ||
1276 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
1277 | 0, features->x_max, | ||
1278 | features->x_fuzz, 0); | ||
1279 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
1280 | 0, features->y_max, | ||
1281 | features->y_fuzz, 0); | ||
1282 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | ||
1283 | 0, features->pressure_max, | ||
1284 | features->pressure_fuzz, 0); | ||
1285 | input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, | ||
1286 | MAX_TRACKING_ID, 0, 0); | ||
1287 | } else if (features->device_type == BTN_TOOL_PEN) { | ||
1288 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | ||
1289 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | ||
1290 | __set_bit(BTN_STYLUS, input_dev->keybit); | ||
1291 | __set_bit(BTN_STYLUS2, input_dev->keybit); | ||
1292 | } | ||
1293 | break; | ||
1081 | } | 1294 | } |
1082 | } | 1295 | } |
1083 | 1296 | ||
@@ -1215,6 +1428,14 @@ static const struct wacom_features wacom_features_0xE3 = | |||
1215 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; | 1428 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; |
1216 | static const struct wacom_features wacom_features_0x47 = | 1429 | static const struct wacom_features wacom_features_0x47 = |
1217 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; | 1430 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; |
1431 | static struct wacom_features wacom_features_0xD0 = | ||
1432 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; | ||
1433 | static struct wacom_features wacom_features_0xD1 = | ||
1434 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; | ||
1435 | static struct wacom_features wacom_features_0xD2 = | ||
1436 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; | ||
1437 | static struct wacom_features wacom_features_0xD3 = | ||
1438 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; | ||
1218 | 1439 | ||
1219 | #define USB_DEVICE_WACOM(prod) \ | 1440 | #define USB_DEVICE_WACOM(prod) \ |
1220 | USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ | 1441 | USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ |
@@ -1279,6 +1500,10 @@ const struct usb_device_id wacom_ids[] = { | |||
1279 | { USB_DEVICE_WACOM(0xC6) }, | 1500 | { USB_DEVICE_WACOM(0xC6) }, |
1280 | { USB_DEVICE_WACOM(0xC7) }, | 1501 | { USB_DEVICE_WACOM(0xC7) }, |
1281 | { USB_DEVICE_WACOM(0xCE) }, | 1502 | { USB_DEVICE_WACOM(0xCE) }, |
1503 | { USB_DEVICE_WACOM(0xD0) }, | ||
1504 | { USB_DEVICE_WACOM(0xD1) }, | ||
1505 | { USB_DEVICE_WACOM(0xD2) }, | ||
1506 | { USB_DEVICE_WACOM(0xD3) }, | ||
1282 | { USB_DEVICE_WACOM(0xF0) }, | 1507 | { USB_DEVICE_WACOM(0xF0) }, |
1283 | { USB_DEVICE_WACOM(0xCC) }, | 1508 | { USB_DEVICE_WACOM(0xCC) }, |
1284 | { USB_DEVICE_WACOM(0x90) }, | 1509 | { USB_DEVICE_WACOM(0x90) }, |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 99e1a54cd305..00ca01541d89 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define WACOM_PKGLEN_INTUOS 10 | 21 | #define WACOM_PKGLEN_INTUOS 10 |
22 | #define WACOM_PKGLEN_TPC1FG 5 | 22 | #define WACOM_PKGLEN_TPC1FG 5 |
23 | #define WACOM_PKGLEN_TPC2FG 14 | 23 | #define WACOM_PKGLEN_TPC2FG 14 |
24 | #define WACOM_PKGLEN_BBTOUCH 20 | ||
24 | 25 | ||
25 | /* device IDs */ | 26 | /* device IDs */ |
26 | #define STYLUS_DEVICE_ID 0x02 | 27 | #define STYLUS_DEVICE_ID 0x02 |
@@ -37,6 +38,13 @@ | |||
37 | #define WACOM_REPORT_TPC1FG 6 | 38 | #define WACOM_REPORT_TPC1FG 6 |
38 | #define WACOM_REPORT_TPC2FG 13 | 39 | #define WACOM_REPORT_TPC2FG 13 |
39 | 40 | ||
41 | /* device quirks */ | ||
42 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 | ||
43 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 | ||
44 | |||
45 | /* largest reported tracking id */ | ||
46 | #define MAX_TRACKING_ID 0xfff | ||
47 | |||
40 | enum { | 48 | enum { |
41 | PENPARTNER = 0, | 49 | PENPARTNER = 0, |
42 | GRAPHIRE, | 50 | GRAPHIRE, |
@@ -44,6 +52,7 @@ enum { | |||
44 | PTU, | 52 | PTU, |
45 | PL, | 53 | PL, |
46 | DTU, | 54 | DTU, |
55 | BAMBOO_PT, | ||
47 | INTUOS, | 56 | INTUOS, |
48 | INTUOS3S, | 57 | INTUOS3S, |
49 | INTUOS3, | 58 | INTUOS3, |
@@ -73,6 +82,11 @@ struct wacom_features { | |||
73 | int y_phy; | 82 | int y_phy; |
74 | unsigned char unit; | 83 | unsigned char unit; |
75 | unsigned char unitExpo; | 84 | unsigned char unitExpo; |
85 | int x_fuzz; | ||
86 | int y_fuzz; | ||
87 | int pressure_fuzz; | ||
88 | int distance_fuzz; | ||
89 | unsigned quirks; | ||
76 | }; | 90 | }; |
77 | 91 | ||
78 | struct wacom_shared { | 92 | struct wacom_shared { |
@@ -86,6 +100,7 @@ struct wacom_wac { | |||
86 | int id[3]; | 100 | int id[3]; |
87 | __u32 serial[2]; | 101 | __u32 serial[2]; |
88 | int last_finger; | 102 | int last_finger; |
103 | int trk_id; | ||
89 | struct wacom_features features; | 104 | struct wacom_features features; |
90 | struct wacom_shared *shared; | 105 | struct wacom_shared *shared; |
91 | struct input_dev *input; | 106 | struct input_dev *input; |