android: Add goldfish_battery virtual device.
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 979e532..6db7837 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -28,6 +28,7 @@
 obj-$(CONFIG_NSERIES) += cbus.o
 obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
+obj-$(CONFIG_GOLDFISH) += goldfish_battery.o
 obj-$(CONFIG_IMX) += imx_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
diff --git a/hw/misc/goldfish_battery.c b/hw/misc/goldfish_battery.c
new file mode 100644
index 0000000..2bf9fbd
--- /dev/null
+++ b/hw/misc/goldfish_battery.c
@@ -0,0 +1,345 @@
+/* Copyright (C) 2007-2015 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "qemu/error-report.h"
+#include "monitor/monitor.h"
+#include "hw/misc/goldfish_battery.h"
+
+#include <assert.h>
+
+enum {
+	/* status register */
+	BATTERY_INT_STATUS	    = 0x00,
+	/* set this to enable IRQ */
+	BATTERY_INT_ENABLE	    = 0x04,
+
+	BATTERY_AC_ONLINE       = 0x08,
+	BATTERY_STATUS          = 0x0C,
+	BATTERY_HEALTH          = 0x10,
+	BATTERY_PRESENT         = 0x14,
+	BATTERY_CAPACITY        = 0x18,
+
+	BATTERY_STATUS_CHANGED	= 1U << 0,
+	AC_STATUS_CHANGED   	= 1U << 1,
+	BATTERY_INT_MASK        = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED,
+};
+
+#define TYPE_GOLDFISH_BATTERY "goldfish_battery"
+#define GOLDFISH_BATTERY(obj) OBJECT_CHECK(struct goldfish_battery_state, (obj), TYPE_GOLDFISH_BATTERY)
+
+struct goldfish_battery_state {
+    SysBusDevice parent;
+
+    MemoryRegion iomem;
+    qemu_irq irq;
+
+    // IRQs
+    uint32_t int_status;
+    // irq enable mask for int_status
+    uint32_t int_enable;
+
+    uint32_t ac_online;
+    uint32_t status;
+    uint32_t health;
+    uint32_t present;
+    uint32_t capacity;
+    uint32_t hw_has_battery;
+};
+
+/* update this each time you update the battery_state struct */
+#define  BATTERY_STATE_SAVE_VERSION  1
+
+static const VMStateDescription goldfish_battery_vmsd = {
+    .name = "goldfish_battery",
+    .version_id = BATTERY_STATE_SAVE_VERSION,
+    .minimum_version_id = BATTERY_STATE_SAVE_VERSION,
+    .minimum_version_id_old = BATTERY_STATE_SAVE_VERSION,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(int_status, struct goldfish_battery_state),
+        VMSTATE_UINT32(int_enable, struct goldfish_battery_state),
+        VMSTATE_UINT32(ac_online, struct goldfish_battery_state),
+        VMSTATE_UINT32(status, struct goldfish_battery_state),
+        VMSTATE_UINT32(health, struct goldfish_battery_state),
+        VMSTATE_UINT32(present, struct goldfish_battery_state),
+        VMSTATE_UINT32(capacity, struct goldfish_battery_state),
+        VMSTATE_UINT32(hw_has_battery, struct goldfish_battery_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void goldfish_battery_display_cb(void* opaque, BatteryLineCallback callback)
+{
+    DeviceState *dev = qdev_find_recursive(sysbus_get_default(),
+                                           TYPE_GOLDFISH_BATTERY);
+    struct goldfish_battery_state *s = GOLDFISH_BATTERY(dev);
+    const char *value;
+    int size;
+    char buf[128] = {0};
+
+    size = snprintf(buf, sizeof(buf) - 1,
+                    "AC: %s\n", (s->ac_online) ? "online" : "offline");
+    assert(size > 0);
+    callback(opaque, buf, size);
+
+    switch (s->status) {
+    case POWER_SUPPLY_STATUS_CHARGING:
+        value = "Charging";
+        break;
+    case POWER_SUPPLY_STATUS_DISCHARGING:
+        value = "Discharging";
+        break;
+    case POWER_SUPPLY_STATUS_NOT_CHARGING:
+        value = "Not charging";
+        break;
+    case POWER_SUPPLY_STATUS_FULL:
+        value = "Full";
+        break;
+    default:
+        value = "Unknown";
+    }
+
+    size = snprintf(buf, sizeof(buf) - 1, "status: %s\n", value);
+    assert(size > 0);
+    callback(opaque, buf, size);
+
+    switch (s->health) {
+    case POWER_SUPPLY_HEALTH_GOOD:
+        value = "Good";
+        break;
+    case POWER_SUPPLY_HEALTH_OVERHEAT:
+        value = "Overheat";
+        break;
+    case POWER_SUPPLY_HEALTH_DEAD:
+        value = "Dead";
+        break;
+    case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
+        value = "Overvoltage";
+        break;
+    case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
+        value = "Unspecified failure";
+        break;
+    default:
+        value = "Unknown";
+    }
+    size = snprintf(buf, sizeof(buf) - 1, "health: %s\n", value);
+    assert(size > 0);
+    callback(opaque, buf, size);
+
+    size = snprintf(buf, sizeof(buf) - 1,
+                    "present: %s\n", (s->present) ? "true" : "false");
+    assert(size > 0);
+    callback(opaque, buf, size);
+
+    size = snprintf(buf, sizeof(buf) - 1, "capacity: %d\n", s->capacity);
+    assert(size > 0);
+    callback(opaque, buf, size);
+}
+
+static void monitor_print_callback(void* opaque, const char* buf, int size)
+{
+    Monitor* mon = (Monitor*)opaque;
+    monitor_printf(mon, buf);
+}
+
+void goldfish_battery_display(Monitor *mon)
+{
+    goldfish_battery_display_cb(mon, &monitor_print_callback);
+}
+
+int goldfish_battery_read_prop(int property)
+{
+    int retVal = 0;
+
+    DeviceState *dev = qdev_find_recursive(sysbus_get_default(),
+                                           TYPE_GOLDFISH_BATTERY);
+    struct goldfish_battery_state *battery_state = GOLDFISH_BATTERY(dev);
+
+    if (!battery_state || !battery_state->hw_has_battery) {
+        return 0;
+    }
+
+    switch (property) {
+        case POWER_SUPPLY_PROP_ONLINE:
+            retVal = battery_state->ac_online;
+            break;
+        case POWER_SUPPLY_PROP_STATUS:
+            retVal = battery_state->status;
+            break;
+        case POWER_SUPPLY_PROP_HEALTH:
+            retVal = battery_state->health;
+            break;
+        case POWER_SUPPLY_PROP_PRESENT:
+            retVal = battery_state->present;
+            break;
+        case POWER_SUPPLY_PROP_CAPACITY:
+            retVal = battery_state->capacity;
+            break;
+        default:
+            retVal = 0;
+            break;
+    }
+    return retVal;
+}
+
+void goldfish_battery_set_prop(int ac, int property, int value)
+{
+    DeviceState *dev = qdev_find_recursive(sysbus_get_default(),
+                                           TYPE_GOLDFISH_BATTERY);
+    struct goldfish_battery_state *battery_state = GOLDFISH_BATTERY(dev);
+    int new_status = (ac ? AC_STATUS_CHANGED : BATTERY_STATUS_CHANGED);
+
+    if (!battery_state || !battery_state->hw_has_battery) {
+        return;
+    }
+
+    if (ac) {
+        switch (property) {
+        case POWER_SUPPLY_PROP_ONLINE:
+            battery_state->ac_online = value;
+            break;
+        }
+    } else {
+        switch (property) {
+        case POWER_SUPPLY_PROP_STATUS:
+            battery_state->status = value;
+            break;
+        case POWER_SUPPLY_PROP_HEALTH:
+            battery_state->health = value;
+            break;
+        case POWER_SUPPLY_PROP_PRESENT:
+            battery_state->present = value;
+            break;
+        case POWER_SUPPLY_PROP_CAPACITY:
+            battery_state->capacity = value;
+            break;
+        }
+    }
+
+    if (new_status != battery_state->int_status) {
+        battery_state->int_status |= new_status;
+        qemu_set_irq(battery_state->irq,
+                     (battery_state->int_status &
+                     battery_state->int_enable));
+    }
+}
+
+static uint64_t goldfish_battery_read(void *opaque, hwaddr offset, unsigned size)
+{
+    uint64_t ret;
+    struct goldfish_battery_state *s = opaque;
+
+    switch(offset) {
+        case BATTERY_INT_STATUS:
+            // return current buffer status flags
+            ret = s->int_status & s->int_enable;
+            if (ret) {
+                qemu_irq_lower(s->irq);
+                s->int_status = 0;
+            }
+            return ret;
+
+		case BATTERY_INT_ENABLE:
+		    return s->int_enable;
+		case BATTERY_AC_ONLINE:
+		    return s->ac_online;
+		case BATTERY_STATUS:
+		    return s->status;
+		case BATTERY_HEALTH:
+		    return s->health;
+		case BATTERY_PRESENT:
+		    return s->present;
+		case BATTERY_CAPACITY:
+		    return s->capacity;
+
+        default:
+            error_report ("goldfish_battery_read: Bad offset " TARGET_FMT_plx,
+                    offset);
+            return 0;
+    }
+}
+
+static void goldfish_battery_write(void *opaque, hwaddr offset, uint64_t val,
+        unsigned size)
+{
+    struct goldfish_battery_state *s = opaque;
+
+    switch(offset) {
+        case BATTERY_INT_ENABLE:
+            /* enable interrupts */
+            s->int_enable = val;
+            break;
+
+        default:
+            error_report("goldfish_battery_write: Bad offset " TARGET_FMT_plx,
+                    offset);
+    }
+}
+
+static const MemoryRegionOps goldfish_battery_iomem_ops = {
+    .read = goldfish_battery_read,
+    .write = goldfish_battery_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+};
+
+static void goldfish_battery_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
+    struct goldfish_battery_state *s = GOLDFISH_BATTERY(dev);
+
+    /* Initialize the device ID so the battery can be looked up during monitor
+     * commands.
+     */
+    dev->id = g_strdup("goldfish_battery");
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &goldfish_battery_iomem_ops, s,
+            "goldfish_battery", 0x1000);
+    sysbus_init_mmio(sbdev, &s->iomem);
+    sysbus_init_irq(sbdev, &s->irq);
+
+    // default values for the battery
+    s->ac_online = 1;
+    /* TODO: The Android Emulator gets this attribute from the AVD
+     *       hw-config-defs.h.  For now we hard-code the value to match the
+     *       other values.
+     */
+    s->hw_has_battery = 1;
+    s->status = POWER_SUPPLY_STATUS_CHARGING;
+    s->health = POWER_SUPPLY_HEALTH_GOOD;
+    s->present = 1;     // battery is present
+    s->capacity = 50;   // 50% charged
+}
+
+static void goldfish_battery_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = goldfish_battery_realize;
+    dc->vmsd = &goldfish_battery_vmsd;
+    dc->desc = "goldfish battery";
+}
+
+static const TypeInfo goldfish_battery_info = {
+    .name          = TYPE_GOLDFISH_BATTERY,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(struct goldfish_battery_state),
+    .class_init    = goldfish_battery_class_init,
+};
+
+static void goldfish_battery_register(void)
+{
+    type_register_static(&goldfish_battery_info);
+}
+
+type_init(goldfish_battery_register);
diff --git a/include/hw/misc/goldfish_battery.h b/include/hw/misc/goldfish_battery.h
new file mode 100644
index 0000000..71a034d
--- /dev/null
+++ b/include/hw/misc/goldfish_battery.h
@@ -0,0 +1,79 @@
+/* Copyright (C) 2007-2015 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#ifndef _HW_GOLDFISH_BATTERY_H
+#define _HW_GOLDFISH_BATTERY_H
+
+enum {
+    POWER_SUPPLY_STATUS_UNKNOWN = 0,
+    POWER_SUPPLY_STATUS_CHARGING,
+    POWER_SUPPLY_STATUS_DISCHARGING,
+    POWER_SUPPLY_STATUS_NOT_CHARGING,
+    POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+    POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+    POWER_SUPPLY_HEALTH_GOOD,
+    POWER_SUPPLY_HEALTH_OVERHEAT,
+    POWER_SUPPLY_HEALTH_DEAD,
+    POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+    POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+
+enum power_supply_property {
+    /* Properties of type `int' */
+    POWER_SUPPLY_PROP_STATUS = 0,
+    POWER_SUPPLY_PROP_HEALTH,
+    POWER_SUPPLY_PROP_PRESENT,
+    POWER_SUPPLY_PROP_ONLINE,
+    POWER_SUPPLY_PROP_TECHNOLOGY,
+    POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+    POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+    POWER_SUPPLY_PROP_VOLTAGE_NOW,
+    POWER_SUPPLY_PROP_VOLTAGE_AVG,
+    POWER_SUPPLY_PROP_CURRENT_NOW,
+    POWER_SUPPLY_PROP_CURRENT_AVG,
+    POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+    POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+    POWER_SUPPLY_PROP_CHARGE_FULL,
+    POWER_SUPPLY_PROP_CHARGE_EMPTY,
+    POWER_SUPPLY_PROP_CHARGE_NOW,
+    POWER_SUPPLY_PROP_CHARGE_AVG,
+    POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+    POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+    POWER_SUPPLY_PROP_ENERGY_FULL,
+    POWER_SUPPLY_PROP_ENERGY_EMPTY,
+    POWER_SUPPLY_PROP_ENERGY_NOW,
+    POWER_SUPPLY_PROP_ENERGY_AVG,
+    POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+    POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+    POWER_SUPPLY_PROP_TEMP,
+    POWER_SUPPLY_PROP_TEMP_AMBIENT,
+    POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+    POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+    POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+    POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+    /* Properties of type `const char *' */
+    POWER_SUPPLY_PROP_MODEL_NAME,
+    POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+extern void goldfish_battery_display(Monitor *mon);
+
+typedef void (*BatteryLineCallback)(void* opaque, const char* line, int len);
+extern void goldfish_battery_display_cb(void* opaque,
+                                        BatteryLineCallback callback);
+int  goldfish_battery_read_prop(int property);
+void goldfish_battery_set_prop(int ac, int property, int value);
+
+#endif /* _HW_GOLDFISH_BATTERY_H */