aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/battery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r--drivers/acpi/battery.c164
1 files changed, 95 insertions, 69 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 681e26b56b11..c2ce0ad21693 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -125,11 +125,15 @@ static int acpi_battery_technology(struct acpi_battery *battery)
125 return POWER_SUPPLY_TECHNOLOGY_NiMH; 125 return POWER_SUPPLY_TECHNOLOGY_NiMH;
126 if (!strcasecmp("LION", battery->type)) 126 if (!strcasecmp("LION", battery->type))
127 return POWER_SUPPLY_TECHNOLOGY_LION; 127 return POWER_SUPPLY_TECHNOLOGY_LION;
128 if (!strcasecmp("LI-ION", battery->type))
129 return POWER_SUPPLY_TECHNOLOGY_LION;
128 if (!strcasecmp("LiP", battery->type)) 130 if (!strcasecmp("LiP", battery->type))
129 return POWER_SUPPLY_TECHNOLOGY_LIPO; 131 return POWER_SUPPLY_TECHNOLOGY_LIPO;
130 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 132 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
131} 133}
132 134
135static int acpi_battery_update(struct acpi_battery *battery);
136
133static int acpi_battery_get_property(struct power_supply *psy, 137static int acpi_battery_get_property(struct power_supply *psy,
134 enum power_supply_property psp, 138 enum power_supply_property psp,
135 union power_supply_propval *val) 139 union power_supply_propval *val)
@@ -139,6 +143,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
139 if ((!acpi_battery_present(battery)) && 143 if ((!acpi_battery_present(battery)) &&
140 psp != POWER_SUPPLY_PROP_PRESENT) 144 psp != POWER_SUPPLY_PROP_PRESENT)
141 return -ENODEV; 145 return -ENODEV;
146 acpi_battery_update(battery);
142 switch (psp) { 147 switch (psp) {
143 case POWER_SUPPLY_PROP_STATUS: 148 case POWER_SUPPLY_PROP_STATUS:
144 if (battery->state & 0x01) 149 if (battery->state & 0x01)
@@ -257,7 +262,7 @@ static int extract_package(struct acpi_battery *battery,
257 union acpi_object *package, 262 union acpi_object *package,
258 struct acpi_offsets *offsets, int num) 263 struct acpi_offsets *offsets, int num)
259{ 264{
260 int i, *x; 265 int i;
261 union acpi_object *element; 266 union acpi_object *element;
262 if (package->type != ACPI_TYPE_PACKAGE) 267 if (package->type != ACPI_TYPE_PACKAGE)
263 return -EFAULT; 268 return -EFAULT;
@@ -266,16 +271,21 @@ static int extract_package(struct acpi_battery *battery,
266 return -EFAULT; 271 return -EFAULT;
267 element = &package->package.elements[i]; 272 element = &package->package.elements[i];
268 if (offsets[i].mode) { 273 if (offsets[i].mode) {
269 if (element->type != ACPI_TYPE_STRING && 274 u8 *ptr = (u8 *)battery + offsets[i].offset;
270 element->type != ACPI_TYPE_BUFFER) 275 if (element->type == ACPI_TYPE_STRING ||
271 return -EFAULT; 276 element->type == ACPI_TYPE_BUFFER)
272 strncpy((u8 *)battery + offsets[i].offset, 277 strncpy(ptr, element->string.pointer, 32);
273 element->string.pointer, 32); 278 else if (element->type == ACPI_TYPE_INTEGER) {
279 strncpy(ptr, (u8 *)&element->integer.value,
280 sizeof(acpi_integer));
281 ptr[sizeof(acpi_integer)] = 0;
282 } else return -EFAULT;
274 } else { 283 } else {
275 if (element->type != ACPI_TYPE_INTEGER) 284 if (element->type == ACPI_TYPE_INTEGER) {
276 return -EFAULT; 285 int *x = (int *)((u8 *)battery +
277 x = (int *)((u8 *)battery + offsets[i].offset); 286 offsets[i].offset);
278 *x = element->integer.value; 287 *x = element->integer.value;
288 } else return -EFAULT;
279 } 289 }
280 } 290 }
281 return 0; 291 return 0;
@@ -385,29 +395,81 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
385 return acpi_battery_set_alarm(battery); 395 return acpi_battery_set_alarm(battery);
386} 396}
387 397
398static ssize_t acpi_battery_alarm_show(struct device *dev,
399 struct device_attribute *attr,
400 char *buf)
401{
402 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
403 return sprintf(buf, "%d\n", battery->alarm * 1000);
404}
405
406static ssize_t acpi_battery_alarm_store(struct device *dev,
407 struct device_attribute *attr,
408 const char *buf, size_t count)
409{
410 unsigned long x;
411 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
412 if (sscanf(buf, "%ld\n", &x) == 1)
413 battery->alarm = x/1000;
414 if (acpi_battery_present(battery))
415 acpi_battery_set_alarm(battery);
416 return count;
417}
418
419static struct device_attribute alarm_attr = {
420 .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
421 .show = acpi_battery_alarm_show,
422 .store = acpi_battery_alarm_store,
423};
424
425static int sysfs_add_battery(struct acpi_battery *battery)
426{
427 int result;
428
429 battery->update_time = 0;
430 result = acpi_battery_get_info(battery);
431 acpi_battery_init_alarm(battery);
432 if (result)
433 return result;
434 if (battery->power_unit) {
435 battery->bat.properties = charge_battery_props;
436 battery->bat.num_properties =
437 ARRAY_SIZE(charge_battery_props);
438 } else {
439 battery->bat.properties = energy_battery_props;
440 battery->bat.num_properties =
441 ARRAY_SIZE(energy_battery_props);
442 }
443
444 battery->bat.name = acpi_device_bid(battery->device);
445 battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
446 battery->bat.get_property = acpi_battery_get_property;
447
448 result = power_supply_register(&battery->device->dev, &battery->bat);
449 if (result)
450 return result;
451 return device_create_file(battery->bat.dev, &alarm_attr);
452}
453
454static void sysfs_remove_battery(struct acpi_battery *battery)
455{
456 if (!battery->bat.dev)
457 return;
458 device_remove_file(battery->bat.dev, &alarm_attr);
459 power_supply_unregister(&battery->bat);
460}
461
388static int acpi_battery_update(struct acpi_battery *battery) 462static int acpi_battery_update(struct acpi_battery *battery)
389{ 463{
390 int saved_present = acpi_battery_present(battery);
391 int result = acpi_battery_get_status(battery); 464 int result = acpi_battery_get_status(battery);
392 if (result || !acpi_battery_present(battery)) 465 if (result)
393 return result; 466 return result;
394 if (saved_present != acpi_battery_present(battery) || 467 if (!acpi_battery_present(battery)) {
395 !battery->update_time) { 468 sysfs_remove_battery(battery);
396 battery->update_time = 0; 469 return 0;
397 result = acpi_battery_get_info(battery);
398 if (result)
399 return result;
400 if (battery->power_unit) {
401 battery->bat.properties = charge_battery_props;
402 battery->bat.num_properties =
403 ARRAY_SIZE(charge_battery_props);
404 } else {
405 battery->bat.properties = energy_battery_props;
406 battery->bat.num_properties =
407 ARRAY_SIZE(energy_battery_props);
408 }
409 acpi_battery_init_alarm(battery);
410 } 470 }
471 if (!battery->bat.dev)
472 sysfs_add_battery(battery);
411 return acpi_battery_get_state(battery); 473 return acpi_battery_get_state(battery);
412} 474}
413 475
@@ -554,10 +616,6 @@ static ssize_t acpi_battery_write_alarm(struct file *file,
554 616
555 if (!battery || (count > sizeof(alarm_string) - 1)) 617 if (!battery || (count > sizeof(alarm_string) - 1))
556 return -EINVAL; 618 return -EINVAL;
557 if (result) {
558 result = -ENODEV;
559 goto end;
560 }
561 if (!acpi_battery_present(battery)) { 619 if (!acpi_battery_present(battery)) {
562 result = -ENODEV; 620 result = -ENODEV;
563 goto end; 621 goto end;
@@ -688,33 +746,6 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
688 746
689#endif 747#endif
690 748
691static ssize_t acpi_battery_alarm_show(struct device *dev,
692 struct device_attribute *attr,
693 char *buf)
694{
695 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
696 return sprintf(buf, "%d\n", battery->alarm * 1000);
697}
698
699static ssize_t acpi_battery_alarm_store(struct device *dev,
700 struct device_attribute *attr,
701 const char *buf, size_t count)
702{
703 unsigned long x;
704 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
705 if (sscanf(buf, "%ld\n", &x) == 1)
706 battery->alarm = x/1000;
707 if (acpi_battery_present(battery))
708 acpi_battery_set_alarm(battery);
709 return count;
710}
711
712static struct device_attribute alarm_attr = {
713 .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
714 .show = acpi_battery_alarm_show,
715 .store = acpi_battery_alarm_store,
716};
717
718/* -------------------------------------------------------------------------- 749/* --------------------------------------------------------------------------
719 Driver Interface 750 Driver Interface
720 -------------------------------------------------------------------------- */ 751 -------------------------------------------------------------------------- */
@@ -732,7 +763,9 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
732 acpi_bus_generate_netlink_event(device->pnp.device_class, 763 acpi_bus_generate_netlink_event(device->pnp.device_class,
733 device->dev.bus_id, event, 764 device->dev.bus_id, event,
734 acpi_battery_present(battery)); 765 acpi_battery_present(battery));
735 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); 766 /* acpi_batter_update could remove power_supply object */
767 if (battery->bat.dev)
768 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
736} 769}
737 770
738static int acpi_battery_add(struct acpi_device *device) 771static int acpi_battery_add(struct acpi_device *device)
@@ -756,11 +789,6 @@ static int acpi_battery_add(struct acpi_device *device)
756 if (result) 789 if (result)
757 goto end; 790 goto end;
758#endif 791#endif
759 battery->bat.name = acpi_device_bid(device);
760 battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
761 battery->bat.get_property = acpi_battery_get_property;
762 result = power_supply_register(&battery->device->dev, &battery->bat);
763 result = device_create_file(battery->bat.dev, &alarm_attr);
764 status = acpi_install_notify_handler(device->handle, 792 status = acpi_install_notify_handler(device->handle,
765 ACPI_ALL_NOTIFY, 793 ACPI_ALL_NOTIFY,
766 acpi_battery_notify, battery); 794 acpi_battery_notify, battery);
@@ -796,10 +824,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
796#ifdef CONFIG_ACPI_PROCFS 824#ifdef CONFIG_ACPI_PROCFS
797 acpi_battery_remove_fs(device); 825 acpi_battery_remove_fs(device);
798#endif 826#endif
799 if (battery->bat.dev) { 827 sysfs_remove_battery(battery);
800 device_remove_file(battery->bat.dev, &alarm_attr);
801 power_supply_unregister(&battery->bat);
802 }
803 mutex_destroy(&battery->lock); 828 mutex_destroy(&battery->lock);
804 kfree(battery); 829 kfree(battery);
805 return 0; 830 return 0;
@@ -813,6 +838,7 @@ static int acpi_battery_resume(struct acpi_device *device)
813 return -EINVAL; 838 return -EINVAL;
814 battery = acpi_driver_data(device); 839 battery = acpi_driver_data(device);
815 battery->update_time = 0; 840 battery->update_time = 0;
841 acpi_battery_update(battery);
816 return 0; 842 return 0;
817} 843}
818 844