@@ -340,13 +340,45 @@ static unsigned find_battery_quirk(struct hid_device *hdev)
340
340
return quirks ;
341
341
}
342
342
343
+ static int hidinput_scale_battery_capacity (struct hid_device * dev ,
344
+ int value )
345
+ {
346
+ if (dev -> battery_min < dev -> battery_max &&
347
+ value >= dev -> battery_min && value <= dev -> battery_max )
348
+ value = ((value - dev -> battery_min ) * 100 ) /
349
+ (dev -> battery_max - dev -> battery_min );
350
+
351
+ return value ;
352
+ }
353
+
354
+ static int hidinput_query_battery_capacity (struct hid_device * dev )
355
+ {
356
+ u8 * buf ;
357
+ int ret ;
358
+
359
+ buf = kmalloc (2 , GFP_KERNEL );
360
+ if (!buf )
361
+ return - ENOMEM ;
362
+
363
+ ret = hid_hw_raw_request (dev , dev -> battery_report_id , buf , 2 ,
364
+ dev -> battery_report_type , HID_REQ_GET_REPORT );
365
+ if (ret != 2 ) {
366
+ kfree (buf );
367
+ return - ENODATA ;
368
+ }
369
+
370
+ ret = hidinput_scale_battery_capacity (dev , buf [1 ]);
371
+ kfree (buf );
372
+ return ret ;
373
+ }
374
+
343
375
static int hidinput_get_battery_property (struct power_supply * psy ,
344
376
enum power_supply_property prop ,
345
377
union power_supply_propval * val )
346
378
{
347
379
struct hid_device * dev = power_supply_get_drvdata (psy );
380
+ int value ;
348
381
int ret = 0 ;
349
- __u8 * buf ;
350
382
351
383
switch (prop ) {
352
384
case POWER_SUPPLY_PROP_PRESENT :
@@ -355,37 +387,38 @@ static int hidinput_get_battery_property(struct power_supply *psy,
355
387
break ;
356
388
357
389
case POWER_SUPPLY_PROP_CAPACITY :
358
-
359
- buf = kmalloc (2 * sizeof (__u8 ), GFP_KERNEL );
360
- if (!buf ) {
361
- ret = - ENOMEM ;
362
- break ;
363
- }
364
- ret = hid_hw_raw_request (dev , dev -> battery_report_id , buf , 2 ,
365
- dev -> battery_report_type ,
366
- HID_REQ_GET_REPORT );
367
-
368
- if (ret != 2 ) {
369
- ret = - ENODATA ;
370
- kfree (buf );
371
- break ;
390
+ if (dev -> battery_report_type == HID_FEATURE_REPORT ) {
391
+ value = hidinput_query_battery_capacity (dev );
392
+ if (value < 0 )
393
+ return value ;
394
+ } else {
395
+ value = dev -> battery_capacity ;
372
396
}
373
- ret = 0 ;
374
397
375
- if (dev -> battery_min < dev -> battery_max &&
376
- buf [1 ] >= dev -> battery_min &&
377
- buf [1 ] <= dev -> battery_max )
378
- val -> intval = (100 * (buf [1 ] - dev -> battery_min )) /
379
- (dev -> battery_max - dev -> battery_min );
380
- kfree (buf );
398
+ val -> intval = value ;
381
399
break ;
382
400
383
401
case POWER_SUPPLY_PROP_MODEL_NAME :
384
402
val -> strval = dev -> name ;
385
403
break ;
386
404
387
405
case POWER_SUPPLY_PROP_STATUS :
388
- val -> intval = POWER_SUPPLY_STATUS_DISCHARGING ;
406
+ if (!dev -> battery_reported &&
407
+ dev -> battery_report_type == HID_FEATURE_REPORT ) {
408
+ value = hidinput_query_battery_capacity (dev );
409
+ if (value < 0 )
410
+ return value ;
411
+
412
+ dev -> battery_capacity = value ;
413
+ dev -> battery_reported = true;
414
+ }
415
+
416
+ if (!dev -> battery_reported )
417
+ val -> intval = POWER_SUPPLY_STATUS_UNKNOWN ;
418
+ else if (dev -> battery_capacity == 100 )
419
+ val -> intval = POWER_SUPPLY_STATUS_FULL ;
420
+ else
421
+ val -> intval = POWER_SUPPLY_STATUS_DISCHARGING ;
389
422
break ;
390
423
391
424
case POWER_SUPPLY_PROP_SCOPE :
@@ -400,35 +433,33 @@ static int hidinput_get_battery_property(struct power_supply *psy,
400
433
return ret ;
401
434
}
402
435
403
- static bool hidinput_setup_battery (struct hid_device * dev , unsigned report_type , struct hid_field * field )
436
+ static int hidinput_setup_battery (struct hid_device * dev , unsigned report_type , struct hid_field * field )
404
437
{
405
- struct power_supply_desc * psy_desc = NULL ;
438
+ struct power_supply_desc * psy_desc ;
406
439
struct power_supply_config psy_cfg = { .drv_data = dev , };
407
440
unsigned quirks ;
408
441
s32 min , max ;
442
+ int error ;
409
443
410
- if (field -> usage -> hid != HID_DC_BATTERYSTRENGTH )
411
- return false; /* no match */
412
-
413
- if (dev -> battery != NULL )
414
- goto out ; /* already initialized? */
444
+ if (dev -> battery )
445
+ return 0 ; /* already initialized? */
415
446
416
447
quirks = find_battery_quirk (dev );
417
448
418
449
hid_dbg (dev , "device %x:%x:%x %d quirks %d\n" ,
419
450
dev -> bus , dev -> vendor , dev -> product , dev -> version , quirks );
420
451
421
452
if (quirks & HID_BATTERY_QUIRK_IGNORE )
422
- goto out ;
453
+ return 0 ;
423
454
424
455
psy_desc = kzalloc (sizeof (* psy_desc ), GFP_KERNEL );
425
- if (psy_desc == NULL )
426
- goto out ;
456
+ if (! psy_desc )
457
+ return - ENOMEM ;
427
458
428
459
psy_desc -> name = kasprintf (GFP_KERNEL , "hid-%s-battery" , dev -> uniq );
429
- if (psy_desc -> name == NULL ) {
430
- kfree ( psy_desc ) ;
431
- goto out ;
460
+ if (! psy_desc -> name ) {
461
+ error = - ENOMEM ;
462
+ goto err_free_mem ;
432
463
}
433
464
434
465
psy_desc -> type = POWER_SUPPLY_TYPE_BATTERY ;
@@ -455,17 +486,20 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
455
486
456
487
dev -> battery = power_supply_register (& dev -> dev , psy_desc , & psy_cfg );
457
488
if (IS_ERR (dev -> battery )) {
458
- hid_warn (dev , "can't register power supply: %ld\n" ,
459
- PTR_ERR (dev -> battery ));
460
- kfree (psy_desc -> name );
461
- kfree (psy_desc );
462
- dev -> battery = NULL ;
463
- } else {
464
- power_supply_powers (dev -> battery , & dev -> dev );
489
+ error = PTR_ERR (dev -> battery );
490
+ hid_warn (dev , "can't register power supply: %d\n" , error );
491
+ goto err_free_name ;
465
492
}
466
493
467
- out :
468
- return true;
494
+ power_supply_powers (dev -> battery , & dev -> dev );
495
+ return 0 ;
496
+
497
+ err_free_name :
498
+ kfree (psy_desc -> name );
499
+ err_free_mem :
500
+ kfree (psy_desc );
501
+ dev -> battery = NULL ;
502
+ return error ;
469
503
}
470
504
471
505
static void hidinput_cleanup_battery (struct hid_device * dev )
@@ -481,16 +515,33 @@ static void hidinput_cleanup_battery(struct hid_device *dev)
481
515
kfree (psy_desc );
482
516
dev -> battery = NULL ;
483
517
}
518
+
519
+ static void hidinput_update_battery (struct hid_device * dev , int value )
520
+ {
521
+ if (!dev -> battery )
522
+ return ;
523
+
524
+ if (value == 0 || value < dev -> battery_min || value > dev -> battery_max )
525
+ return ;
526
+
527
+ dev -> battery_capacity = hidinput_scale_battery_capacity (dev , value );
528
+ dev -> battery_reported = true;
529
+ power_supply_changed (dev -> battery );
530
+ }
484
531
#else /* !CONFIG_HID_BATTERY_STRENGTH */
485
- static bool hidinput_setup_battery (struct hid_device * dev , unsigned report_type ,
486
- struct hid_field * field )
532
+ static int hidinput_setup_battery (struct hid_device * dev , unsigned report_type ,
533
+ struct hid_field * field )
487
534
{
488
- return false ;
535
+ return 0 ;
489
536
}
490
537
491
538
static void hidinput_cleanup_battery (struct hid_device * dev )
492
539
{
493
540
}
541
+
542
+ static void hidinput_update_battery (struct hid_device * dev , int value )
543
+ {
544
+ }
494
545
#endif /* CONFIG_HID_BATTERY_STRENGTH */
495
546
496
547
static void hidinput_configure_usage (struct hid_input * hidinput , struct hid_field * field ,
@@ -710,6 +761,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
710
761
}
711
762
break ;
712
763
764
+ case 0x3b : /* Battery Strength */
765
+ hidinput_setup_battery (device , HID_INPUT_REPORT , field );
766
+ usage -> type = EV_PWR ;
767
+ goto ignore ;
768
+
713
769
case 0x3c : /* Invert */
714
770
map_key_clear (BTN_TOOL_RUBBER );
715
771
break ;
@@ -944,11 +1000,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
944
1000
break ;
945
1001
946
1002
case HID_UP_GENDEVCTRLS :
947
- if (hidinput_setup_battery (device , HID_INPUT_REPORT , field ))
1003
+ switch (usage -> hid ) {
1004
+ case HID_DC_BATTERYSTRENGTH :
1005
+ hidinput_setup_battery (device , HID_INPUT_REPORT , field );
1006
+ usage -> type = EV_PWR ;
948
1007
goto ignore ;
949
- else
950
- goto unknown ;
951
- break ;
1008
+ }
1009
+ goto unknown ;
952
1010
953
1011
case HID_UP_HPVENDOR : /* Reported on a Dutch layout HP5308 */
954
1012
set_bit (EV_REP , input -> evbit );
@@ -1031,7 +1089,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
1031
1089
if (usage -> code > max )
1032
1090
goto ignore ;
1033
1091
1034
-
1035
1092
if (usage -> type == EV_ABS ) {
1036
1093
1037
1094
int a = field -> logical_minimum ;
@@ -1090,14 +1147,19 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
1090
1147
struct input_dev * input ;
1091
1148
unsigned * quirks = & hid -> quirks ;
1092
1149
1093
- if (!field -> hidinput )
1150
+ if (!usage -> type )
1094
1151
return ;
1095
1152
1096
- input = field -> hidinput -> input ;
1153
+ if (usage -> type == EV_PWR ) {
1154
+ hidinput_update_battery (hid , value );
1155
+ return ;
1156
+ }
1097
1157
1098
- if (!usage -> type )
1158
+ if (!field -> hidinput )
1099
1159
return ;
1100
1160
1161
+ input = field -> hidinput -> input ;
1162
+
1101
1163
if (usage -> hat_min < usage -> hat_max || usage -> hat_dir ) {
1102
1164
int hat_dir = usage -> hat_dir ;
1103
1165
if (!hat_dir )
@@ -1373,6 +1435,7 @@ static void report_features(struct hid_device *hid)
1373
1435
struct hid_driver * drv = hid -> driver ;
1374
1436
struct hid_report_enum * rep_enum ;
1375
1437
struct hid_report * rep ;
1438
+ struct hid_usage * usage ;
1376
1439
int i , j ;
1377
1440
1378
1441
rep_enum = & hid -> report_enum [HID_FEATURE_REPORT ];
@@ -1383,12 +1446,15 @@ static void report_features(struct hid_device *hid)
1383
1446
continue ;
1384
1447
1385
1448
for (j = 0 ; j < rep -> field [i ]-> maxusage ; j ++ ) {
1449
+ usage = & rep -> field [i ]-> usage [j ];
1450
+
1386
1451
/* Verify if Battery Strength feature is available */
1387
- hidinput_setup_battery (hid , HID_FEATURE_REPORT , rep -> field [i ]);
1452
+ if (usage -> hid == HID_DC_BATTERYSTRENGTH )
1453
+ hidinput_setup_battery (hid , HID_FEATURE_REPORT ,
1454
+ rep -> field [i ]);
1388
1455
1389
1456
if (drv -> feature_mapping )
1390
- drv -> feature_mapping (hid , rep -> field [i ],
1391
- rep -> field [i ]-> usage + j );
1457
+ drv -> feature_mapping (hid , rep -> field [i ], usage );
1392
1458
}
1393
1459
}
1394
1460
}
0 commit comments