linux/drivers/power/test_power.c
<<
>>
Prefs
   1/*
   2 * Power supply driver for testing.
   3 *
   4 * Copyright 2010  Anton Vorontsov <cbouatmailru@gmail.com>
   5 *
   6 * Dynamic module parameter code from the Virtual Battery Driver
   7 * Copyright (C) 2008 Pylone, Inc.
   8 * By: Masashi YOKOTA <yokota@pylone.jp>
   9 * Originally found here:
  10 * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/power_supply.h>
  20#include <linux/errno.h>
  21#include <linux/delay.h>
  22#include <linux/vermagic.h>
  23
  24static int ac_online                    = 1;
  25static int usb_online                   = 1;
  26static int battery_status               = POWER_SUPPLY_STATUS_DISCHARGING;
  27static int battery_health               = POWER_SUPPLY_HEALTH_GOOD;
  28static int battery_present              = 1; /* true */
  29static int battery_technology           = POWER_SUPPLY_TECHNOLOGY_LION;
  30static int battery_capacity             = 50;
  31static int battery_voltage              = 3300;
  32
  33static int test_power_get_ac_property(struct power_supply *psy,
  34                                      enum power_supply_property psp,
  35                                      union power_supply_propval *val)
  36{
  37        switch (psp) {
  38        case POWER_SUPPLY_PROP_ONLINE:
  39                val->intval = ac_online;
  40                break;
  41        default:
  42                return -EINVAL;
  43        }
  44        return 0;
  45}
  46
  47static int test_power_get_usb_property(struct power_supply *psy,
  48                                      enum power_supply_property psp,
  49                                      union power_supply_propval *val)
  50{
  51        switch (psp) {
  52        case POWER_SUPPLY_PROP_ONLINE:
  53                val->intval = usb_online;
  54                break;
  55        default:
  56                return -EINVAL;
  57        }
  58        return 0;
  59}
  60
  61static int test_power_get_battery_property(struct power_supply *psy,
  62                                           enum power_supply_property psp,
  63                                           union power_supply_propval *val)
  64{
  65        switch (psp) {
  66        case POWER_SUPPLY_PROP_MODEL_NAME:
  67                val->strval = "Test battery";
  68                break;
  69        case POWER_SUPPLY_PROP_MANUFACTURER:
  70                val->strval = "Linux";
  71                break;
  72        case POWER_SUPPLY_PROP_SERIAL_NUMBER:
  73                val->strval = UTS_RELEASE;
  74                break;
  75        case POWER_SUPPLY_PROP_STATUS:
  76                val->intval = battery_status;
  77                break;
  78        case POWER_SUPPLY_PROP_CHARGE_TYPE:
  79                val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
  80                break;
  81        case POWER_SUPPLY_PROP_HEALTH:
  82                val->intval = battery_health;
  83                break;
  84        case POWER_SUPPLY_PROP_PRESENT:
  85                val->intval = battery_present;
  86                break;
  87        case POWER_SUPPLY_PROP_TECHNOLOGY:
  88                val->intval = battery_technology;
  89                break;
  90        case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
  91                val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
  92                break;
  93        case POWER_SUPPLY_PROP_CAPACITY:
  94        case POWER_SUPPLY_PROP_CHARGE_NOW:
  95                val->intval = battery_capacity;
  96                break;
  97        case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  98        case POWER_SUPPLY_PROP_CHARGE_FULL:
  99                val->intval = 100;
 100                break;
 101        case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
 102        case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
 103                val->intval = 3600;
 104                break;
 105        case POWER_SUPPLY_PROP_TEMP:
 106                val->intval = 26;
 107                break;
 108        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 109                val->intval = battery_voltage;
 110                break;
 111        default:
 112                pr_info("%s: some properties deliberately report errors.\n",
 113                        __func__);
 114                return -EINVAL;
 115        }
 116        return 0;
 117}
 118
 119static enum power_supply_property test_power_ac_props[] = {
 120        POWER_SUPPLY_PROP_ONLINE,
 121};
 122
 123static enum power_supply_property test_power_battery_props[] = {
 124        POWER_SUPPLY_PROP_STATUS,
 125        POWER_SUPPLY_PROP_CHARGE_TYPE,
 126        POWER_SUPPLY_PROP_HEALTH,
 127        POWER_SUPPLY_PROP_PRESENT,
 128        POWER_SUPPLY_PROP_TECHNOLOGY,
 129        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 130        POWER_SUPPLY_PROP_CHARGE_FULL,
 131        POWER_SUPPLY_PROP_CHARGE_NOW,
 132        POWER_SUPPLY_PROP_CAPACITY,
 133        POWER_SUPPLY_PROP_CAPACITY_LEVEL,
 134        POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
 135        POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
 136        POWER_SUPPLY_PROP_MODEL_NAME,
 137        POWER_SUPPLY_PROP_MANUFACTURER,
 138        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 139        POWER_SUPPLY_PROP_TEMP,
 140        POWER_SUPPLY_PROP_VOLTAGE_NOW,
 141};
 142
 143static char *test_power_ac_supplied_to[] = {
 144        "test_battery",
 145};
 146
 147static struct power_supply test_power_supplies[] = {
 148        {
 149                .name = "test_ac",
 150                .type = POWER_SUPPLY_TYPE_MAINS,
 151                .supplied_to = test_power_ac_supplied_to,
 152                .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
 153                .properties = test_power_ac_props,
 154                .num_properties = ARRAY_SIZE(test_power_ac_props),
 155                .get_property = test_power_get_ac_property,
 156        }, {
 157                .name = "test_battery",
 158                .type = POWER_SUPPLY_TYPE_BATTERY,
 159                .properties = test_power_battery_props,
 160                .num_properties = ARRAY_SIZE(test_power_battery_props),
 161                .get_property = test_power_get_battery_property,
 162        }, {
 163                .name = "test_usb",
 164                .type = POWER_SUPPLY_TYPE_USB,
 165                .supplied_to = test_power_ac_supplied_to,
 166                .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
 167                .properties = test_power_ac_props,
 168                .num_properties = ARRAY_SIZE(test_power_ac_props),
 169                .get_property = test_power_get_usb_property,
 170        },
 171};
 172
 173
 174static int __init test_power_init(void)
 175{
 176        int i;
 177        int ret;
 178
 179        for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) {
 180                ret = power_supply_register(NULL, &test_power_supplies[i]);
 181                if (ret) {
 182                        pr_err("%s: failed to register %s\n", __func__,
 183                                test_power_supplies[i].name);
 184                        goto failed;
 185                }
 186        }
 187
 188        return 0;
 189failed:
 190        while (--i >= 0)
 191                power_supply_unregister(&test_power_supplies[i]);
 192        return ret;
 193}
 194module_init(test_power_init);
 195
 196static void __exit test_power_exit(void)
 197{
 198        int i;
 199
 200        /* Let's see how we handle changes... */
 201        ac_online = 0;
 202        usb_online = 0;
 203        battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
 204        for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
 205                power_supply_changed(&test_power_supplies[i]);
 206        pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
 207                __func__);
 208        ssleep(10);
 209
 210        for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
 211                power_supply_unregister(&test_power_supplies[i]);
 212}
 213module_exit(test_power_exit);
 214
 215
 216
 217#define MAX_KEYLENGTH 256
 218struct battery_property_map {
 219        int value;
 220        char const *key;
 221};
 222
 223static struct battery_property_map map_ac_online[] = {
 224        { 0,  "on"  },
 225        { 1,  "off" },
 226        { -1, NULL  },
 227};
 228
 229static struct battery_property_map map_status[] = {
 230        { POWER_SUPPLY_STATUS_CHARGING,     "charging"     },
 231        { POWER_SUPPLY_STATUS_DISCHARGING,  "discharging"  },
 232        { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" },
 233        { POWER_SUPPLY_STATUS_FULL,         "full"         },
 234        { -1,                               NULL           },
 235};
 236
 237static struct battery_property_map map_health[] = {
 238        { POWER_SUPPLY_HEALTH_GOOD,           "good"        },
 239        { POWER_SUPPLY_HEALTH_OVERHEAT,       "overheat"    },
 240        { POWER_SUPPLY_HEALTH_DEAD,           "dead"        },
 241        { POWER_SUPPLY_HEALTH_OVERVOLTAGE,    "overvoltage" },
 242        { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure"     },
 243        { -1,                                 NULL          },
 244};
 245
 246static struct battery_property_map map_present[] = {
 247        { 0,  "false" },
 248        { 1,  "true"  },
 249        { -1, NULL    },
 250};
 251
 252static struct battery_property_map map_technology[] = {
 253        { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" },
 254        { POWER_SUPPLY_TECHNOLOGY_LION, "LION" },
 255        { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" },
 256        { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" },
 257        { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" },
 258        { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" },
 259        { -1,                           NULL   },
 260};
 261
 262
 263static int map_get_value(struct battery_property_map *map, const char *key,
 264                                int def_val)
 265{
 266        char buf[MAX_KEYLENGTH];
 267        int cr;
 268
 269        strncpy(buf, key, MAX_KEYLENGTH);
 270        buf[MAX_KEYLENGTH-1] = '\0';
 271
 272        cr = strnlen(buf, MAX_KEYLENGTH) - 1;
 273        if (buf[cr] == '\n')
 274                buf[cr] = '\0';
 275
 276        while (map->key) {
 277                if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0)
 278                        return map->value;
 279                map++;
 280        }
 281
 282        return def_val;
 283}
 284
 285
 286static const char *map_get_key(struct battery_property_map *map, int value,
 287                                const char *def_key)
 288{
 289        while (map->key) {
 290                if (map->value == value)
 291                        return map->key;
 292                map++;
 293        }
 294
 295        return def_key;
 296}
 297
 298static int param_set_ac_online(const char *key, const struct kernel_param *kp)
 299{
 300        ac_online = map_get_value(map_ac_online, key, ac_online);
 301        power_supply_changed(&test_power_supplies[0]);
 302        return 0;
 303}
 304
 305static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
 306{
 307        strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown"));
 308        return strlen(buffer);
 309}
 310
 311static int param_set_usb_online(const char *key, const struct kernel_param *kp)
 312{
 313        usb_online = map_get_value(map_ac_online, key, usb_online);
 314        power_supply_changed(&test_power_supplies[2]);
 315        return 0;
 316}
 317
 318static int param_get_usb_online(char *buffer, const struct kernel_param *kp)
 319{
 320        strcpy(buffer, map_get_key(map_ac_online, usb_online, "unknown"));
 321        return strlen(buffer);
 322}
 323
 324static int param_set_battery_status(const char *key,
 325                                        const struct kernel_param *kp)
 326{
 327        battery_status = map_get_value(map_status, key, battery_status);
 328        power_supply_changed(&test_power_supplies[1]);
 329        return 0;
 330}
 331
 332static int param_get_battery_status(char *buffer, const struct kernel_param *kp)
 333{
 334        strcpy(buffer, map_get_key(map_status, battery_status, "unknown"));
 335        return strlen(buffer);
 336}
 337
 338static int param_set_battery_health(const char *key,
 339                                        const struct kernel_param *kp)
 340{
 341        battery_health = map_get_value(map_health, key, battery_health);
 342        power_supply_changed(&test_power_supplies[1]);
 343        return 0;
 344}
 345
 346static int param_get_battery_health(char *buffer, const struct kernel_param *kp)
 347{
 348        strcpy(buffer, map_get_key(map_health, battery_health, "unknown"));
 349        return strlen(buffer);
 350}
 351
 352static int param_set_battery_present(const char *key,
 353                                        const struct kernel_param *kp)
 354{
 355        battery_present = map_get_value(map_present, key, battery_present);
 356        power_supply_changed(&test_power_supplies[0]);
 357        return 0;
 358}
 359
 360static int param_get_battery_present(char *buffer,
 361                                        const struct kernel_param *kp)
 362{
 363        strcpy(buffer, map_get_key(map_present, battery_present, "unknown"));
 364        return strlen(buffer);
 365}
 366
 367static int param_set_battery_technology(const char *key,
 368                                        const struct kernel_param *kp)
 369{
 370        battery_technology = map_get_value(map_technology, key,
 371                                                battery_technology);
 372        power_supply_changed(&test_power_supplies[1]);
 373        return 0;
 374}
 375
 376static int param_get_battery_technology(char *buffer,
 377                                        const struct kernel_param *kp)
 378{
 379        strcpy(buffer,
 380                map_get_key(map_technology, battery_technology, "unknown"));
 381        return strlen(buffer);
 382}
 383
 384static int param_set_battery_capacity(const char *key,
 385                                        const struct kernel_param *kp)
 386{
 387        int tmp;
 388
 389        if (1 != sscanf(key, "%d", &tmp))
 390                return -EINVAL;
 391
 392        battery_capacity = tmp;
 393        power_supply_changed(&test_power_supplies[1]);
 394        return 0;
 395}
 396
 397#define param_get_battery_capacity param_get_int
 398
 399static int param_set_battery_voltage(const char *key,
 400                                        const struct kernel_param *kp)
 401{
 402        int tmp;
 403
 404        if (1 != sscanf(key, "%d", &tmp))
 405                return -EINVAL;
 406
 407        battery_voltage = tmp;
 408        power_supply_changed(&test_power_supplies[1]);
 409        return 0;
 410}
 411
 412#define param_get_battery_voltage param_get_int
 413
 414static struct kernel_param_ops param_ops_ac_online = {
 415        .set = param_set_ac_online,
 416        .get = param_get_ac_online,
 417};
 418
 419static struct kernel_param_ops param_ops_usb_online = {
 420        .set = param_set_usb_online,
 421        .get = param_get_usb_online,
 422};
 423
 424static struct kernel_param_ops param_ops_battery_status = {
 425        .set = param_set_battery_status,
 426        .get = param_get_battery_status,
 427};
 428
 429static struct kernel_param_ops param_ops_battery_present = {
 430        .set = param_set_battery_present,
 431        .get = param_get_battery_present,
 432};
 433
 434static struct kernel_param_ops param_ops_battery_technology = {
 435        .set = param_set_battery_technology,
 436        .get = param_get_battery_technology,
 437};
 438
 439static struct kernel_param_ops param_ops_battery_health = {
 440        .set = param_set_battery_health,
 441        .get = param_get_battery_health,
 442};
 443
 444static struct kernel_param_ops param_ops_battery_capacity = {
 445        .set = param_set_battery_capacity,
 446        .get = param_get_battery_capacity,
 447};
 448
 449static struct kernel_param_ops param_ops_battery_voltage = {
 450        .set = param_set_battery_voltage,
 451        .get = param_get_battery_voltage,
 452};
 453
 454#define param_check_ac_online(name, p) __param_check(name, p, void);
 455#define param_check_usb_online(name, p) __param_check(name, p, void);
 456#define param_check_battery_status(name, p) __param_check(name, p, void);
 457#define param_check_battery_present(name, p) __param_check(name, p, void);
 458#define param_check_battery_technology(name, p) __param_check(name, p, void);
 459#define param_check_battery_health(name, p) __param_check(name, p, void);
 460#define param_check_battery_capacity(name, p) __param_check(name, p, void);
 461#define param_check_battery_voltage(name, p) __param_check(name, p, void);
 462
 463
 464module_param(ac_online, ac_online, 0644);
 465MODULE_PARM_DESC(ac_online, "AC charging state <on|off>");
 466
 467module_param(usb_online, usb_online, 0644);
 468MODULE_PARM_DESC(usb_online, "USB charging state <on|off>");
 469
 470module_param(battery_status, battery_status, 0644);
 471MODULE_PARM_DESC(battery_status,
 472        "battery status <charging|discharging|not-charging|full>");
 473
 474module_param(battery_present, battery_present, 0644);
 475MODULE_PARM_DESC(battery_present,
 476        "battery presence state <good|overheat|dead|overvoltage|failure>");
 477
 478module_param(battery_technology, battery_technology, 0644);
 479MODULE_PARM_DESC(battery_technology,
 480        "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
 481
 482module_param(battery_health, battery_health, 0644);
 483MODULE_PARM_DESC(battery_health,
 484        "battery health state <good|overheat|dead|overvoltage|failure>");
 485
 486module_param(battery_capacity, battery_capacity, 0644);
 487MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)");
 488
 489module_param(battery_voltage, battery_voltage, 0644);
 490MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)");
 491
 492MODULE_DESCRIPTION("Power supply driver for testing");
 493MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
 494MODULE_LICENSE("GPL");
 495
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.