diff options
-rw-r--r-- | drivers/hid/Kconfig | 5 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 110 | ||||
-rw-r--r-- | include/linux/hid.h | 16 |
3 files changed, 131 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 22a4a051f221..3a97f1fab243 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -31,6 +31,11 @@ config HID | |||
31 | 31 | ||
32 | If unsure, say Y. | 32 | If unsure, say Y. |
33 | 33 | ||
34 | config HID_BATTERY_STRENGTH | ||
35 | bool | ||
36 | depends on POWER_SUPPLY | ||
37 | default y | ||
38 | |||
34 | config HIDRAW | 39 | config HIDRAW |
35 | bool "/dev/hidraw raw HID device support" | 40 | bool "/dev/hidraw raw HID device support" |
36 | depends on HID | 41 | depends on HID |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6e3252651ce3..2d96b782b203 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -271,6 +271,97 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | |||
271 | return logical_extents / physical_extents; | 271 | return logical_extents / physical_extents; |
272 | } | 272 | } |
273 | 273 | ||
274 | #ifdef CONFIG_HID_BATTERY_STRENGTH | ||
275 | static enum power_supply_property hidinput_battery_props[] = { | ||
276 | POWER_SUPPLY_PROP_PRESENT, | ||
277 | POWER_SUPPLY_PROP_ONLINE, | ||
278 | POWER_SUPPLY_PROP_CAPACITY, | ||
279 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
280 | }; | ||
281 | |||
282 | static int hidinput_get_battery_property(struct power_supply *psy, | ||
283 | enum power_supply_property prop, | ||
284 | union power_supply_propval *val) | ||
285 | { | ||
286 | struct hid_device *dev = container_of(psy, struct hid_device, battery); | ||
287 | int ret = 0; | ||
288 | |||
289 | switch (prop) { | ||
290 | case POWER_SUPPLY_PROP_PRESENT: | ||
291 | case POWER_SUPPLY_PROP_ONLINE: | ||
292 | val->intval = 1; | ||
293 | break; | ||
294 | |||
295 | case POWER_SUPPLY_PROP_CAPACITY: | ||
296 | if (dev->battery_min < dev->battery_max && | ||
297 | dev->battery_val >= dev->battery_min && | ||
298 | dev->battery_val <= dev->battery_max) | ||
299 | val->intval = (100 * (dev->battery_val - dev->battery_min)) / | ||
300 | (dev->battery_max - dev->battery_min); | ||
301 | else | ||
302 | ret = -EINVAL; | ||
303 | break; | ||
304 | |||
305 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
306 | val->strval = dev->name; | ||
307 | break; | ||
308 | |||
309 | default: | ||
310 | ret = -EINVAL; | ||
311 | break; | ||
312 | } | ||
313 | |||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max) | ||
318 | { | ||
319 | struct power_supply *battery = &dev->battery; | ||
320 | int ret; | ||
321 | |||
322 | if (battery->name != NULL) | ||
323 | return; /* already initialized? */ | ||
324 | |||
325 | battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq); | ||
326 | if (battery->name == NULL) | ||
327 | return; | ||
328 | |||
329 | battery->type = POWER_SUPPLY_TYPE_BATTERY; | ||
330 | battery->properties = hidinput_battery_props; | ||
331 | battery->num_properties = ARRAY_SIZE(hidinput_battery_props); | ||
332 | battery->use_for_apm = 0; | ||
333 | battery->get_property = hidinput_get_battery_property; | ||
334 | |||
335 | dev->battery_min = min; | ||
336 | dev->battery_max = max; | ||
337 | |||
338 | ret = power_supply_register(&dev->dev, battery); | ||
339 | if (ret != 0) { | ||
340 | hid_warn(dev, "can't register power supply: %d\n", ret); | ||
341 | kfree(battery->name); | ||
342 | battery->name = NULL; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | static void hidinput_cleanup_battery(struct hid_device *dev) | ||
347 | { | ||
348 | if (!dev->battery.name) | ||
349 | return; | ||
350 | |||
351 | power_supply_unregister(&dev->battery); | ||
352 | kfree(dev->battery.name); | ||
353 | dev->battery.name = NULL; | ||
354 | } | ||
355 | #else /* !CONFIG_HID_BATTERY_STRENGTH */ | ||
356 | static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max) | ||
357 | { | ||
358 | } | ||
359 | |||
360 | static void hidinput_cleanup_battery(struct hid_device *dev) | ||
361 | { | ||
362 | } | ||
363 | #endif /* CONFIG_HID_BATTERY_STRENGTH */ | ||
364 | |||
274 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 365 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
275 | struct hid_usage *usage) | 366 | struct hid_usage *usage) |
276 | { | 367 | { |
@@ -629,6 +720,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
629 | } | 720 | } |
630 | break; | 721 | break; |
631 | 722 | ||
723 | case HID_UP_GENDEVCTRLS: | ||
724 | if ((usage->hid & HID_USAGE) == 0x20) { /* Battery Strength */ | ||
725 | hidinput_setup_battery(device, | ||
726 | field->logical_minimum, | ||
727 | field->logical_maximum); | ||
728 | goto ignore; | ||
729 | } else | ||
730 | goto unknown; | ||
731 | break; | ||
732 | |||
632 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ | 733 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ |
633 | set_bit(EV_REP, input->evbit); | 734 | set_bit(EV_REP, input->evbit); |
634 | switch (usage->hid & HID_USAGE) { | 735 | switch (usage->hid & HID_USAGE) { |
@@ -760,6 +861,13 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
760 | 861 | ||
761 | input = field->hidinput->input; | 862 | input = field->hidinput->input; |
762 | 863 | ||
864 | if (usage->hid == HID_DC_BATTERYSTRENGTH) { | ||
865 | hid->battery_val = value; | ||
866 | hid_dbg(hid, "battery value is %d (range %d-%d)\n", | ||
867 | value, hid->battery_min, hid->battery_max); | ||
868 | return; | ||
869 | } | ||
870 | |||
763 | if (!usage->type) | 871 | if (!usage->type) |
764 | return; | 872 | return; |
765 | 873 | ||
@@ -1016,6 +1124,8 @@ void hidinput_disconnect(struct hid_device *hid) | |||
1016 | { | 1124 | { |
1017 | struct hid_input *hidinput, *next; | 1125 | struct hid_input *hidinput, *next; |
1018 | 1126 | ||
1127 | hidinput_cleanup_battery(hid); | ||
1128 | |||
1019 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { | 1129 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { |
1020 | list_del(&hidinput->list); | 1130 | list_del(&hidinput->list); |
1021 | input_unregister_device(hidinput->input); | 1131 | input_unregister_device(hidinput->input); |
diff --git a/include/linux/hid.h b/include/linux/hid.h index deed5f9a1e1c..7f344c3da767 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -72,6 +72,7 @@ | |||
72 | #include <linux/workqueue.h> | 72 | #include <linux/workqueue.h> |
73 | #include <linux/input.h> | 73 | #include <linux/input.h> |
74 | #include <linux/semaphore.h> | 74 | #include <linux/semaphore.h> |
75 | #include <linux/power_supply.h> | ||
75 | 76 | ||
76 | /* | 77 | /* |
77 | * We parse each description item into this structure. Short items data | 78 | * We parse each description item into this structure. Short items data |
@@ -190,6 +191,7 @@ struct hid_item { | |||
190 | #define HID_UP_UNDEFINED 0x00000000 | 191 | #define HID_UP_UNDEFINED 0x00000000 |
191 | #define HID_UP_GENDESK 0x00010000 | 192 | #define HID_UP_GENDESK 0x00010000 |
192 | #define HID_UP_SIMULATION 0x00020000 | 193 | #define HID_UP_SIMULATION 0x00020000 |
194 | #define HID_UP_GENDEVCTRLS 0x00060000 | ||
193 | #define HID_UP_KEYBOARD 0x00070000 | 195 | #define HID_UP_KEYBOARD 0x00070000 |
194 | #define HID_UP_LED 0x00080000 | 196 | #define HID_UP_LED 0x00080000 |
195 | #define HID_UP_BUTTON 0x00090000 | 197 | #define HID_UP_BUTTON 0x00090000 |
@@ -239,6 +241,8 @@ struct hid_item { | |||
239 | #define HID_GD_RIGHT 0x00010092 | 241 | #define HID_GD_RIGHT 0x00010092 |
240 | #define HID_GD_LEFT 0x00010093 | 242 | #define HID_GD_LEFT 0x00010093 |
241 | 243 | ||
244 | #define HID_DC_BATTERYSTRENGTH 0x00060020 | ||
245 | |||
242 | #define HID_DG_DIGITIZER 0x000d0001 | 246 | #define HID_DG_DIGITIZER 0x000d0001 |
243 | #define HID_DG_PEN 0x000d0002 | 247 | #define HID_DG_PEN 0x000d0002 |
244 | #define HID_DG_LIGHTPEN 0x000d0003 | 248 | #define HID_DG_LIGHTPEN 0x000d0003 |
@@ -482,6 +486,18 @@ struct hid_device { /* device report descriptor */ | |||
482 | struct hid_driver *driver; | 486 | struct hid_driver *driver; |
483 | struct hid_ll_driver *ll_driver; | 487 | struct hid_ll_driver *ll_driver; |
484 | 488 | ||
489 | #ifdef CONFIG_HID_BATTERY_STRENGTH | ||
490 | /* | ||
491 | * Power supply information for HID devices which report | ||
492 | * battery strength. power_supply is registered iff | ||
493 | * battery.name is non-NULL. | ||
494 | */ | ||
495 | struct power_supply battery; | ||
496 | __s32 battery_min; | ||
497 | __s32 battery_max; | ||
498 | __s32 battery_val; | ||
499 | #endif | ||
500 | |||
485 | unsigned int status; /* see STAT flags above */ | 501 | unsigned int status; /* see STAT flags above */ |
486 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | 502 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
487 | unsigned quirks; /* Various quirks the device can pull on us */ | 503 | unsigned quirks; /* Various quirks the device can pull on us */ |