Index: build/jam/HaikuImage
===================================================================
--- build/jam/HaikuImage	(revisione 31122)
+++ build/jam/HaikuImage	(copia locale)
@@ -205,6 +205,7 @@
 AddNewDriversToHaikuImage disk scsi	: scsi_cd scsi_disk ;
 AddNewDriversToHaikuImage power : $(X86_ONLY)enhanced_speedstep ;
 AddNewDriversToHaikuImage power : $(X86_ONLY)acpi_embedded_controller ;
+AddNewDriversToHaikuImage power : $(X86_ONLY)acpi_battery ;
 
 # legacy drivers
 AddDriversToHaikuImage				: console dprintf $(X86_ONLY)keyboard null
Index: src/add-ons/kernel/drivers/power/acpi_battery/Jamfile
===================================================================
--- src/add-ons/kernel/drivers/power/acpi_battery/Jamfile	(revisione 0)
+++ src/add-ons/kernel/drivers/power/acpi_battery/Jamfile	(revisione 0)
@@ -0,0 +1,15 @@
+SubDir HAIKU_TOP src add-ons kernel drivers power acpi_battery ;
+
+SetSubDirSupportedPlatformsBeOSCompatible ;
+
+if $(TARGET_PLATFORM) != haiku {
+	# Needed for <ACPI.h>. Unfortunately we also get the other headers there,
+	# that we don't really want.
+	UsePublicHeaders drivers ;
+}
+
+KernelAddon acpi_battery :
+	acpi_battery.c
+	;
+
+Depends acpi_battery : acpi ;
Index: src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.c
===================================================================
--- src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.c	(revisione 0)
+++ src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.c	(revisione 0)
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2009 Francesco Piccinno <stack.box@gmail.com>
+ *
+ * Simple acpi_battery implementation for haiku ported from Linux.
+ *
+ * Distributed under the terms of the MIT License.
+ */
+
+#include <KernelExport.h>
+#include <Drivers.h>
+#include <Errors.h>
+#include <string.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ACPI.h>
+#include "acpi_battery.h"
+
+#define ACPI_BATTERY_MODULE_NAME "drivers/power/acpi_battery/driver_v1"
+
+#define ACPI_BATTERY_DEVICE_MODULE_NAME "drivers/power/acpi_battery/device_v1"
+
+/* Base Namespace devices are published to */
+#define ACPI_BATTERY_BASENAME "power/acpi_battery/%d"
+
+// name of pnp generator of path ids
+#define ACPI_BATTERY_PATHID_GENERATOR "acpi_battery/path_id"
+
+#define TRACE_ACPI_BATTERY
+
+#ifdef TRACE_ACPI_BATTERY
+#   define TRACE(x...) dprintf("acpi_battery: " x)
+#else
+#   define TRACE(x...)
+#endif
+
+static device_manager_info *sDeviceManager;
+
+typedef struct acpi_ns_device_info {
+    device_node *node;
+    acpi_device_module_info *acpi;
+    acpi_device acpi_cookie;
+    acpi_battery_type *battery;
+} acpi_battery_device_info;
+
+/* Proto */
+static status_t acpi_battery_control(void*, uint32, void*, size_t);
+
+inline int
+acpi_battery_present(acpi_battery_device_info *device)
+{
+    return device->battery->status.battery_present;
+}
+
+static inline char *acpi_battery_units(struct acpi_battery_type *battery)
+{
+    return (battery->power_unit) ? "mA" : "mW";
+}
+
+static int acpi_extract_package(struct acpi_battery_type *battery,
+                                 acpi_object_type *package,
+                                 struct acpi_offsets *offsets, int num)
+{
+    int i;
+    acpi_object_type *element;
+
+    if (package->object_type != ACPI_TYPE_PACKAGE)
+        return B_ERROR;
+
+    for (i = 0; i < num; ++i) {
+        if (package->data.package.count <= i)
+            return B_ERROR;
+
+        element = &package->data.package.objects[i];
+
+        if (offsets[i].mode) {
+            uint8 *ptr = (uint8 *)battery + offsets[i].offset;
+
+            if (element->object_type == ACPI_TYPE_STRING ||
+                element->object_type == ACPI_TYPE_BUFFER)
+                    strncpy((char *)ptr, element->data.string.string, 32);
+
+            else if (element->object_type == ACPI_TYPE_INTEGER) {
+                strncpy((char *)ptr, (char *)&element->data.integer,
+                        sizeof(uint32));
+                ptr[sizeof(uint32)] = 0;
+            } else
+                *ptr = 0; /* don't have value */
+        } else {
+            int *x = (int *)((uint8 *)battery + offsets[i].offset);
+            *x = (element->object_type == ACPI_TYPE_INTEGER) ?
+                    element->data.integer : -1;
+        }
+    }
+    return B_OK;
+}
+
+static int
+acpi_bus_get_status (acpi_battery_device_info *device, acpi_battery_type *batt)
+{
+    acpi_data buf;
+    acpi_object_type object;
+    buf.pointer = &object;
+    buf.length = sizeof(acpi_object_type);
+
+    status_t status = B_OK;
+
+    if (!device)
+        return B_ERROR;
+
+    status = device->acpi->evaluate_method(device->acpi_cookie, "_STA",
+                                           NULL, &buf);
+
+    if (status == B_OK) {
+        if (object.object_type == ACPI_TYPE_INTEGER)
+            (*((int*)&batt->status)) = (int)object.data.integer;
+        else
+            status = B_ERROR;
+    }
+
+    if (status == B_ERROR)
+        (*((int*)&batt->status)) = 0x0F;
+
+    return B_ERROR;
+}
+
+static status_t
+acpi_battery_init_device(void *_cookie, void **cookie)
+{
+    device_node *node = (device_node *)_cookie;
+    acpi_battery_device_info *device;
+    device_node *parent;
+
+    device = \
+        (acpi_battery_device_info *)malloc(sizeof(acpi_battery_device_info));
+
+    if (device == NULL)
+        return B_NO_MEMORY;
+
+    memset(device, 0, sizeof(acpi_battery_device_info));
+
+    device->battery = (acpi_battery_type *)malloc(sizeof(acpi_battery_type));
+
+    if (device->battery == NULL)
+        return B_NO_MEMORY;
+
+    memset(device->battery, 0, sizeof(acpi_battery_type));
+
+    device->node = node;
+
+    parent = sDeviceManager->get_parent_node(node);
+    sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
+        (void **)&device->acpi_cookie);
+    sDeviceManager->put_node(parent);
+
+    *cookie = device;
+
+    return B_OK;
+}
+
+static void
+acpi_battery_uninit_device(void *_cookie)
+{
+    acpi_battery_device_info *device = (acpi_battery_device_info *)_cookie;
+
+    if (device) {
+        if (device->battery)
+            free(device->battery);
+        free(device);
+    }
+}
+
+static status_t
+acpi_battery_open(void *_cookie, const char *path, int flags, void** cookie)
+{
+    acpi_battery_device_info *device = (acpi_battery_device_info *)_cookie;
+    *cookie = device;
+    return B_OK;
+}
+
+static status_t
+acpi_battery_control(void* _cookie, uint32 op, void* arg, size_t len)
+{
+    acpi_battery_device_info* device = (acpi_battery_device_info*)_cookie;
+    status_t err = B_ERROR;
+
+    acpi_data buf;
+    buf.pointer = NULL;
+    buf.length = ACPI_ALLOCATE_BUFFER;
+
+    acpi_battery_type *att;
+
+    if (arg == NULL)
+        att = (acpi_battery_type *)device->battery;
+    else
+        att = (acpi_battery_type *)arg;
+
+    if (att == NULL) {
+        TRACE("NULL pointer\n");
+        return B_ERROR;
+    }
+
+    switch (op) {
+        case drvOpGetBatteryState: {
+            TRACE("evaluating _BST to get battery state: ");
+
+            err = device->acpi->evaluate_method(device->acpi_cookie, "_BST",
+                                                NULL, &buf);
+
+            if (err != B_OK)
+                break;
+
+            err = acpi_extract_package(att, buf.pointer, state_offsets,
+                                       ARRAY_SIZE(state_offsets));
+            break;
+        }
+        case drvOpGetBatteryInfo: {
+            TRACE("evaluating _BIF to get battery informations: ");
+
+            err = device->acpi->evaluate_method(device->acpi_cookie, "_BIF",
+                                                NULL, &buf);
+
+            if (err != B_OK)
+                break;
+
+            err = acpi_extract_package(att, buf.pointer, info_offsets,
+                                       ARRAY_SIZE(info_offsets));
+            break;
+        }
+        case drvOpGetBatteryPresent: {
+            TRACE("evaluating _STA to check for battery presence: ");
+            err = acpi_bus_get_status(device, att);
+            break;
+        }
+    }
+
+    if (buf.pointer)
+        free(buf.pointer);
+
+    if (err == B_OK)
+        TRACE("ok :)\n");
+    else
+        TRACE("argh. error!\n");
+
+    return err;
+}
+
+
+static status_t
+acpi_battery_read(void* _cookie, off_t position, void *buf, size_t* num_bytes)
+{
+    acpi_battery_device_info* device = (acpi_battery_device_info*)_cookie;
+
+    if (*num_bytes < 1)
+        return B_IO_ERROR;
+
+    if (device == NULL) {
+        TRACE("are you kidding me man? cookie is NULL\n");
+        return B_ERROR;
+    }
+
+    if (position == 0) {
+        size_t ret;
+        size_t max_len = *num_bytes;
+        char *str = (char *)buf;
+
+        TRACE("reading battery state via ioctl()\n");
+
+        acpi_battery_control(device, drvOpGetBatteryPresent, NULL, 0);
+        acpi_battery_control(device, drvOpGetBatteryInfo, NULL, 0);
+        acpi_battery_control(device, drvOpGetBatteryState, NULL, 0);
+
+        ret = snprintf(str, max_len, "Present: %s\n",
+                       acpi_battery_present(device) ? "yes" : "no");
+
+        max_len -= ret;
+        str += ret;
+
+        if (!acpi_battery_present(device))
+            goto end;
+
+        ret = snprintf(str, max_len, "Capacity state: %s\n",
+                       (device->battery->state & 0x04) ? "critical" : "ok");
+
+        max_len -= ret;
+        str += ret;
+
+        if ((device->battery->state & 0x01) && (device->battery->state & 0x02))
+            ret = snprintf(str, max_len,
+                           "Charging state: charging/discharging\n");
+        else if (device->battery->state & 0x01)
+            ret = snprintf(str, max_len, "Charging state: discharging\n");
+        else if (device->battery->state & 0x02)
+            ret = snprintf(str, max_len, "Charging state: charging\n");
+        else
+            ret = snprintf(str, max_len, "Charging state: charged\n");
+
+        max_len -= ret;
+        str += ret;
+
+        if (device->battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN)
+            ret = snprintf(str, max_len, "Present rate: unknown\n");
+        else
+            ret = snprintf(str, max_len, "Present rate: %d %s\n",
+                           device->battery->current_now,
+                           acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        if (device->battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
+            ret = snprintf(str, max_len, "Remaining capacity: unknown\n");
+        else
+            ret = snprintf(str, max_len, "Remaining capacity: %d %sh\n",
+                           device->battery->capacity_now,
+                           acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        if (device->battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
+            ret = snprintf(str, max_len, "Present voltage: unknown\n");
+        else
+            ret = snprintf(str, max_len, "Present voltage: %d mV\n",
+                           device->battery->voltage_now);
+
+        max_len -= ret;
+        str += ret;
+
+        if (device->battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+            ret = snprintf(str, max_len, "Design capacity: unknown\n");
+        else
+            ret = snprintf(str, max_len, "Design capacity: %d %sh\n",
+                           device->battery->design_capacity,
+                           acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        if (device->battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+            ret = snprintf(str, max_len, "Last full capacity: unknown\n");
+        else
+            ret = snprintf(str, max_len, "Last full capacity: %d %sh\n",
+                           device->battery->full_charge_capacity,
+                           acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Battery technology: %srechargeable\n",
+                       (!device->battery->technology)?"non-":"");
+
+        max_len -= ret;
+        str += ret;
+
+        if (device->battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
+            ret = snprintf(str, max_len, "Design voltage: unknown\n");
+        else
+            ret = snprintf(str, max_len, "Design voltage: %d mV\n",
+                           device->battery->design_voltage);
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Design capacity warning: %d %sh\n",
+                       device->battery->design_capacity_warning,
+                       acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Design capacity low: %d %sh\n",
+                       device->battery->design_capacity_low,
+                       acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Capacity granularity 1: %d %sh\n",
+                 device->battery->capacity_granularity_1,
+                 acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Capacity granularity 2: %d %sh\n",
+                       device->battery->capacity_granularity_2,
+                       acpi_battery_units(device->battery));
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Model number: %s\n",
+                       device->battery->model_number);
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Serial number: %s\n",
+                       device->battery->serial_number);
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "Battery type: %s\n",
+                       device->battery->type);
+
+        max_len -= ret;
+        str += ret;
+
+        ret = snprintf(str, max_len, "OEM info: %s\n",
+                       device->battery->oem_info);
+
+end:
+        *num_bytes = strlen((char *)buf);
+
+    } else {
+        *num_bytes = 0;
+    }
+
+    return B_OK;
+}
+
+
+static status_t
+acpi_battery_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
+{
+    return B_ERROR;
+}
+
+
+static status_t
+acpi_battery_close (void* cookie)
+{
+    return B_OK;
+}
+
+
+static status_t
+acpi_battery_free (void* cookie)
+{
+    return B_OK;
+}
+
+//    #pragma mark - driver module API
+
+static int32
+acpi_get_type(device_node* dev)
+{
+    const char *bus;
+    if (sDeviceManager->get_attr_string(dev, B_DEVICE_BUS, &bus, false))
+        return -1;
+
+    if (strcmp(bus, "acpi"))
+        return -1;
+
+    uint32 deviceType;
+    if (sDeviceManager->get_attr_uint32(dev, ACPI_DEVICE_TYPE_ITEM,
+        &deviceType, false) != B_OK)
+        return -1;
+
+    return deviceType;
+}
+
+static float
+acpi_battery_support(device_node *dev)
+{
+    static char *bat_ids[] = { "PNP0C0A", NULL };
+
+    if (acpi_get_type(dev) != ACPI_TYPE_DEVICE)
+        return 0.0;
+
+    const char *name;
+    if (sDeviceManager->get_attr_string(dev, ACPI_DEVICE_HID_ITEM, &name,
+        false) != B_OK || strcmp(name, bat_ids[0]))
+        return 0.0;
+
+    TRACE("acpi_battery: got it man!\n");
+
+    return 0.6;
+}
+
+
+static status_t
+acpi_battery_register_device(device_node *node)
+{
+    device_attr attrs[] = {
+        { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI Battery" }},
+        { NULL }
+    };
+
+    return sDeviceManager->register_node(node, ACPI_BATTERY_MODULE_NAME, attrs,
+                                          NULL, NULL);
+}
+
+
+static status_t
+acpi_battery_init_driver(device_node *node, void **cookie)
+{
+    TRACE("(C) 2009 - Francesco Piccinno <stack.box@gmail.com>\n");
+    *cookie = node;
+    return B_OK;
+}
+
+
+static void
+acpi_battery_uninit_driver(void *driverCookie)
+{
+}
+
+
+static status_t
+acpi_battery_register_child_devices(void *_cookie)
+{
+    device_node *node = _cookie;
+    int path_id;
+    char name[128];
+
+    TRACE("acpi_battery_register_child_devices\n");
+
+    path_id = sDeviceManager->create_id(ACPI_BATTERY_PATHID_GENERATOR);
+    if (path_id < 0) {
+        TRACE("register_child_devices: couldn't create a path_id\n");
+        return B_ERROR;
+    }
+
+    snprintf(name, sizeof(name), ACPI_BATTERY_BASENAME, path_id);
+
+    return sDeviceManager->publish_device(node, name,
+                                           ACPI_BATTERY_DEVICE_MODULE_NAME);
+}
+
+
+module_dependency module_dependencies[] = {
+    { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
+    {}
+};
+
+
+driver_module_info acpi_battery_driver_module = {
+    {
+        ACPI_BATTERY_MODULE_NAME,
+        0,
+        NULL
+    },
+
+    acpi_battery_support,
+    acpi_battery_register_device,
+    acpi_battery_init_driver,
+    acpi_battery_uninit_driver,
+    acpi_battery_register_child_devices,
+    NULL,    // rescan
+    NULL,    // removed
+};
+
+
+struct device_module_info acpi_battery_device_module = {
+    {
+        ACPI_BATTERY_DEVICE_MODULE_NAME,
+        0,
+        NULL
+    },
+
+    acpi_battery_init_device,
+    acpi_battery_uninit_device,
+    NULL,
+
+    acpi_battery_open,
+    acpi_battery_close,
+    acpi_battery_free,
+    acpi_battery_read,
+    acpi_battery_write,
+    NULL,
+    acpi_battery_control,
+
+    NULL,
+    NULL
+};
+
+module_info *modules[] = {
+    (module_info *)&acpi_battery_driver_module,
+    (module_info *)&acpi_battery_device_module,
+    NULL
+};
Index: src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.h
===================================================================
--- src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.h	(revisione 0)
+++ src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.h	(revisione 0)
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009 Francesco Piccinno <stack.box@gmail.com>
+ *
+ * Simple acpi_battery implementation for haiku ported from Linux.
+ *
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifndef _ACPI_BATTERY_H
+#define _ACPI_BATTERY_H
+
+#include <KernelExport.h>
+#include <ACPI.h>
+
+enum { /* ioctl op-codes */
+    drvOpGetBatteryState   = B_DEVICE_OP_CODES_END + 1001,
+    drvOpGetBatteryInfo    = B_DEVICE_OP_CODES_END + 1002,
+    drvOpGetBatteryPresent = B_DEVICE_OP_CODES_END + 1003,
+};
+
+typedef struct acpi_battery_type acpi_battery_type;
+
+/* Status (_STA) */
+struct acpi_device_status {
+    unsigned long present:1;
+    unsigned long enabled:1;
+    unsigned long show_in_ui:1;
+    unsigned long functional:1;
+    unsigned long battery_present:1;
+    unsigned long reserved:27;
+};
+
+struct acpi_battery_type {
+    struct acpi_device_status status;
+    int current_now;
+    int capacity_now;
+    int voltage_now;
+    int design_capacity;
+    int full_charge_capacity;
+    int technology;
+    int design_voltage;
+    int design_capacity_warning;
+    int design_capacity_low;
+    int capacity_granularity_1;
+    int capacity_granularity_2;
+    char model_number[32];
+    char serial_number[32];
+    char type[32];
+    char oem_info[32];
+    int state;
+    int power_unit;
+};
+
+struct acpi_offsets {
+    size_t offset;          /* offset inside struct acpi_sbs_battery */
+    uint8 mode;             /* int or string? */
+};
+
+static struct acpi_offsets state_offsets[] = {
+    {offsetof(struct acpi_battery_type, state), 0},
+    {offsetof(struct acpi_battery_type, current_now), 0},
+    {offsetof(struct acpi_battery_type, capacity_now), 0},
+    {offsetof(struct acpi_battery_type, voltage_now), 0},
+};
+
+static struct acpi_offsets info_offsets[] = {
+    {offsetof(struct acpi_battery_type, power_unit), 0},
+    {offsetof(struct acpi_battery_type, design_capacity), 0},
+    {offsetof(struct acpi_battery_type, full_charge_capacity), 0},
+    {offsetof(struct acpi_battery_type, technology), 0},
+    {offsetof(struct acpi_battery_type, design_voltage), 0},
+    {offsetof(struct acpi_battery_type, design_capacity_warning), 0},
+    {offsetof(struct acpi_battery_type, design_capacity_low), 0},
+    {offsetof(struct acpi_battery_type, capacity_granularity_1), 0},
+    {offsetof(struct acpi_battery_type, capacity_granularity_2), 0},
+    {offsetof(struct acpi_battery_type, model_number), 1},
+    {offsetof(struct acpi_battery_type, serial_number), 1},
+    {offsetof(struct acpi_battery_type, type), 1},
+    {offsetof(struct acpi_battery_type, oem_info), 1},
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
+
+#endif /* _ACPI_BATTERY_H */
Index: src/add-ons/kernel/drivers/power/Jamfile
===================================================================
--- src/add-ons/kernel/drivers/power/Jamfile	(revisione 31122)
+++ src/add-ons/kernel/drivers/power/Jamfile	(copia locale)
@@ -4,4 +4,5 @@
 SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_embedded_controller ;
 SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ;
 SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ;
+SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_battery ;
 SubInclude HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ;
