diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 8 | ||||
-rw-r--r-- | drivers/hid/hid-wacom.c | 127 |
2 files changed, 135 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 71d4c0703629..8e1b505b5bf2 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -357,6 +357,14 @@ config HID_WACOM | |||
357 | ---help--- | 357 | ---help--- |
358 | Support for Wacom Graphire Bluetooth tablet. | 358 | Support for Wacom Graphire Bluetooth tablet. |
359 | 359 | ||
360 | config HID_WACOM_POWER_SUPPLY | ||
361 | bool "Wacom Bluetooth devices power supply status support" | ||
362 | depends on HID_WACOM | ||
363 | select POWER_SUPPLY | ||
364 | ---help--- | ||
365 | Say Y here if you want to enable power supply status monitoring for | ||
366 | Wacom Bluetooth devices. | ||
367 | |||
360 | config HID_ZEROPLUS | 368 | config HID_ZEROPLUS |
361 | tristate "Zeroplus based game controller support" if EMBEDDED | 369 | tristate "Zeroplus based game controller support" if EMBEDDED |
362 | depends on USB_HID | 370 | depends on USB_HID |
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 8d3b46f5d149..4d2d2a2e1a5f 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -21,14 +21,88 @@ | |||
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/hid.h> | 22 | #include <linux/hid.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
25 | #include <linux/power_supply.h> | ||
26 | #endif | ||
24 | 27 | ||
25 | #include "hid-ids.h" | 28 | #include "hid-ids.h" |
26 | 29 | ||
27 | struct wacom_data { | 30 | struct wacom_data { |
28 | __u16 tool; | 31 | __u16 tool; |
29 | unsigned char butstate; | 32 | unsigned char butstate; |
33 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
34 | int battery_capacity; | ||
35 | struct power_supply battery; | ||
36 | struct power_supply ac; | ||
37 | #endif | ||
30 | }; | 38 | }; |
31 | 39 | ||
40 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
41 | /*percent of battery capacity, 0 means AC online*/ | ||
42 | static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 }; | ||
43 | |||
44 | static enum power_supply_property wacom_battery_props[] = { | ||
45 | POWER_SUPPLY_PROP_PRESENT, | ||
46 | POWER_SUPPLY_PROP_CAPACITY | ||
47 | }; | ||
48 | |||
49 | static enum power_supply_property wacom_ac_props[] = { | ||
50 | POWER_SUPPLY_PROP_PRESENT, | ||
51 | POWER_SUPPLY_PROP_ONLINE | ||
52 | }; | ||
53 | |||
54 | static int wacom_battery_get_property(struct power_supply *psy, | ||
55 | enum power_supply_property psp, | ||
56 | union power_supply_propval *val) | ||
57 | { | ||
58 | struct wacom_data *wdata = container_of(psy, | ||
59 | struct wacom_data, battery); | ||
60 | int power_state = batcap[wdata->battery_capacity]; | ||
61 | int ret = 0; | ||
62 | |||
63 | switch (psp) { | ||
64 | case POWER_SUPPLY_PROP_PRESENT: | ||
65 | val->intval = 1; | ||
66 | break; | ||
67 | case POWER_SUPPLY_PROP_CAPACITY: | ||
68 | /* show 100% battery capacity when charging */ | ||
69 | if (power_state == 0) | ||
70 | val->intval = 100; | ||
71 | else | ||
72 | val->intval = power_state; | ||
73 | break; | ||
74 | default: | ||
75 | ret = -EINVAL; | ||
76 | break; | ||
77 | } | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static int wacom_ac_get_property(struct power_supply *psy, | ||
82 | enum power_supply_property psp, | ||
83 | union power_supply_propval *val) | ||
84 | { | ||
85 | struct wacom_data *wdata = container_of(psy, struct wacom_data, ac); | ||
86 | int power_state = batcap[wdata->battery_capacity]; | ||
87 | int ret = 0; | ||
88 | |||
89 | switch (psp) { | ||
90 | case POWER_SUPPLY_PROP_PRESENT: | ||
91 | /* fall through */ | ||
92 | case POWER_SUPPLY_PROP_ONLINE: | ||
93 | if (power_state == 0) | ||
94 | val->intval = 1; | ||
95 | else | ||
96 | val->intval = 0; | ||
97 | break; | ||
98 | default: | ||
99 | ret = -EINVAL; | ||
100 | break; | ||
101 | } | ||
102 | return ret; | ||
103 | } | ||
104 | #endif | ||
105 | |||
32 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | 106 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, |
33 | u8 *raw_data, int size) | 107 | u8 *raw_data, int size) |
34 | { | 108 | { |
@@ -147,6 +221,12 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
147 | input_sync(input); | 221 | input_sync(input); |
148 | } | 222 | } |
149 | 223 | ||
224 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
225 | /* Store current battery capacity */ | ||
226 | rw = (data[7] >> 2 & 0x07); | ||
227 | if (rw != wdata->battery_capacity) | ||
228 | wdata->battery_capacity = rw; | ||
229 | #endif | ||
150 | return 1; | 230 | return 1; |
151 | } | 231 | } |
152 | 232 | ||
@@ -206,6 +286,45 @@ static int wacom_probe(struct hid_device *hdev, | |||
206 | if (ret < 0) | 286 | if (ret < 0) |
207 | dev_warn(&hdev->dev, "failed to poke device #2, %d\n", ret); | 287 | dev_warn(&hdev->dev, "failed to poke device #2, %d\n", ret); |
208 | 288 | ||
289 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
290 | wdata->battery.properties = wacom_battery_props; | ||
291 | wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props); | ||
292 | wdata->battery.get_property = wacom_battery_get_property; | ||
293 | wdata->battery.name = "wacom_battery"; | ||
294 | wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
295 | wdata->battery.use_for_apm = 0; | ||
296 | |||
297 | ret = power_supply_register(&hdev->dev, &wdata->battery); | ||
298 | if (ret) { | ||
299 | dev_warn(&hdev->dev, | ||
300 | "can't create sysfs battery attribute, err: %d\n", ret); | ||
301 | /* | ||
302 | * battery attribute is not critical for the tablet, but if it | ||
303 | * failed then there is no need to create ac attribute | ||
304 | */ | ||
305 | goto move_on; | ||
306 | } | ||
307 | |||
308 | wdata->ac.properties = wacom_ac_props; | ||
309 | wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props); | ||
310 | wdata->ac.get_property = wacom_ac_get_property; | ||
311 | wdata->ac.name = "wacom_ac"; | ||
312 | wdata->ac.type = POWER_SUPPLY_TYPE_MAINS; | ||
313 | wdata->ac.use_for_apm = 0; | ||
314 | |||
315 | ret = power_supply_register(&hdev->dev, &wdata->ac); | ||
316 | if (ret) { | ||
317 | dev_warn(&hdev->dev, | ||
318 | "can't create ac battery attribute, err: %d\n", ret); | ||
319 | /* | ||
320 | * ac attribute is not critical for the tablet, but if it | ||
321 | * failed then we don't want to battery attribute to exist | ||
322 | */ | ||
323 | power_supply_unregister(&wdata->battery); | ||
324 | } | ||
325 | |||
326 | move_on: | ||
327 | #endif | ||
209 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | 328 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); |
210 | input = hidinput->input; | 329 | input = hidinput->input; |
211 | 330 | ||
@@ -250,7 +369,15 @@ err_free: | |||
250 | 369 | ||
251 | static void wacom_remove(struct hid_device *hdev) | 370 | static void wacom_remove(struct hid_device *hdev) |
252 | { | 371 | { |
372 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
373 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
374 | #endif | ||
253 | hid_hw_stop(hdev); | 375 | hid_hw_stop(hdev); |
376 | |||
377 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
378 | power_supply_unregister(&wdata->battery); | ||
379 | power_supply_unregister(&wdata->ac); | ||
380 | #endif | ||
254 | kfree(hid_get_drvdata(hdev)); | 381 | kfree(hid_get_drvdata(hdev)); |
255 | } | 382 | } |
256 | 383 | ||