htc battery

 http://pastebin.com/YZqhLKQL

 

 

/* arch/arm/mach-msm/htc_battery.c
 *
 * Copyright (C) 2008 HTC Corporation.
 * Copyright (C) 2008 Google, Inc.
 *
 * 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 <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/power_supply.h>
#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/wakelock.h>
#include <asm/gpio.h>
#include <mach/msm_rpcrouter.h>
#include <mach/board.h>
#include <asm/mach-types.h>
#include <mach/board_htc.h>
 
static struct wake_lock vbus_wake_lock;
 
#define TRACE_BATT 0
 
#if TRACE_BATT
#include <linux/rtc.h>
 
#define BATT(x...) do { \
struct timespec ts; \
struct rtc_time tm; \
getnstimeofday(&ts); \
rtc_time_to_tm(ts.tv_sec, &tm); \
printk(KERN_INFO "[BATT] " x); \
printk(" at %lld (%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", \
ktime_to_ns(ktime_get()), tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); \
} while (0)
#else
#define BATT(x...) do {} while (0)
#endif
 
/* rpc related */
#define APP_BATT_PDEV_NAME              "rs30100001:00000000"
#define APP_BATT_PROG                   0x30100001
#define APP_BATT_VER                    MSM_RPC_VERS(0,0)
#define HTC_PROCEDURE_BATTERY_NULL      0
#define HTC_PROCEDURE_GET_BATT_LEVEL    1
#define HTC_PROCEDURE_GET_BATT_INFO     2
#define HTC_PROCEDURE_GET_CABLE_STATUS  3
#define HTC_PROCEDURE_SET_BATT_DELTA    4
 
/* module debugger */
#define HTC_BATTERY_DEBUG               1
#define BATTERY_PREVENTION              1
 
/* Enable this will shut down if no battery */
#define ENABLE_BATTERY_DETECTION        0
/* Sapphire pin changes:
 *  USB_ID (GPIO 90) is renamed to AC_IN (GPIO 30)
 *  CHARGER_EN (CPLD MISC2 bit[0]) is move to PMIC (MPP_14).
 *  ISET (CPLD MISC2 bit[1]) is move to PMIC (MPP_13). */
#define GPIO_SAPPHIRE_USB_ID    30
 
#define GPIO_BATTERY_DETECTION          21
#define GPIO_BATTERY_CHARGER_EN         128
 
/* Charge current selection */
#define GPIO_BATTERY_CHARGER_CURRENT    129
 
typedef enum {
        DISABLE = 0,
        ENABLE_SLOW_CHG,
        ENABLE_FAST_CHG
} batt_ctl_t;
 
/* This order is the same as htc_power_supplies[]
 * And it's also the same as htc_cable_status_update()
 */
typedef enum {
        CHARGER_BATTERY = 0,
        CHARGER_USB,
        CHARGER_AC
} charger_type_t;
 
const char *charger_tags[] = {"none", "USB", "AC"};
 
struct battery_info_reply {
        u32 batt_id;            /* Battery ID from ADC */
        u32 batt_vol;           /* Battery voltage from ADC */
        u32 batt_temp;          /* Battery Temperature (C) from formula and ADC */
        u32 batt_current;       /* Battery current from ADC */
        u32 level;              /* formula */
        u32 charging_source;    /* 0: no cable, 1:usb, 2:AC */
        u32 charging_enabled;   /* 0: Disable, 1: Enable */
        u32 full_bat;           /* Full capacity of battery (mAh) */
};
 
struct htc_battery_info {
        int present;
        unsigned long update_time;
 
        /* lock to protect the battery info */
        struct mutex lock;
 
        /* lock held while calling the arm9 to query the battery info */
        struct mutex rpc_lock;
        struct battery_info_reply rep;
};
 
static struct msm_rpc_endpoint *endpoint;
 
static struct htc_battery_info htc_batt_info;
 
static unsigned int cache_time = 1000;
 
static int htc_battery_initial = 0;
 
static enum power_supply_property htc_battery_properties[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_HEALTH,
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_TECHNOLOGY,
        POWER_SUPPLY_PROP_CAPACITY,
};
 
static enum power_supply_property htc_power_properties[] = {
        POWER_SUPPLY_PROP_ONLINE,
};
 
static char *supply_list[] = {
        "battery",
};
 
/* HTC dedicated attributes */
static ssize_t htc_battery_show_property(struct device *dev,
                                          struct device_attribute *attr,
                                          char *buf);
 
static int htc_power_get_property(struct power_supply *psy,
                                    enum power_supply_property psp,
                                    union power_supply_propval *val);
 
static int htc_battery_get_property(struct power_supply *psy,
                                    enum power_supply_property psp,
                                    union power_supply_propval *val);
 
static struct power_supply htc_power_supplies[] = {
        {
                .name = "battery",
                .type = POWER_SUPPLY_TYPE_BATTERY,
                .properties = htc_battery_properties,
                .num_properties = ARRAY_SIZE(htc_battery_properties),
                .get_property = htc_battery_get_property,
        },
        {
                .name = "usb",
                .type = POWER_SUPPLY_TYPE_USB,
                .supplied_to = supply_list,
                .num_supplicants = ARRAY_SIZE(supply_list),
                .properties = htc_power_properties,
                .num_properties = ARRAY_SIZE(htc_power_properties),
                .get_property = htc_power_get_property,
        },
        {
                .name = "ac",
                .type = POWER_SUPPLY_TYPE_MAINS,
                .supplied_to = supply_list,
                .num_supplicants = ARRAY_SIZE(supply_list),
                .properties = htc_power_properties,
                .num_properties = ARRAY_SIZE(htc_power_properties),
                .get_property = htc_power_get_property,
        },
};
 
static int g_usb_online;
 
/* -------------------------------------------------------------------------- */
 
#if defined(CONFIG_DEBUG_FS)
int htc_battery_set_charging(batt_ctl_t ctl);
static int batt_debug_set(void *data, u64 val)
{
        return htc_battery_set_charging((batt_ctl_t) val);
}
 
static int batt_debug_get(void *data, u64 *val)
{
        return -ENOSYS;
}
 
DEFINE_SIMPLE_ATTRIBUTE(batt_debug_fops, batt_debug_get, batt_debug_set, "%llu\n");
static int __init batt_debug_init(void)
{
        struct dentry *dent;
 
        dent = debugfs_create_dir("htc_battery", 0);
        if (IS_ERR(dent))
                return PTR_ERR(dent);
 
        debugfs_create_file("charger_state", 0644, dent, NULL, &batt_debug_fops);
 
        return 0;
}
 
device_initcall(batt_debug_init);
#endif
 
static int init_batt_gpio(void)
{
        if (!machine_is_trout())
                return 0;
 
        if (gpio_request(GPIO_BATTERY_DETECTION, "batt_detect") < 0)
                goto gpio_failed;
        if (gpio_request(GPIO_BATTERY_CHARGER_EN, "charger_en") < 0)
                goto gpio_failed;
        if (gpio_request(GPIO_BATTERY_CHARGER_CURRENT, "charge_current") < 0)
                goto gpio_failed;
 
        return 0;
 
gpio_failed:   
        return -EINVAL;
       
}
 
/*
 *      battery_charging_ctrl - battery charing control.
 *      @ctl:                   battery control command
 *
 */
static int battery_charging_ctrl(batt_ctl_t ctl)
{
        int result = 0;
 
        /* The charing operations are move to A9 in Sapphire. */
        if (!machine_is_trout())
                return result;
 
        switch (ctl) {
        case DISABLE:
                BATT("charger OFF");
                /* 0 for enable; 1 disable */
                result = gpio_direction_output(GPIO_BATTERY_CHARGER_EN, 1);
                break;
        case ENABLE_SLOW_CHG:
                BATT("charger ON (SLOW)");
                result = gpio_direction_output(GPIO_BATTERY_CHARGER_CURRENT, 0);
                result = gpio_direction_output(GPIO_BATTERY_CHARGER_EN, 0);
                break;
        case ENABLE_FAST_CHG:
                BATT("charger ON (FAST)");
                result = gpio_direction_output(GPIO_BATTERY_CHARGER_CURRENT, 1);
                result = gpio_direction_output(GPIO_BATTERY_CHARGER_EN, 0);
                break;
        default:
                printk(KERN_ERR "Not supported battery ctr called.!\n");
                result = -EINVAL;
                break;
        }
       
        return result;
}
 
int htc_battery_set_charging(batt_ctl_t ctl)
{
        int rc;
       
        if ((rc = battery_charging_ctrl(ctl)) < 0)
                goto result;
       
        if (!htc_battery_initial) {
                htc_batt_info.rep.charging_enabled = ctl & 0x3;
        } else {
                mutex_lock(&htc_batt_info.lock);
                htc_batt_info.rep.charging_enabled = ctl & 0x3;
                mutex_unlock(&htc_batt_info.lock);
        }
result:
        return rc;
}
 
int htc_battery_status_update(u32 curr_level)
{
        int notify;
        if (!htc_battery_initial)
                return 0;
 
        mutex_lock(&htc_batt_info.lock);
        notify = (htc_batt_info.rep.level != curr_level);
        htc_batt_info.rep.level = curr_level;
        mutex_unlock(&htc_batt_info.lock);
 
        if (notify)
                power_supply_changed(&htc_power_supplies[CHARGER_BATTERY]);
        return 0;
}
 
int htc_cable_status_update(int status)
{
        int rc = 0;
        unsigned last_source;
 
        if (!htc_battery_initial)
                return 0;
       
        if (status < CHARGER_BATTERY || status > CHARGER_AC) {
                BATT("%s: Not supported cable status received!", __func__);
                return -EINVAL;
        }
        mutex_lock(&htc_batt_info.lock);
        /* A9 reports USB charging when helf AC cable in and China AC charger. */
        /* Work arround: notify userspace AC charging first,
        and notify USB charging again when receiving usb connected notificaiton from usb driver. */
        last_source = htc_batt_info.rep.charging_source;
        if (status == CHARGER_USB && g_usb_online == 0)
                htc_batt_info.rep.charging_source = CHARGER_AC;
        else {
                htc_batt_info.rep.charging_source  = status;
                /* usb driver will not notify usb offline. */
                if (status == CHARGER_BATTERY && g_usb_online == 1)
                        g_usb_online = 0;
        }
 
        /* TODO: Don't call usb driver again with the same cable status. */
        msm_hsusb_set_vbus_state(status == CHARGER_USB);
 
        if (htc_batt_info.rep.charging_source != last_source) {
                if (htc_batt_info.rep.charging_source == CHARGER_USB ||
                        htc_batt_info.rep.charging_source == CHARGER_AC) {
                wake_lock(&vbus_wake_lock);
        } else {
                /* give userspace some time to see the uevent and update
                 * LED state or whatnot...
                 */
                wake_lock_timeout(&vbus_wake_lock, HZ / 2);
        }
                if (htc_batt_info.rep.charging_source == CHARGER_BATTERY || last_source == CHARGER_BATTERY)
        power_supply_changed(&htc_power_supplies[CHARGER_BATTERY]);
                if (htc_batt_info.rep.charging_source == CHARGER_USB || last_source == CHARGER_USB)
        power_supply_changed(&htc_power_supplies[CHARGER_USB]);
                if (htc_batt_info.rep.charging_source == CHARGER_AC || last_source == CHARGER_AC)
        power_supply_changed(&htc_power_supplies[CHARGER_AC]);
        }
        mutex_unlock(&htc_batt_info.lock);
 
        return rc;
}
 
/* A9 reports USB charging when helf AC cable in and China AC charger. */
/* Work arround: notify userspace AC charging first,
and notify USB charging again when receiving usb connected notification from usb driver. */
void notify_usb_connected(int online)
{
        mutex_lock(&htc_batt_info.lock);
 
        BATT("%s: online=%d, g_usb_online=%d", __func__, online, g_usb_online);
 
        if (g_usb_online != online) {
                g_usb_online = online;
                if (online && htc_batt_info.rep.charging_source == CHARGER_AC) {
                        mutex_unlock(&htc_batt_info.lock);
                        htc_cable_status_update(CHARGER_USB);
                        mutex_lock(&htc_batt_info.lock);
                } else if (online) {
                        BATT("warning: usb connected but charging source=%d", htc_batt_info.rep.charging_source);
                }
        }
        mutex_unlock(&htc_batt_info.lock);
}
 
static int htc_get_batt_info(struct battery_info_reply *buffer)
{
        struct rpc_request_hdr req;
       
        struct htc_get_batt_info_rep {
                struct rpc_reply_hdr hdr;
                struct battery_info_reply info;
        } rep;
       
        int rc;
 
        if (buffer == NULL)
                return -EINVAL;
 
        rc = msm_rpc_call_reply(endpoint, HTC_PROCEDURE_GET_BATT_INFO,
                                &req, sizeof(req),
                                &rep, sizeof(rep),
                                5 * HZ);
        if ( rc < 0 )
                return rc;
       
        mutex_lock(&htc_batt_info.lock);
        buffer->batt_id                 = be32_to_cpu(rep.info.batt_id);
        buffer->batt_vol                = be32_to_cpu(rep.info.batt_vol);
        buffer->batt_temp               = be32_to_cpu(rep.info.batt_temp);
        buffer->batt_current            = be32_to_cpu(rep.info.batt_current);
        buffer->level                   = be32_to_cpu(rep.info.level);
        /* Move the rules of charging_source to cable_status_update. */
        /* buffer->charging_source      = be32_to_cpu(rep.info.charging_source); */
        buffer->charging_enabled        = be32_to_cpu(rep.info.charging_enabled);
        buffer->full_bat                = be32_to_cpu(rep.info.full_bat);
        mutex_unlock(&htc_batt_info.lock);
 
        return 0;
}
 
/* -------------------------------------------------------------------------- */
static int htc_power_get_property(struct power_supply *psy,
                                    enum power_supply_property psp,
                                    union power_supply_propval *val)
{
        charger_type_t charger;
       
        mutex_lock(&htc_batt_info.lock);
        charger = htc_batt_info.rep.charging_source;
        mutex_unlock(&htc_batt_info.lock);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
                if (psy->type == POWER_SUPPLY_TYPE_MAINS)
                        val->intval = (charger ==  CHARGER_AC ? 1 : 0);
                else if (psy->type == POWER_SUPPLY_TYPE_USB)
                        val->intval = (charger ==  CHARGER_USB ? 1 : 0);
                else
                        val->intval = 0;
                break;
        default:
                return -EINVAL;
        }
       
        return 0;
}
 
static int htc_battery_get_charging_status(void)
{
        u32 level;
        charger_type_t charger;
        int ret;
       
        mutex_lock(&htc_batt_info.lock);
        charger = htc_batt_info.rep.charging_source;
       
        switch (charger) {
        case CHARGER_BATTERY:
                ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
                break;
        case CHARGER_USB:
        case CHARGER_AC:
                level = htc_batt_info.rep.level;
                if (level == 100)
                        ret = POWER_SUPPLY_STATUS_FULL;
                else
                        ret = POWER_SUPPLY_STATUS_CHARGING;
                break;
        default:
                ret = POWER_SUPPLY_STATUS_UNKNOWN;
        }
        mutex_unlock(&htc_batt_info.lock);
        return ret;
}
 
static int htc_battery_get_property(struct power_supply *psy,
                                    enum power_supply_property psp,
                                    union power_supply_propval *val)
{
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                val->intval = htc_battery_get_charging_status();
                break;
        case POWER_SUPPLY_PROP_HEALTH:
                val->intval = POWER_SUPPLY_HEALTH_GOOD;
                break;
        case POWER_SUPPLY_PROP_PRESENT:
                val->intval = htc_batt_info.present;
                break;
        case POWER_SUPPLY_PROP_TECHNOLOGY:
                val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                mutex_lock(&htc_batt_info.lock);
                val->intval = htc_batt_info.rep.level;
                mutex_unlock(&htc_batt_info.lock);
                break;
        default:               
                return -EINVAL;
        }
       
        return 0;
}
 
#define HTC_BATTERY_ATTR(_name)                                                 \
{                                                                               \
        .attr = { .name = #_name, .mode = S_IRUGO, .owner = THIS_MODULE },      \
        .show = htc_battery_show_property,                                      \
        .store = NULL,                                                          \
}
 
static struct device_attribute htc_battery_attrs[] = {
        HTC_BATTERY_ATTR(batt_id),
        HTC_BATTERY_ATTR(batt_vol),
        HTC_BATTERY_ATTR(batt_temp),
        HTC_BATTERY_ATTR(batt_current),
        HTC_BATTERY_ATTR(charging_source),
        HTC_BATTERY_ATTR(charging_enabled),
        HTC_BATTERY_ATTR(full_bat),
};
 
enum {
        BATT_ID = 0,
        BATT_VOL,
        BATT_TEMP,
        BATT_CURRENT,
        CHARGING_SOURCE,
        CHARGING_ENABLED,
        FULL_BAT,
};
 
static int htc_rpc_set_delta(unsigned delta)
{
        struct set_batt_delta_req {
                struct rpc_request_hdr hdr;
                uint32_t data;
        } req;
 
        req.data = cpu_to_be32(delta);
        return msm_rpc_call(endpoint, HTC_PROCEDURE_SET_BATT_DELTA,
                            &req, sizeof(req), 5 * HZ);
}
 
 
static ssize_t htc_battery_set_delta(struct device *dev,
                                     struct device_attribute *attr,
                                     const char *buf, size_t count)
{
        int rc;
        unsigned long delta = 0;
       
        delta = simple_strtoul(buf, NULL, 10);
 
        if (delta > 100)
                return -EINVAL;
 
        mutex_lock(&htc_batt_info.rpc_lock);
        rc = htc_rpc_set_delta(delta);
        mutex_unlock(&htc_batt_info.rpc_lock);
        if (rc < 0)
                return rc;
        return count;
}
 
static struct device_attribute htc_set_delta_attrs[] = {
        __ATTR(delta, S_IWUSR | S_IWGRP, NULL, htc_battery_set_delta),
};
 
static int htc_battery_create_attrs(struct device * dev)
{
        int i, j, rc;
       
        for (i = 0; i < ARRAY_SIZE(htc_battery_attrs); i++) {
                rc = device_create_file(dev, &htc_battery_attrs[i]);
                if (rc)
                        goto htc_attrs_failed;
        }
 
        for (j = 0; j < ARRAY_SIZE(htc_set_delta_attrs); j++) {
                rc = device_create_file(dev, &htc_set_delta_attrs[j]);
                if (rc)
                        goto htc_delta_attrs_failed;
        }
       
        goto succeed;
       
htc_attrs_failed:
        while (i--)
                device_remove_file(dev, &htc_battery_attrs[i]);
htc_delta_attrs_failed:
        while (j--)
                device_remove_file(dev, &htc_set_delta_attrs[i]);
succeed:       
        return rc;
}
 
static ssize_t htc_battery_show_property(struct device *dev,
                                         struct device_attribute *attr,
                                         char *buf)
{
        int i = 0;
        const ptrdiff_t off = attr - htc_battery_attrs;
       
        /* rpc lock is used to prevent two threads from calling
         * into the get info rpc at the same time
         */
 
        mutex_lock(&htc_batt_info.rpc_lock);
        /* check cache time to decide if we need to update */
        if (htc_batt_info.update_time &&
            time_before(jiffies, htc_batt_info.update_time +
                                msecs_to_jiffies(cache_time)))
                goto dont_need_update;
       
        if (htc_get_batt_info(&htc_batt_info.rep) < 0) {
                printk(KERN_ERR "%s: rpc failed!!!\n", __FUNCTION__);
        } else {
                htc_batt_info.update_time = jiffies;
        }
dont_need_update:
        mutex_unlock(&htc_batt_info.rpc_lock);
 
        mutex_lock(&htc_batt_info.lock);
        switch (off) {
        case BATT_ID:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.batt_id);
                break;
        case BATT_VOL:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.batt_vol);
                break;
        case BATT_TEMP:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.batt_temp);
                break;
        case BATT_CURRENT:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.batt_current);
                break;
        case CHARGING_SOURCE:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.charging_source);
                break;
        case CHARGING_ENABLED:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.charging_enabled);
                break;         
        case FULL_BAT:
                i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
                               htc_batt_info.rep.full_bat);
                break;
        default:
                i = -EINVAL;
        }      
        mutex_unlock(&htc_batt_info.lock);
       
        return i;
}
 
static int htc_battery_probe(struct platform_device *pdev)
{
        int i, rc;
 
        /* init battery gpio */
        if ((rc = init_batt_gpio()) < 0) {
                printk(KERN_ERR "%s: init battery gpio failed!\n", __FUNCTION__);
                return rc;
        }
 
        /* init structure data member */
        htc_batt_info.update_time       = jiffies;
        /* A9 will shutdown the phone if battery is pluged out, so this value is always 1.
        htc_batt_info.present           = gpio_get_value(GPIO_TROUT_MBAT_IN);
        */
        htc_batt_info.present           = 1;
 
        /* init rpc */
        endpoint = msm_rpc_connect(APP_BATT_PROG, APP_BATT_VER, 0);
        if (IS_ERR(endpoint)) {
                printk(KERN_ERR "%s: init rpc failed! rc = %ld\n",
                       __FUNCTION__, PTR_ERR(endpoint));
                return rc;
        }
 
        /* init power supplier framework */
        for (i = 0; i < ARRAY_SIZE(htc_power_supplies); i++) {
                rc = power_supply_register(&pdev->dev, &htc_power_supplies[i]);
                if (rc)
                        printk(KERN_ERR "Failed to register power supply (%d)\n", rc); 
        }
 
        /* create htc detail attributes */
        htc_battery_create_attrs(htc_power_supplies[CHARGER_BATTERY].dev);
 
        /* After battery driver gets initialized, send rpc request to inquiry
         * the battery status in case of we lost some info
         */
        htc_battery_initial = 1;
 
        mutex_lock(&htc_batt_info.rpc_lock);
        htc_batt_info.rep.charging_source = CHARGER_BATTERY;
        if (htc_get_batt_info(&htc_batt_info.rep) < 0)
                printk(KERN_ERR "%s: get info failed\n", __FUNCTION__);
 
        if (htc_rpc_set_delta(1) < 0)
                printk(KERN_ERR "%s: set delta failed\n", __FUNCTION__);
        htc_batt_info.update_time = jiffies;
        mutex_unlock(&htc_batt_info.rpc_lock);
 
        return 0;
}
 
static struct platform_driver htc_battery_driver = {
        .probe  = htc_battery_probe,
        .driver = {
                .name   = APP_BATT_PDEV_NAME,
                .owner  = THIS_MODULE,
        },
};
 
/* batt_mtoa server definitions */
#define BATT_MTOA_PROG                          0x30100000
#define BATT_MTOA_VERS                          0
#define RPC_BATT_MTOA_NULL                      0
#define RPC_BATT_MTOA_SET_CHARGING_PROC         1
#define RPC_BATT_MTOA_CABLE_STATUS_UPDATE_PROC  2
#define RPC_BATT_MTOA_LEVEL_UPDATE_PROC         3
 
struct rpc_batt_mtoa_set_charging_args {
        int enable;
};
 
struct rpc_batt_mtoa_cable_status_update_args {
        int status;
};
 
struct rpc_dem_battery_update_args {
        uint32_t level;
};
 
static int handle_battery_call(struct msm_rpc_server *server,
                               struct rpc_request_hdr *req, unsigned len)
{      
        switch (req->procedure) {
        case RPC_BATT_MTOA_NULL:
                return 0;
 
        case RPC_BATT_MTOA_SET_CHARGING_PROC: {
                struct rpc_batt_mtoa_set_charging_args *args;
                args = (struct rpc_batt_mtoa_set_charging_args *)(req + 1);
                args->enable = be32_to_cpu(args->enable);
                BATT("set_charging: enable=%d",args->enable);
                htc_battery_set_charging(args->enable);
                return 0;
        }
        case RPC_BATT_MTOA_CABLE_STATUS_UPDATE_PROC: {
                struct rpc_batt_mtoa_cable_status_update_args *args;
                args = (struct rpc_batt_mtoa_cable_status_update_args *)(req + 1);
                args->status = be32_to_cpu(args->status);
                BATT("cable_status_update: status=%d",args->status);
                htc_cable_status_update(args->status);
                return 0;
        }
        case RPC_BATT_MTOA_LEVEL_UPDATE_PROC: {
                struct rpc_dem_battery_update_args *args;
                args = (struct rpc_dem_battery_update_args *)(req + 1);
                args->level = be32_to_cpu(args->level);
                BATT("dem_battery_update: level=%d",args->level);
                htc_battery_status_update(args->level);
                return 0;
        }
        default:
                printk(KERN_ERR "%s: program 0x%08x:%d: unknown procedure %d\n",
                       __FUNCTION__, req->prog, req->vers, req->procedure);
                return -ENODEV;
        }
}
 
static struct msm_rpc_server battery_server = {
        .prog = BATT_MTOA_PROG,
        .vers = BATT_MTOA_VERS,
        .rpc_call = handle_battery_call,
};
 
static int __init htc_battery_init(void)
{
        wake_lock_init(&vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present");
        mutex_init(&htc_batt_info.lock);
        mutex_init(&htc_batt_info.rpc_lock);
        msm_rpc_create_server(&battery_server);
        platform_driver_register(&htc_battery_driver);
        return 0;
}
 
module_init(htc_battery_init);
MODULE_DESCRIPTION("HTC Battery Driver");
MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值