]> Pileus Git - ~andy/linux/blob - drivers/hid/hid-wacom.c
HID: wacom: Initial driver for Wacom Intuos4 Wireless (Bluetooth)
[~andy/linux] / drivers / hid / hid-wacom.c
1 /*
2  *  Bluetooth Wacom Tablet support
3  *
4  *  Copyright (c) 1999 Andreas Gal
5  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7  *  Copyright (c) 2006-2007 Jiri Kosina
8  *  Copyright (c) 2007 Paul Walmsley
9  *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
10  *  Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
11  *  Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
12  *  Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu>
13  */
14
15 /*
16  * This program is free software; you can redistribute it and/or modify it
17  * under the terms of the GNU General Public License as published by the Free
18  * Software Foundation; either version 2 of the License, or (at your option)
19  * any later version.
20  */
21
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24 #include <linux/device.h>
25 #include <linux/hid.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
29 #include <linux/power_supply.h>
30 #endif
31
32 #include "hid-ids.h"
33
34 struct wacom_data {
35         __u16 tool;
36         unsigned char butstate;
37         __u8 features;
38         unsigned char high_speed;
39 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
40         int battery_capacity;
41         struct power_supply battery;
42         struct power_supply ac;
43 #endif
44 };
45
46 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
47 /*percent of battery capacity, 0 means AC online*/
48 static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
49
50 static enum power_supply_property wacom_battery_props[] = {
51         POWER_SUPPLY_PROP_PRESENT,
52         POWER_SUPPLY_PROP_CAPACITY
53 };
54
55 static enum power_supply_property wacom_ac_props[] = {
56         POWER_SUPPLY_PROP_PRESENT,
57         POWER_SUPPLY_PROP_ONLINE
58 };
59
60 static int wacom_battery_get_property(struct power_supply *psy,
61                                 enum power_supply_property psp,
62                                 union power_supply_propval *val)
63 {
64         struct wacom_data *wdata = container_of(psy,
65                                         struct wacom_data, battery);
66         int power_state = batcap[wdata->battery_capacity];
67         int ret = 0;
68
69         switch (psp) {
70         case POWER_SUPPLY_PROP_PRESENT:
71                 val->intval = 1;
72                 break;
73         case POWER_SUPPLY_PROP_CAPACITY:
74                 /* show 100% battery capacity when charging */
75                 if (power_state == 0)
76                         val->intval = 100;
77                 else
78                         val->intval = power_state;
79                 break;
80         default:
81                 ret = -EINVAL;
82                 break;
83         }
84         return ret;
85 }
86
87 static int wacom_ac_get_property(struct power_supply *psy,
88                                 enum power_supply_property psp,
89                                 union power_supply_propval *val)
90 {
91         struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
92         int power_state = batcap[wdata->battery_capacity];
93         int ret = 0;
94
95         switch (psp) {
96         case POWER_SUPPLY_PROP_PRESENT:
97                 /* fall through */
98         case POWER_SUPPLY_PROP_ONLINE:
99                 if (power_state == 0)
100                         val->intval = 1;
101                 else
102                         val->intval = 0;
103                 break;
104         default:
105                 ret = -EINVAL;
106                 break;
107         }
108         return ret;
109 }
110 #endif
111
112 static void wacom_set_features(struct hid_device *hdev)
113 {
114         int ret;
115         __u8 rep_data[2];
116
117         /*set high speed, tablet mode*/
118         rep_data[0] = 0x03;
119         rep_data[1] = 0x20;
120         ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
121                                 HID_FEATURE_REPORT);
122         return;
123 }
124
125 static void wacom_poke(struct hid_device *hdev, u8 speed)
126 {
127         struct wacom_data *wdata = hid_get_drvdata(hdev);
128         int limit, ret;
129         char rep_data[2];
130
131         rep_data[0] = 0x03 ; rep_data[1] = 0x00;
132         limit = 3;
133         do {
134                 ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
135                                 HID_FEATURE_REPORT);
136         } while (ret < 0 && limit-- > 0);
137
138         if (ret >= 0) {
139                 if (speed == 0)
140                         rep_data[0] = 0x05;
141                 else
142                         rep_data[0] = 0x06;
143
144                 rep_data[1] = 0x00;
145                 limit = 3;
146                 do {
147                         ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
148                                         HID_FEATURE_REPORT);
149                 } while (ret < 0 && limit-- > 0);
150
151                 if (ret >= 0) {
152                         wdata->high_speed = speed;
153                         return;
154                 }
155         }
156
157         /*
158          * Note that if the raw queries fail, it's not a hard failure and it
159          * is safe to continue
160          */
161         hid_warn(hdev, "failed to poke device, command %d, err %d\n",
162                  rep_data[0], ret);
163         return;
164 }
165
166 static ssize_t wacom_show_speed(struct device *dev,
167                                 struct device_attribute
168                                 *attr, char *buf)
169 {
170         struct wacom_data *wdata = dev_get_drvdata(dev);
171
172         return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
173 }
174
175 static ssize_t wacom_store_speed(struct device *dev,
176                                 struct device_attribute *attr,
177                                 const char *buf, size_t count)
178 {
179         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
180         int new_speed;
181
182         if (sscanf(buf, "%1d", &new_speed ) != 1)
183                 return -EINVAL;
184
185         if (new_speed == 0 || new_speed == 1) {
186                 wacom_poke(hdev, new_speed);
187                 return strnlen(buf, PAGE_SIZE);
188         } else
189                 return -EINVAL;
190 }
191
192 static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
193                 wacom_show_speed, wacom_store_speed);
194
195 static int wacom_gr_parse_report(struct hid_device *hdev,
196                         struct wacom_data *wdata,
197                         struct input_dev *input, unsigned char *data)
198 {
199         int tool, x, y, rw;
200
201         tool = 0;
202         /* Get X & Y positions */
203         x = le16_to_cpu(*(__le16 *) &data[2]);
204         y = le16_to_cpu(*(__le16 *) &data[4]);
205
206         /* Get current tool identifier */
207         if (data[1] & 0x90) { /* If pen is in the in/active area */
208                 switch ((data[1] >> 5) & 3) {
209                 case 0: /* Pen */
210                         tool = BTN_TOOL_PEN;
211                         break;
212
213                 case 1: /* Rubber */
214                         tool = BTN_TOOL_RUBBER;
215                         break;
216
217                 case 2: /* Mouse with wheel */
218                 case 3: /* Mouse without wheel */
219                         tool = BTN_TOOL_MOUSE;
220                         break;
221                 }
222
223                 /* Reset tool if out of active tablet area */
224                 if (!(data[1] & 0x10))
225                         tool = 0;
226         }
227
228         /* If tool changed, notify input subsystem */
229         if (wdata->tool != tool) {
230                 if (wdata->tool) {
231                         /* Completely reset old tool state */
232                         if (wdata->tool == BTN_TOOL_MOUSE) {
233                                 input_report_key(input, BTN_LEFT, 0);
234                                 input_report_key(input, BTN_RIGHT, 0);
235                                 input_report_key(input, BTN_MIDDLE, 0);
236                                 input_report_abs(input, ABS_DISTANCE,
237                                         input_abs_get_max(input, ABS_DISTANCE));
238                         } else {
239                                 input_report_key(input, BTN_TOUCH, 0);
240                                 input_report_key(input, BTN_STYLUS, 0);
241                                 input_report_key(input, BTN_STYLUS2, 0);
242                                 input_report_abs(input, ABS_PRESSURE, 0);
243                         }
244                         input_report_key(input, wdata->tool, 0);
245                         input_sync(input);
246                 }
247                 wdata->tool = tool;
248                 if (tool)
249                         input_report_key(input, tool, 1);
250         }
251
252         if (tool) {
253                 input_report_abs(input, ABS_X, x);
254                 input_report_abs(input, ABS_Y, y);
255
256                 switch ((data[1] >> 5) & 3) {
257                 case 2: /* Mouse with wheel */
258                         input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
259                         rw = (data[6] & 0x01) ? -1 :
260                                 (data[6] & 0x02) ? 1 : 0;
261                         input_report_rel(input, REL_WHEEL, rw);
262                         /* fall through */
263
264                 case 3: /* Mouse without wheel */
265                         input_report_key(input, BTN_LEFT, data[1] & 0x01);
266                         input_report_key(input, BTN_RIGHT, data[1] & 0x02);
267                         /* Compute distance between mouse and tablet */
268                         rw = 44 - (data[6] >> 2);
269                         if (rw < 0)
270                                 rw = 0;
271                         else if (rw > 31)
272                                 rw = 31;
273                         input_report_abs(input, ABS_DISTANCE, rw);
274                         break;
275
276                 default:
277                         input_report_abs(input, ABS_PRESSURE,
278                                         data[6] | (((__u16) (data[1] & 0x08)) << 5));
279                         input_report_key(input, BTN_TOUCH, data[1] & 0x01);
280                         input_report_key(input, BTN_STYLUS, data[1] & 0x02);
281                         input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
282                         break;
283                 }
284
285                 input_sync(input);
286         }
287
288         /* Report the state of the two buttons at the top of the tablet
289          * as two extra fingerpad keys (buttons 4 & 5). */
290         rw = data[7] & 0x03;
291         if (rw != wdata->butstate) {
292                 wdata->butstate = rw;
293                 input_report_key(input, BTN_0, rw & 0x02);
294                 input_report_key(input, BTN_1, rw & 0x01);
295                 input_report_key(input, BTN_TOOL_FINGER, 0xf0);
296                 input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
297                 input_sync(input);
298         }
299
300 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
301         /* Store current battery capacity */
302         rw = (data[7] >> 2 & 0x07);
303         if (rw != wdata->battery_capacity)
304                 wdata->battery_capacity = rw;
305 #endif
306         return 1;
307 }
308
309 static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
310                         struct input_dev *input, unsigned char *data)
311 {
312         __u16 x, y, pressure;
313         __u32 id;
314
315         switch (data[1]) {
316         case 0x80: /* Out of proximity report */
317                 wdata->tool = 0;
318                 input_report_key(input, BTN_TOUCH, 0);
319                 input_report_abs(input, ABS_PRESSURE, 0);
320                 input_report_key(input, wdata->tool, 0);
321                 input_sync(input);
322                 break;
323         case 0xC2: /* Tool report */
324                 id = ((data[2] << 4) | (data[3] >> 4) |
325                         ((data[7] & 0x0f) << 20) |
326                         ((data[8] & 0xf0) << 12)) & 0xfffff;
327
328                 switch (id) {
329                 case 0x802:
330                         wdata->tool = BTN_TOOL_PEN;
331                         break;
332                 case 0x80A:
333                         wdata->tool = BTN_TOOL_RUBBER;
334                         break;
335                 }
336                 break;
337         default: /* Position/pressure report */
338                 x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1);
339                 y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01);
340                 pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
341                         | (data[1] & 0x01);
342
343                 input_report_key(input, BTN_TOUCH, pressure > 1);
344
345                 input_report_key(input, BTN_STYLUS, data[1] & 0x02);
346                 input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
347                 input_report_key(input, wdata->tool, 1);
348                 input_report_abs(input, ABS_X, x);
349                 input_report_abs(input, ABS_Y, y);
350                 input_report_abs(input, ABS_PRESSURE, pressure);
351                 input_sync(input);
352                 break;
353         }
354
355         return;
356 }
357
358 static void wacom_i4_parse_report(struct hid_device *hdev,
359                         struct wacom_data *wdata,
360                         struct input_dev *input, unsigned char *data)
361 {
362         switch (data[0]) {
363         case 0x00: /* Empty report */
364                 break;
365         case 0x02: /* Pen report */
366                 wacom_i4_parse_pen_report(wdata, input, data);
367                 break;
368         case 0x03: /* Features Report */
369                 wdata->features = data[2];
370                 break;
371         case 0x0C: /* Button report */
372                 break;
373         default:
374                 hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]);
375                 break;
376         }
377 }
378
379 static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
380                 u8 *raw_data, int size)
381 {
382         struct wacom_data *wdata = hid_get_drvdata(hdev);
383         struct hid_input *hidinput;
384         struct input_dev *input;
385         unsigned char *data = (unsigned char *) raw_data;
386         int i;
387
388         if (!(hdev->claimed & HID_CLAIMED_INPUT))
389                 return 0;
390
391         hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
392         input = hidinput->input;
393
394         /* Check if this is a tablet report */
395         if (data[0] != 0x03)
396                 return 0;
397
398         switch (hdev->product) {
399         case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
400                 return wacom_gr_parse_report(hdev, wdata, input, data);
401                 break;
402         case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
403                 i = 1;
404
405                 switch (data[0]) {
406                 case 0x04:
407                         wacom_i4_parse_report(hdev, wdata, input, data + i);
408                         i += 10;
409                         /* fall through */
410                 case 0x03:
411                         wacom_i4_parse_report(hdev, wdata, input, data + i);
412                         i += 10;
413                         wacom_i4_parse_report(hdev, wdata, input, data + i);
414                         break;
415                 default:
416                         hid_err(hdev, "Unknown report: %d,%d size:%d\n",
417                                         data[0], data[1], size);
418                         return 0;
419                 }
420         }
421         return 1;
422 }
423
424 static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
425         struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
426                                                                 int *max)
427 {
428         struct input_dev *input = hi->input;
429
430         __set_bit(INPUT_PROP_POINTER, input->propbit);
431
432         /* Basics */
433         input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
434
435         __set_bit(REL_WHEEL, input->relbit);
436
437         __set_bit(BTN_TOOL_PEN, input->keybit);
438         __set_bit(BTN_TOUCH, input->keybit);
439         __set_bit(BTN_STYLUS, input->keybit);
440         __set_bit(BTN_STYLUS2, input->keybit);
441         __set_bit(BTN_LEFT, input->keybit);
442         __set_bit(BTN_RIGHT, input->keybit);
443         __set_bit(BTN_MIDDLE, input->keybit);
444
445         /* Pad */
446         input->evbit[0] |= BIT(EV_MSC);
447
448         __set_bit(MSC_SERIAL, input->mscbit);
449
450         __set_bit(BTN_0, input->keybit);
451         __set_bit(BTN_1, input->keybit);
452         __set_bit(BTN_TOOL_FINGER, input->keybit);
453
454         /* Distance, rubber and mouse */
455         __set_bit(BTN_TOOL_RUBBER, input->keybit);
456         __set_bit(BTN_TOOL_MOUSE, input->keybit);
457
458         switch (hdev->product) {
459         case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
460                 input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
461                 input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
462                 input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
463                 input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
464                 break;
465         case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
466                 input_set_abs_params(input, ABS_X, 0, 40640, 4, 0);
467                 input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
468                 input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
469                 break;
470         }
471
472         return 0;
473 }
474
475 static int wacom_probe(struct hid_device *hdev,
476                 const struct hid_device_id *id)
477 {
478         struct wacom_data *wdata;
479         int ret;
480
481         wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
482         if (wdata == NULL) {
483                 hid_err(hdev, "can't alloc wacom descriptor\n");
484                 return -ENOMEM;
485         }
486
487         hid_set_drvdata(hdev, wdata);
488
489         /* Parse the HID report now */
490         ret = hid_parse(hdev);
491         if (ret) {
492                 hid_err(hdev, "parse failed\n");
493                 goto err_free;
494         }
495
496         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
497         if (ret) {
498                 hid_err(hdev, "hw start failed\n");
499                 goto err_free;
500         }
501
502         ret = device_create_file(&hdev->dev, &dev_attr_speed);
503         if (ret)
504                 hid_warn(hdev,
505                          "can't create sysfs speed attribute err: %d\n", ret);
506
507         switch (hdev->product) {
508         case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
509                 /* Set Wacom mode 2 with high reporting speed */
510                 wacom_poke(hdev, 1);
511                 break;
512         case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
513                 wdata->features = 0;
514                 wacom_set_features(hdev);
515                 break;
516         }
517
518 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
519         wdata->battery.properties = wacom_battery_props;
520         wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
521         wdata->battery.get_property = wacom_battery_get_property;
522         wdata->battery.name = "wacom_battery";
523         wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
524         wdata->battery.use_for_apm = 0;
525
526         ret = power_supply_register(&hdev->dev, &wdata->battery);
527         if (ret) {
528                 hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
529                          ret);
530                 goto err_battery;
531         }
532
533         wdata->ac.properties = wacom_ac_props;
534         wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
535         wdata->ac.get_property = wacom_ac_get_property;
536         wdata->ac.name = "wacom_ac";
537         wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
538         wdata->ac.use_for_apm = 0;
539
540         ret = power_supply_register(&hdev->dev, &wdata->ac);
541         if (ret) {
542                 hid_warn(hdev,
543                          "can't create ac battery attribute, err: %d\n", ret);
544                 goto err_ac;
545         }
546 #endif
547         return 0;
548
549 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
550 err_ac:
551         power_supply_unregister(&wdata->battery);
552 err_battery:
553         device_remove_file(&hdev->dev, &dev_attr_speed);
554         hid_hw_stop(hdev);
555 #endif
556 err_free:
557         kfree(wdata);
558         return ret;
559 }
560
561 static void wacom_remove(struct hid_device *hdev)
562 {
563 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
564         struct wacom_data *wdata = hid_get_drvdata(hdev);
565 #endif
566         device_remove_file(&hdev->dev, &dev_attr_speed);
567         hid_hw_stop(hdev);
568
569 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
570         power_supply_unregister(&wdata->battery);
571         power_supply_unregister(&wdata->ac);
572 #endif
573         kfree(hid_get_drvdata(hdev));
574 }
575
576 static const struct hid_device_id wacom_devices[] = {
577         { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
578         { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
579
580         { }
581 };
582 MODULE_DEVICE_TABLE(hid, wacom_devices);
583
584 static struct hid_driver wacom_driver = {
585         .name = "wacom",
586         .id_table = wacom_devices,
587         .probe = wacom_probe,
588         .remove = wacom_remove,
589         .raw_event = wacom_raw_event,
590         .input_mapped = wacom_input_mapped,
591 };
592
593 static int __init wacom_init(void)
594 {
595         int ret;
596
597         ret = hid_register_driver(&wacom_driver);
598         if (ret)
599                 pr_err("can't register wacom driver\n");
600         return ret;
601 }
602
603 static void __exit wacom_exit(void)
604 {
605         hid_unregister_driver(&wacom_driver);
606 }
607
608 module_init(wacom_init);
609 module_exit(wacom_exit);
610 MODULE_LICENSE("GPL");
611