HID: hidraw: Use Interrupt Endpoint for OUT Transfers if Available
[sfrench/cifs-2.6.git] / 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  */
13
14 /*
15  * This program is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the Free
17  * Software Foundation; either version 2 of the License, or (at your option)
18  * any later version.
19  */
20
21 #include <linux/device.h>
22 #include <linux/hid.h>
23 #include <linux/module.h>
24 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
25 #include <linux/power_supply.h>
26 #endif
27
28 #include "hid-ids.h"
29
30 struct wacom_data {
31         __u16 tool;
32         unsigned char butstate;
33         unsigned char high_speed;
34 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
35         int battery_capacity;
36         struct power_supply battery;
37         struct power_supply ac;
38 #endif
39 };
40
41 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
42 /*percent of battery capacity, 0 means AC online*/
43 static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
44
45 static enum power_supply_property wacom_battery_props[] = {
46         POWER_SUPPLY_PROP_PRESENT,
47         POWER_SUPPLY_PROP_CAPACITY
48 };
49
50 static enum power_supply_property wacom_ac_props[] = {
51         POWER_SUPPLY_PROP_PRESENT,
52         POWER_SUPPLY_PROP_ONLINE
53 };
54
55 static int wacom_battery_get_property(struct power_supply *psy,
56                                 enum power_supply_property psp,
57                                 union power_supply_propval *val)
58 {
59         struct wacom_data *wdata = container_of(psy,
60                                         struct wacom_data, battery);
61         int power_state = batcap[wdata->battery_capacity];
62         int ret = 0;
63
64         switch (psp) {
65         case POWER_SUPPLY_PROP_PRESENT:
66                 val->intval = 1;
67                 break;
68         case POWER_SUPPLY_PROP_CAPACITY:
69                 /* show 100% battery capacity when charging */
70                 if (power_state == 0)
71                         val->intval = 100;
72                 else
73                         val->intval = power_state;
74                 break;
75         default:
76                 ret = -EINVAL;
77                 break;
78         }
79         return ret;
80 }
81
82 static int wacom_ac_get_property(struct power_supply *psy,
83                                 enum power_supply_property psp,
84                                 union power_supply_propval *val)
85 {
86         struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
87         int power_state = batcap[wdata->battery_capacity];
88         int ret = 0;
89
90         switch (psp) {
91         case POWER_SUPPLY_PROP_PRESENT:
92                 /* fall through */
93         case POWER_SUPPLY_PROP_ONLINE:
94                 if (power_state == 0)
95                         val->intval = 1;
96                 else
97                         val->intval = 0;
98                 break;
99         default:
100                 ret = -EINVAL;
101                 break;
102         }
103         return ret;
104 }
105 #endif
106
107 static void wacom_poke(struct hid_device *hdev, u8 speed)
108 {
109         struct wacom_data *wdata = hid_get_drvdata(hdev);
110         int limit, ret;
111         char rep_data[2];
112
113         rep_data[0] = 0x03 ; rep_data[1] = 0x00;
114         limit = 3;
115         do {
116                 ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
117                                 HID_FEATURE_REPORT);
118         } while (ret < 0 && limit-- > 0);
119
120         if (ret >= 0) {
121                 if (speed == 0)
122                         rep_data[0] = 0x05;
123                 else
124                         rep_data[0] = 0x06;
125
126                 rep_data[1] = 0x00;
127                 limit = 3;
128                 do {
129                         ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
130                                         HID_FEATURE_REPORT);
131                 } while (ret < 0 && limit-- > 0);
132
133                 if (ret >= 0) {
134                         wdata->high_speed = speed;
135                         return;
136                 }
137         }
138
139         /*
140          * Note that if the raw queries fail, it's not a hard failure and it
141          * is safe to continue
142          */
143         dev_warn(&hdev->dev, "failed to poke device, command %d, err %d\n",
144                                 rep_data[0], ret);
145         return;
146 }
147
148 static ssize_t wacom_show_speed(struct device *dev,
149                                 struct device_attribute
150                                 *attr, char *buf)
151 {
152         struct wacom_data *wdata = dev_get_drvdata(dev);
153
154         return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
155 }
156
157 static ssize_t wacom_store_speed(struct device *dev,
158                                 struct device_attribute *attr,
159                                 const char *buf, size_t count)
160 {
161         struct hid_device *hdev = container_of(dev, struct hid_device, dev);
162         int new_speed;
163
164         if (sscanf(buf, "%1d", &new_speed ) != 1)
165                 return -EINVAL;
166
167         if (new_speed == 0 || new_speed == 1) {
168                 wacom_poke(hdev, new_speed);
169                 return strnlen(buf, PAGE_SIZE);
170         } else
171                 return -EINVAL;
172 }
173
174 static DEVICE_ATTR(speed, S_IRUGO | S_IWUGO,
175                 wacom_show_speed, wacom_store_speed);
176
177 static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
178                 u8 *raw_data, int size)
179 {
180         struct wacom_data *wdata = hid_get_drvdata(hdev);
181         struct hid_input *hidinput;
182         struct input_dev *input;
183         unsigned char *data = (unsigned char *) raw_data;
184         int tool, x, y, rw;
185
186         if (!(hdev->claimed & HID_CLAIMED_INPUT))
187                 return 0;
188
189         tool = 0;
190         hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
191         input = hidinput->input;
192
193         /* Check if this is a tablet report */
194         if (data[0] != 0x03)
195                 return 0;
196
197         /* Get X & Y positions */
198         x = le16_to_cpu(*(__le16 *) &data[2]);
199         y = le16_to_cpu(*(__le16 *) &data[4]);
200
201         /* Get current tool identifier */
202         if (data[1] & 0x90) { /* If pen is in the in/active area */
203                 switch ((data[1] >> 5) & 3) {
204                 case 0: /* Pen */
205                         tool = BTN_TOOL_PEN;
206                         break;
207
208                 case 1: /* Rubber */
209                         tool = BTN_TOOL_RUBBER;
210                         break;
211
212                 case 2: /* Mouse with wheel */
213                 case 3: /* Mouse without wheel */
214                         tool = BTN_TOOL_MOUSE;
215                         break;
216                 }
217
218                 /* Reset tool if out of active tablet area */
219                 if (!(data[1] & 0x10))
220                         tool = 0;
221         }
222
223         /* If tool changed, notify input subsystem */
224         if (wdata->tool != tool) {
225                 if (wdata->tool) {
226                         /* Completely reset old tool state */
227                         if (wdata->tool == BTN_TOOL_MOUSE) {
228                                 input_report_key(input, BTN_LEFT, 0);
229                                 input_report_key(input, BTN_RIGHT, 0);
230                                 input_report_key(input, BTN_MIDDLE, 0);
231                                 input_report_abs(input, ABS_DISTANCE,
232                                                 input->absmax[ABS_DISTANCE]);
233                         } else {
234                                 input_report_key(input, BTN_TOUCH, 0);
235                                 input_report_key(input, BTN_STYLUS, 0);
236                                 input_report_key(input, BTN_STYLUS2, 0);
237                                 input_report_abs(input, ABS_PRESSURE, 0);
238                         }
239                         input_report_key(input, wdata->tool, 0);
240                         input_sync(input);
241                 }
242                 wdata->tool = tool;
243                 if (tool)
244                         input_report_key(input, tool, 1);
245         }
246
247         if (tool) {
248                 input_report_abs(input, ABS_X, x);
249                 input_report_abs(input, ABS_Y, y);
250
251                 switch ((data[1] >> 5) & 3) {
252                 case 2: /* Mouse with wheel */
253                         input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
254                         rw = (data[6] & 0x01) ? -1 :
255                                 (data[6] & 0x02) ? 1 : 0;
256                         input_report_rel(input, REL_WHEEL, rw);
257                         /* fall through */
258
259                 case 3: /* Mouse without wheel */
260                         input_report_key(input, BTN_LEFT, data[1] & 0x01);
261                         input_report_key(input, BTN_RIGHT, data[1] & 0x02);
262                         /* Compute distance between mouse and tablet */
263                         rw = 44 - (data[6] >> 2);
264                         if (rw < 0)
265                                 rw = 0;
266                         else if (rw > 31)
267                                 rw = 31;
268                         input_report_abs(input, ABS_DISTANCE, rw);
269                         break;
270
271                 default:
272                         input_report_abs(input, ABS_PRESSURE,
273                                         data[6] | (((__u16) (data[1] & 0x08)) << 5));
274                         input_report_key(input, BTN_TOUCH, data[1] & 0x01);
275                         input_report_key(input, BTN_STYLUS, data[1] & 0x02);
276                         input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
277                         break;
278                 }
279
280                 input_sync(input);
281         }
282
283         /* Report the state of the two buttons at the top of the tablet
284          * as two extra fingerpad keys (buttons 4 & 5). */
285         rw = data[7] & 0x03;
286         if (rw != wdata->butstate) {
287                 wdata->butstate = rw;
288                 input_report_key(input, BTN_0, rw & 0x02);
289                 input_report_key(input, BTN_1, rw & 0x01);
290                 input_report_key(input, BTN_TOOL_FINGER, 0xf0);
291                 input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
292                 input_sync(input);
293         }
294
295 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
296         /* Store current battery capacity */
297         rw = (data[7] >> 2 & 0x07);
298         if (rw != wdata->battery_capacity)
299                 wdata->battery_capacity = rw;
300 #endif
301         return 1;
302 }
303
304 static int wacom_probe(struct hid_device *hdev,
305                 const struct hid_device_id *id)
306 {
307         struct hid_input *hidinput;
308         struct input_dev *input;
309         struct wacom_data *wdata;
310         int ret;
311
312         wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
313         if (wdata == NULL) {
314                 dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
315                 return -ENOMEM;
316         }
317
318         hid_set_drvdata(hdev, wdata);
319
320         /* Parse the HID report now */
321         ret = hid_parse(hdev);
322         if (ret) {
323                 dev_err(&hdev->dev, "parse failed\n");
324                 goto err_free;
325         }
326
327         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
328         if (ret) {
329                 dev_err(&hdev->dev, "hw start failed\n");
330                 goto err_free;
331         }
332
333         ret = device_create_file(&hdev->dev, &dev_attr_speed);
334         if (ret)
335                 dev_warn(&hdev->dev,
336                         "can't create sysfs speed attribute err: %d\n", ret);
337
338         /* Set Wacom mode 2 with high reporting speed */
339         wacom_poke(hdev, 1);
340
341 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
342         wdata->battery.properties = wacom_battery_props;
343         wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
344         wdata->battery.get_property = wacom_battery_get_property;
345         wdata->battery.name = "wacom_battery";
346         wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
347         wdata->battery.use_for_apm = 0;
348
349         ret = power_supply_register(&hdev->dev, &wdata->battery);
350         if (ret) {
351                 dev_warn(&hdev->dev,
352                         "can't create sysfs battery attribute, err: %d\n", ret);
353                 /*
354                  * battery attribute is not critical for the tablet, but if it
355                  * failed then there is no need to create ac attribute
356                  */
357                 goto move_on;
358         }
359
360         wdata->ac.properties = wacom_ac_props;
361         wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
362         wdata->ac.get_property = wacom_ac_get_property;
363         wdata->ac.name = "wacom_ac";
364         wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
365         wdata->ac.use_for_apm = 0;
366
367         ret = power_supply_register(&hdev->dev, &wdata->ac);
368         if (ret) {
369                 dev_warn(&hdev->dev,
370                         "can't create ac battery attribute, err: %d\n", ret);
371                 /*
372                  * ac attribute is not critical for the tablet, but if it
373                  * failed then we don't want to battery attribute to exist
374                  */
375                 power_supply_unregister(&wdata->battery);
376         }
377
378 move_on:
379 #endif
380         hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
381         input = hidinput->input;
382
383         /* Basics */
384         input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
385         input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) |
386                 BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
387         input->relbit[0] |= BIT(REL_WHEEL);
388         set_bit(BTN_TOOL_PEN, input->keybit);
389         set_bit(BTN_TOUCH, input->keybit);
390         set_bit(BTN_STYLUS, input->keybit);
391         set_bit(BTN_STYLUS2, input->keybit);
392         set_bit(BTN_LEFT, input->keybit);
393         set_bit(BTN_RIGHT, input->keybit);
394         set_bit(BTN_MIDDLE, input->keybit);
395
396         /* Pad */
397         input->evbit[0] |= BIT(EV_MSC);
398         input->mscbit[0] |= BIT(MSC_SERIAL);
399         set_bit(BTN_0, input->keybit);
400         set_bit(BTN_1, input->keybit);
401         set_bit(BTN_TOOL_FINGER, input->keybit);
402
403         /* Distance, rubber and mouse */
404         input->absbit[0] |= BIT(ABS_DISTANCE);
405         set_bit(BTN_TOOL_RUBBER, input->keybit);
406         set_bit(BTN_TOOL_MOUSE, input->keybit);
407
408         input->absmax[ABS_PRESSURE] = 511;
409         input->absmax[ABS_DISTANCE] = 32;
410
411         input->absmax[ABS_X] = 16704;
412         input->absmax[ABS_Y] = 12064;
413         input->absfuzz[ABS_X] = 4;
414         input->absfuzz[ABS_Y] = 4;
415
416         return 0;
417 err_free:
418         kfree(wdata);
419         return ret;
420 }
421
422 static void wacom_remove(struct hid_device *hdev)
423 {
424 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
425         struct wacom_data *wdata = hid_get_drvdata(hdev);
426 #endif
427         hid_hw_stop(hdev);
428
429 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
430         power_supply_unregister(&wdata->battery);
431         power_supply_unregister(&wdata->ac);
432 #endif
433         kfree(hid_get_drvdata(hdev));
434 }
435
436 static const struct hid_device_id wacom_devices[] = {
437         { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
438         { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
439         { }
440 };
441 MODULE_DEVICE_TABLE(hid, wacom_devices);
442
443 static struct hid_driver wacom_driver = {
444         .name = "wacom",
445         .id_table = wacom_devices,
446         .probe = wacom_probe,
447         .remove = wacom_remove,
448         .raw_event = wacom_raw_event,
449 };
450
451 static int __init wacom_init(void)
452 {
453         int ret;
454
455         ret = hid_register_driver(&wacom_driver);
456         if (ret)
457                 printk(KERN_ERR "can't register wacom driver\n");
458         printk(KERN_ERR "wacom driver registered\n");
459         return ret;
460 }
461
462 static void __exit wacom_exit(void)
463 {
464         hid_unregister_driver(&wacom_driver);
465 }
466
467 module_init(wacom_init);
468 module_exit(wacom_exit);
469 MODULE_LICENSE("GPL");
470