aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r--drivers/hid/hid-input.c228
1 files changed, 222 insertions, 6 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index f333139d1a48..9333d692a786 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -32,6 +32,8 @@
32#include <linux/hid.h> 32#include <linux/hid.h>
33#include <linux/hid-debug.h> 33#include <linux/hid-debug.h>
34 34
35#include "hid-ids.h"
36
35#define unk KEY_UNKNOWN 37#define unk KEY_UNKNOWN
36 38
37static const unsigned char hid_keyboard[256] = { 39static const unsigned char hid_keyboard[256] = {
@@ -271,6 +273,161 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
271 return logical_extents / physical_extents; 273 return logical_extents / physical_extents;
272} 274}
273 275
276#ifdef CONFIG_HID_BATTERY_STRENGTH
277static enum power_supply_property hidinput_battery_props[] = {
278 POWER_SUPPLY_PROP_PRESENT,
279 POWER_SUPPLY_PROP_ONLINE,
280 POWER_SUPPLY_PROP_CAPACITY,
281 POWER_SUPPLY_PROP_MODEL_NAME,
282 POWER_SUPPLY_PROP_STATUS
283};
284
285#define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */
286#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */
287
288static const struct hid_device_id hid_battery_quirks[] = {
289 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
290 USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
291 HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
292 {}
293};
294
295static unsigned find_battery_quirk(struct hid_device *hdev)
296{
297 unsigned quirks = 0;
298 const struct hid_device_id *match;
299
300 match = hid_match_id(hdev, hid_battery_quirks);
301 if (match != NULL)
302 quirks = match->driver_data;
303
304 return quirks;
305}
306
307static int hidinput_get_battery_property(struct power_supply *psy,
308 enum power_supply_property prop,
309 union power_supply_propval *val)
310{
311 struct hid_device *dev = container_of(psy, struct hid_device, battery);
312 int ret = 0;
313 __u8 buf[2] = {};
314
315 switch (prop) {
316 case POWER_SUPPLY_PROP_PRESENT:
317 case POWER_SUPPLY_PROP_ONLINE:
318 val->intval = 1;
319 break;
320
321 case POWER_SUPPLY_PROP_CAPACITY:
322 ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
323 buf, sizeof(buf),
324 dev->battery_report_type);
325
326 if (ret != 2) {
327 if (ret >= 0)
328 ret = -EINVAL;
329 break;
330 }
331
332 if (dev->battery_min < dev->battery_max &&
333 buf[1] >= dev->battery_min &&
334 buf[1] <= dev->battery_max)
335 val->intval = (100 * (buf[1] - dev->battery_min)) /
336 (dev->battery_max - dev->battery_min);
337 break;
338
339 case POWER_SUPPLY_PROP_MODEL_NAME:
340 val->strval = dev->name;
341 break;
342
343 case POWER_SUPPLY_PROP_STATUS:
344 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
345 break;
346
347 default:
348 ret = -EINVAL;
349 break;
350 }
351
352 return ret;
353}
354
355static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
356{
357 struct power_supply *battery = &dev->battery;
358 int ret;
359 unsigned quirks;
360 s32 min, max;
361
362 if (field->usage->hid != HID_DC_BATTERYSTRENGTH)
363 return false; /* no match */
364
365 if (battery->name != NULL)
366 goto out; /* already initialized? */
367
368 battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
369 if (battery->name == NULL)
370 goto out;
371
372 battery->type = POWER_SUPPLY_TYPE_BATTERY;
373 battery->properties = hidinput_battery_props;
374 battery->num_properties = ARRAY_SIZE(hidinput_battery_props);
375 battery->use_for_apm = 0;
376 battery->get_property = hidinput_get_battery_property;
377
378 quirks = find_battery_quirk(dev);
379
380 hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",
381 dev->bus, dev->vendor, dev->product, dev->version, quirks);
382
383 min = field->logical_minimum;
384 max = field->logical_maximum;
385
386 if (quirks & HID_BATTERY_QUIRK_PERCENT) {
387 min = 0;
388 max = 100;
389 }
390
391 if (quirks & HID_BATTERY_QUIRK_FEATURE)
392 report_type = HID_FEATURE_REPORT;
393
394 dev->battery_min = min;
395 dev->battery_max = max;
396 dev->battery_report_type = report_type;
397 dev->battery_report_id = field->report->id;
398
399 ret = power_supply_register(&dev->dev, battery);
400 if (ret != 0) {
401 hid_warn(dev, "can't register power supply: %d\n", ret);
402 kfree(battery->name);
403 battery->name = NULL;
404 }
405
406out:
407 return true;
408}
409
410static void hidinput_cleanup_battery(struct hid_device *dev)
411{
412 if (!dev->battery.name)
413 return;
414
415 power_supply_unregister(&dev->battery);
416 kfree(dev->battery.name);
417 dev->battery.name = NULL;
418}
419#else /* !CONFIG_HID_BATTERY_STRENGTH */
420static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
421 struct hid_field *field)
422{
423 return false;
424}
425
426static void hidinput_cleanup_battery(struct hid_device *dev)
427{
428}
429#endif /* CONFIG_HID_BATTERY_STRENGTH */
430
274static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, 431static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
275 struct hid_usage *usage) 432 struct hid_usage *usage)
276{ 433{
@@ -629,6 +786,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
629 } 786 }
630 break; 787 break;
631 788
789 case HID_UP_GENDEVCTRLS:
790 if (hidinput_setup_battery(device, HID_INPUT_REPORT, field))
791 goto ignore;
792 else
793 goto unknown;
794 break;
795
632 case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ 796 case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
633 set_bit(EV_REP, input->evbit); 797 set_bit(EV_REP, input->evbit);
634 switch (usage->hid & HID_USAGE) { 798 switch (usage->hid & HID_USAGE) {
@@ -822,6 +986,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
822 return; 986 return;
823 } 987 }
824 988
989 /* Ignore out-of-range values as per HID specification, section 5.10 */
990 if (value < field->logical_minimum || value > field->logical_maximum) {
991 dbg_hid("Ignoring out-of-range value %x\n", value);
992 return;
993 }
994
825 /* report the usage code as scancode if the key status has changed */ 995 /* report the usage code as scancode if the key status has changed */
826 if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) 996 if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
827 input_event(input, EV_MSC, MSC_SCAN, usage->hid); 997 input_event(input, EV_MSC, MSC_SCAN, usage->hid);
@@ -861,6 +1031,48 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int
861} 1031}
862EXPORT_SYMBOL_GPL(hidinput_find_field); 1032EXPORT_SYMBOL_GPL(hidinput_find_field);
863 1033
1034struct hid_field *hidinput_get_led_field(struct hid_device *hid)
1035{
1036 struct hid_report *report;
1037 struct hid_field *field;
1038 int i, j;
1039
1040 list_for_each_entry(report,
1041 &hid->report_enum[HID_OUTPUT_REPORT].report_list,
1042 list) {
1043 for (i = 0; i < report->maxfield; i++) {
1044 field = report->field[i];
1045 for (j = 0; j < field->maxusage; j++)
1046 if (field->usage[j].type == EV_LED)
1047 return field;
1048 }
1049 }
1050 return NULL;
1051}
1052EXPORT_SYMBOL_GPL(hidinput_get_led_field);
1053
1054unsigned int hidinput_count_leds(struct hid_device *hid)
1055{
1056 struct hid_report *report;
1057 struct hid_field *field;
1058 int i, j;
1059 unsigned int count = 0;
1060
1061 list_for_each_entry(report,
1062 &hid->report_enum[HID_OUTPUT_REPORT].report_list,
1063 list) {
1064 for (i = 0; i < report->maxfield; i++) {
1065 field = report->field[i];
1066 for (j = 0; j < field->maxusage; j++)
1067 if (field->usage[j].type == EV_LED &&
1068 field->value[j])
1069 count += 1;
1070 }
1071 }
1072 return count;
1073}
1074EXPORT_SYMBOL_GPL(hidinput_count_leds);
1075
864static int hidinput_open(struct input_dev *dev) 1076static int hidinput_open(struct input_dev *dev)
865{ 1077{
866 struct hid_device *hid = input_get_drvdata(dev); 1078 struct hid_device *hid = input_get_drvdata(dev);
@@ -882,15 +1094,17 @@ static void report_features(struct hid_device *hid)
882 struct hid_report *rep; 1094 struct hid_report *rep;
883 int i, j; 1095 int i, j;
884 1096
885 if (!drv->feature_mapping)
886 return;
887
888 rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; 1097 rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
889 list_for_each_entry(rep, &rep_enum->report_list, list) 1098 list_for_each_entry(rep, &rep_enum->report_list, list)
890 for (i = 0; i < rep->maxfield; i++) 1099 for (i = 0; i < rep->maxfield; i++)
891 for (j = 0; j < rep->field[i]->maxusage; j++) 1100 for (j = 0; j < rep->field[i]->maxusage; j++) {
892 drv->feature_mapping(hid, rep->field[i], 1101 /* Verify if Battery Strength feature is available */
893 rep->field[i]->usage + j); 1102 hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
1103
1104 if (drv->feature_mapping)
1105 drv->feature_mapping(hid, rep->field[i],
1106 rep->field[i]->usage + j);
1107 }
894} 1108}
895 1109
896/* 1110/*
@@ -1010,6 +1224,8 @@ void hidinput_disconnect(struct hid_device *hid)
1010{ 1224{
1011 struct hid_input *hidinput, *next; 1225 struct hid_input *hidinput, *next;
1012 1226
1227 hidinput_cleanup_battery(hid);
1228
1013 list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { 1229 list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
1014 list_del(&hidinput->list); 1230 list_del(&hidinput->list);
1015 input_unregister_device(hidinput->input); 1231 input_unregister_device(hidinput->input);