您的位置:首页 > 移动开发 > Android开发

[RK3288][Android6.0] 调试笔记 --- 伪电池驱动添加

2016-12-21 15:11 681 查看
Platform: ROCKCHIP

OS: Android 6.0

Kernel: 3.10.92

由于电池部分是用户空间Service从另外一颗MCU获取,而Android需要显示电量,

所以按照电池驱动框架做了一个伪电池驱动, 主要是使用它的充电状态和电池电量

这两个property, 代码如下:

/* drivers/power/rk3288_battery.c

 *

 * Power supply driver for the rk3288

 *

 * Copyright (C) 2008 Google, Inc.

 * Author: kris.fei<kris_fei@126.com>

 *

 * 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/module.h>

#include <linux/err.h>

#include <linux/platform_device.h>

#include <linux/power_supply.h>

#include <linux/types.h>

#include <linux/pci.h>

#include <linux/interrupt.h>

#include <asm/io.h>

#include <linux/timer.h>

#include <linux/slab.h>

#include <linux/of_irq.h>

#include <linux/of_gpio.h>

#include <linux/of.h>

#include <linux/of_device.h>

//#define DEBUG

struct rk3288_battery_data {

    int status;

    int health;

    int present;

    int capacity;

    struct power_supply battery;

};

static struct rk3288_battery_data *battery_data;

static enum power_supply_property rk3288_battery_props[] = {

    POWER_SUPPLY_PROP_STATUS,

    POWER_SUPPLY_PROP_HEALTH,

    POWER_SUPPLY_PROP_PRESENT,

    POWER_SUPPLY_PROP_TECHNOLOGY,

    POWER_SUPPLY_PROP_CAPACITY,

};

static int rk3288_battery_get_property(struct power_supply *psy,

                 enum power_supply_property psp,

                 union power_supply_propval *val)

{

    struct rk3288_battery_data *data = container_of(psy,

        struct rk3288_battery_data, battery);

    int ret = 0;

#ifdef DEBUG

    printk("%s : property: %d \n", __func__, psp);

#endif

    switch (psp) {

    case POWER_SUPPLY_PROP_STATUS:

        val->intval = data->status;

        break;

    case POWER_SUPPLY_PROP_HEALTH:

        val->intval = data->health ;

        break;

    case POWER_SUPPLY_PROP_PRESENT:

        val->intval = data->present ;

        break;

    case POWER_SUPPLY_PROP_TECHNOLOGY:

        val->intval = POWER_SUPPLY_TECHNOLOGY_LION;

        break;

    case POWER_SUPPLY_PROP_CAPACITY:

        val->intval = data->capacity ;

        break;

    default:

        ret = -EINVAL;

        break;

    }

    return ret;

}

static int rk3288_battery_set_property(struct power_supply *psy,

            enum power_supply_property psp,

            const union power_supply_propval *val)

{

    struct rk3288_battery_data *data = container_of(psy,

        struct rk3288_battery_data, battery);

    int ret = 0;

    int value = val->intval;

#ifdef DEBUG

    printk("%s :psp:%d val:%d\n", __func__, psp, value);

#endif

    switch (psp) {

    case POWER_SUPPLY_PROP_STATUS:

        if (value <= POWER_SUPPLY_STATUS_FULL) {

            data->status =value;

        } else {

            printk("Unreasonable value:%d\n", value);

            ret = 1;

        }

        break;

    case POWER_SUPPLY_PROP_HEALTH:

        if (value <= POWER_SUPPLY_HEALTH_COLD) {

            data->health = value;

        } else {

            printk("Unreasonable value:%d\n", value);

            ret = 1;

        }

        break;

    case POWER_SUPPLY_PROP_PRESENT:

        data->present = value;

        break;

    case POWER_SUPPLY_PROP_CAPACITY:

        //Capacity from 0 to 100.

        if (value > 0 && value <= 100) {

            data->capacity = value;

        } else {

            printk("Unreasonable value:%d\n", value);

            ret = 1;

        }

        break;

    default:

        ret = -EINVAL;

        break;

    }

    //Send uevent.

    power_supply_changed(&battery_data->battery);

    return ret;

}

static int rk3288_battery_is_writeable(struct power_supply *psy,

                 enum power_supply_property psp)

{

    switch (psp) {

    //Need to be written from medusa service.

    case POWER_SUPPLY_PROP_CAPACITY:

    case POWER_SUPPLY_PROP_STATUS:

    case POWER_SUPPLY_PROP_PRESENT:

    case POWER_SUPPLY_PROP_HEALTH:

        return 1;

    default:

        break;

    }

    return 0;

}

static int rk3288_battery_probe(struct platform_device *pdev)

{

    int ret;

    struct rk3288_battery_data *data;

    data = kzalloc(sizeof(*data), GFP_KERNEL);

    if (data == NULL) {

        ret = -ENOMEM;

        goto err_data_alloc_failed;

    }

    data->battery.properties = rk3288_battery_props;

    data->battery.num_properties = ARRAY_SIZE(rk3288_battery_props);

    data->battery.get_property = rk3288_battery_get_property;

    data->battery.name = "battery";

    data->battery.type = POWER_SUPPLY_TYPE_BATTERY;

    data->battery.set_property = rk3288_battery_set_property;

    data->battery.property_is_writeable = rk3288_battery_is_writeable;

    data->present = 1;    //Present

    data->status = POWER_SUPPLY_STATUS_UNKNOWN;

    data->health = POWER_SUPPLY_HEALTH_GOOD;

    data ->capacity = 1;

    ret = power_supply_register(&pdev->dev, &data->battery);

    if (ret)

        goto err_battery_failed;

    platform_set_drvdata(pdev, data);

    battery_data = data;

    return 0;

err_battery_failed:

    kfree(data);

err_data_alloc_failed:

    return ret;

}

static int rk3288_battery_remove(struct platform_device *pdev)

{

    struct rk3288_battery_data *data = platform_get_drvdata(pdev);

    power_supply_unregister(&data->battery);

    kfree(data);

    battery_data = NULL;

    return 0;

}

static const struct of_device_id rk3288_battery[] = {

    { .compatible = "rk3288,battery" },

    { /* Sentinel */ }

};

static struct platform_driver rk3288_battery_driver = {

    .probe        = rk3288_battery_probe,

    .remove        = rk3288_battery_remove,

    .driver = {

        .owner = THIS_MODULE,

        .name = "rk3288-battery",

        .of_match_table = of_match_ptr(rk3288_battery),

    }

};

static int __init rk3288_battery_init(void)

{

    return platform_driver_register(&rk3288_battery_driver);

}

static void __exit rk3288_battery_exit(void)

{

    platform_driver_unregister(&rk3288_battery_driver);

}

module_init(rk3288_battery_init);

module_exit(rk3288_battery_exit);

MODULE_AUTHOR("kris.fei");

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Battery driver");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: