aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-input.c61
-rw-r--r--include/linux/hid.h1
2 files changed, 47 insertions, 15 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index b9b8c75a6f9a..8fac47cf42f1 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -277,6 +277,7 @@ static enum power_supply_property hidinput_battery_props[] = {
277 POWER_SUPPLY_PROP_ONLINE, 277 POWER_SUPPLY_PROP_ONLINE,
278 POWER_SUPPLY_PROP_CAPACITY, 278 POWER_SUPPLY_PROP_CAPACITY,
279 POWER_SUPPLY_PROP_MODEL_NAME, 279 POWER_SUPPLY_PROP_MODEL_NAME,
280 POWER_SUPPLY_PROP_STATUS
280}; 281};
281 282
282static int hidinput_get_battery_property(struct power_supply *psy, 283static int hidinput_get_battery_property(struct power_supply *psy,
@@ -285,6 +286,9 @@ static int hidinput_get_battery_property(struct power_supply *psy,
285{ 286{
286 struct hid_device *dev = container_of(psy, struct hid_device, battery); 287 struct hid_device *dev = container_of(psy, struct hid_device, battery);
287 int ret = 0; 288 int ret = 0;
289 int ret_rep;
290 __u8 *buf = NULL;
291 unsigned char report_number = dev->battery_report_id;
288 292
289 switch (prop) { 293 switch (prop) {
290 case POWER_SUPPLY_PROP_PRESENT: 294 case POWER_SUPPLY_PROP_PRESENT:
@@ -293,28 +297,45 @@ static int hidinput_get_battery_property(struct power_supply *psy,
293 break; 297 break;
294 298
295 case POWER_SUPPLY_PROP_CAPACITY: 299 case POWER_SUPPLY_PROP_CAPACITY:
296 if (dev->battery_min < dev->battery_max && 300 buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL);
297 dev->battery_val >= dev->battery_min && 301 if (!buf) {
298 dev->battery_val <= dev->battery_max) 302 ret = -ENOMEM;
299 val->intval = (100 * (dev->battery_val - dev->battery_min)) / 303 break;
300 (dev->battery_max - dev->battery_min); 304 }
301 else 305
306 memset(buf, 0, sizeof(buf));
307 ret_rep = dev->hid_get_raw_report(dev, report_number, buf, sizeof(buf), HID_FEATURE_REPORT);
308 if (ret_rep != 2) {
302 ret = -EINVAL; 309 ret = -EINVAL;
310 break;
311 }
312
313 /* store the returned value */
314 /* I'm not calculating this using the logical_minimum and maximum */
315 /* because my device returns 0-100 even though the min and max are 0-255 */
316 val->intval = buf[1];
303 break; 317 break;
304 318
305 case POWER_SUPPLY_PROP_MODEL_NAME: 319 case POWER_SUPPLY_PROP_MODEL_NAME:
306 val->strval = dev->name; 320 val->strval = dev->name;
307 break; 321 break;
308 322
323 case POWER_SUPPLY_PROP_STATUS:
324 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
325 break;
326
309 default: 327 default:
310 ret = -EINVAL; 328 ret = -EINVAL;
311 break; 329 break;
312 } 330 }
313 331
332 if (buf) {
333 kfree(buf);
334 }
314 return ret; 335 return ret;
315} 336}
316 337
317static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max) 338static void hidinput_setup_battery(struct hid_device *dev, unsigned id, s32 min, s32 max)
318{ 339{
319 struct power_supply *battery = &dev->battery; 340 struct power_supply *battery = &dev->battery;
320 int ret; 341 int ret;
@@ -326,7 +347,7 @@ static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
326 if (battery->name == NULL) 347 if (battery->name == NULL)
327 return; 348 return;
328 349
329 battery->type = POWER_SUPPLY_TYPE_BATTERY; 350 battery->type = POWER_SUPPLY_TYPE_USB;
330 battery->properties = hidinput_battery_props; 351 battery->properties = hidinput_battery_props;
331 battery->num_properties = ARRAY_SIZE(hidinput_battery_props); 352 battery->num_properties = ARRAY_SIZE(hidinput_battery_props);
332 battery->use_for_apm = 0; 353 battery->use_for_apm = 0;
@@ -334,6 +355,7 @@ static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
334 355
335 dev->battery_min = min; 356 dev->battery_min = min;
336 dev->battery_max = max; 357 dev->battery_max = max;
358 dev->battery_report_id = id;
337 359
338 ret = power_supply_register(&dev->dev, battery); 360 ret = power_supply_register(&dev->dev, battery);
339 if (ret != 0) { 361 if (ret != 0) {
@@ -353,7 +375,7 @@ static void hidinput_cleanup_battery(struct hid_device *dev)
353 dev->battery.name = NULL; 375 dev->battery.name = NULL;
354} 376}
355#else /* !CONFIG_HID_BATTERY_STRENGTH */ 377#else /* !CONFIG_HID_BATTERY_STRENGTH */
356static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max) 378static void hidinput_setup_battery(struct hid_device *dev, unsigned id, s32 min, s32 max)
357{ 379{
358} 380}
359 381
@@ -723,6 +745,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
723 case HID_UP_GENDEVCTRLS: 745 case HID_UP_GENDEVCTRLS:
724 if ((usage->hid & HID_USAGE) == 0x20) { /* Battery Strength */ 746 if ((usage->hid & HID_USAGE) == 0x20) { /* Battery Strength */
725 hidinput_setup_battery(device, 747 hidinput_setup_battery(device,
748 field->report->id,
726 field->logical_minimum, 749 field->logical_minimum,
727 field->logical_maximum); 750 field->logical_maximum);
728 goto ignore; 751 goto ignore;
@@ -997,15 +1020,23 @@ static void report_features(struct hid_device *hid)
997 struct hid_report *rep; 1020 struct hid_report *rep;
998 int i, j; 1021 int i, j;
999 1022
1000 if (!drv->feature_mapping)
1001 return;
1002
1003 rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; 1023 rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
1004 list_for_each_entry(rep, &rep_enum->report_list, list) 1024 list_for_each_entry(rep, &rep_enum->report_list, list)
1005 for (i = 0; i < rep->maxfield; i++) 1025 for (i = 0; i < rep->maxfield; i++)
1006 for (j = 0; j < rep->field[i]->maxusage; j++) 1026 for (j = 0; j < rep->field[i]->maxusage; j++) {
1007 drv->feature_mapping(hid, rep->field[i], 1027 /* Verify if Battery Strength feature is available */
1008 rep->field[i]->usage + j); 1028 if (((rep->field[i]->usage + j)->hid & HID_USAGE_PAGE) == HID_UP_GENDEVCTRLS &&
1029 ((rep->field[i]->usage + j)->hid & HID_USAGE) == 0x20) {
1030 hidinput_setup_battery(hid,
1031 rep->id,
1032 rep->field[i]->logical_minimum,
1033 rep->field[i]->logical_maximum);
1034 }
1035
1036 if (drv->feature_mapping)
1037 drv->feature_mapping(hid, rep->field[i],
1038 rep->field[i]->usage + j);
1039 }
1009} 1040}
1010 1041
1011/* 1042/*
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 7f344c3da767..b5df198d87a5 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -496,6 +496,7 @@ struct hid_device { /* device report descriptor */
496 __s32 battery_min; 496 __s32 battery_min;
497 __s32 battery_max; 497 __s32 battery_max;
498 __s32 battery_val; 498 __s32 battery_val;
499 __s32 battery_report_id;
499#endif 500#endif
500 501
501 unsigned int status; /* see STAT flags above */ 502 unsigned int status; /* see STAT flags above */