2
* Copyright (C) 2003,2004 Rene Rebe <rene@rocklinux.org>
3
* 2005 Mattia Dongili <malattia@linux.it>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* Based upon the acpi version:
20
* Copyright (C) 2002-2005 Mattia Dongili<malattia@linux.it>
21
* George Staikos <staikos@0wned.org>
24
* Ported to cpufreqd-2 new plugin interface by Mattia Dongili
32
#include "cpufreqd_plugin.h"
35
# define PMU_INFO_FILE "/proc/pmu/info"
36
# define PMU_BATTERY_FILE "/proc/pmu/battery_0"
38
# define PMU_INFO_FILE "/home/mattia/devel/cpufreqd/pmu/info"
39
# define PMU_BATTERY_FILE "/home/mattia/devel/cpufreqd/pmu/battery_0"
44
struct battery_interval {
50
static char version[100];
51
static unsigned int battery_present;
52
static int battery_percent;
53
static unsigned int ac;
55
static int tokenize (FILE *fp, char *t, char *v) {
61
if (fgets(str, 255, fp) == NULL)
64
if ((s1 = strtok(str, ":")) == NULL)
67
s2 = s1 + strlen (s1) - 1;
68
/* remove trailing spaces */
69
for ( ; s1 != s2 ; --s2) {
80
if ((s1 = strtok(NULL, ":")) == NULL)
83
for ( ; *s1 != 0 ; ++s1) {
88
s2 = s1 + strlen (s1) - 1;
89
/* remove trailing spaces */
90
for ( ; s1 != s2 ; --s2) {
104
/* check if PMU is available
106
static int pmu_init(void) {
110
fp = fopen(PMU_INFO_FILE, "r");
112
clog(LOG_ERR, "%s: %s\n", PMU_INFO_FILE, strerror(errno));
116
while (tokenize(fp, tag, val) != EOF) {
117
if (strcmp(tag, "PMU driver version") == 0) {
118
sprintf(version, "%s - ", val);
120
else if (strcmp(tag, "PMU firmware version") == 0) {
121
strncat(version, val, 100-strlen(version));
126
clog(LOG_NOTICE, "PMU driver/firmware version %s\n", version);
131
static int pmu_update(void) {
135
float bat_charge = .0;
136
float bat_max_charge = .0;
138
/** /proc/pmu/info **/
139
fp = fopen(PMU_INFO_FILE, "r");
141
clog(LOG_ERR, "%s: %s\n", PMU_INFO_FILE, strerror(errno));
145
while (tokenize(fp, tag, val) != EOF) {
146
if (strcmp(tag, "AC Power") == 0) {
149
else if (strcmp(tag, "Battery count") == 0) {
150
battery_present = atoi(val);
155
/** /proc/pmu/battery_0 **/
156
fp = fopen(PMU_BATTERY_FILE, "r");
158
clog(LOG_ERR, "%s: %s\n", PMU_BATTERY_FILE, strerror(errno));
162
while (tokenize(fp, tag, val) != EOF) {
163
if (strcmp(tag, "charge") == 0) {
164
bat_charge = atof(val);
166
else if (strcmp(tag, "max_charge") == 0) {
167
bat_max_charge = atof(val);
172
battery_percent = 100 * (bat_charge / bat_max_charge);
174
clog(LOG_INFO, "battery %s - %d - %s\n",
175
battery_present ? "present" : "absent",
177
ac ? "on-line" : "off-line");
182
* parse the 'ac' keywork
184
static int pmu_ac_parse(const char *ev, void **obj) {
185
unsigned int *ret = malloc(sizeof(int));
187
clog(LOG_ERR, "couldn't make enough room for ac_status (%s)\n",
192
clog(LOG_DEBUG, "called with %s\n", ev);
194
if (strncmp(ev, "on", 2) == 0) {
196
} else if (strncmp(ev, "off", 3) == 0) {
199
clog(LOG_ERR, "couldn't parse %s\n", ev);
203
clog(LOG_INFO, "parsed %s\n", *ret==PLUGGED ? "on" : "off");
210
* evaluate the 'ac' keywork
212
static int pmu_ac_evaluate(const void *s) {
213
const unsigned int *ac_parm = (const unsigned int *)s;
215
clog(LOG_DEBUG, "called %s [%s]\n",
216
*ac_parm==PLUGGED ? "on" : "off", ac==PLUGGED ? "on" : "off");
218
return (*ac_parm == ac) ? MATCH : DONT_MATCH;
222
* parse the 'battery' keywork
224
static int pmu_bat_parse(const char *ev, void **obj) {
225
struct battery_interval *ret = malloc(sizeof(struct battery_interval));
227
clog(LOG_ERR, "couldn't make enough room for battery_interval (%s)\n",
231
ret->min = ret->max = 0;
232
clog(LOG_DEBUG, "called with %s\n", ev);
234
if (sscanf(ev, "%d-%d", &(ret->min), &(ret->max)) != 2) {
235
clog(LOG_ERR, "wrong parameter %s\n", ev);
240
clog(LOG_INFO, "parsed %d-%d\n", ret->min, ret->max);
247
* evaluate the 'battery' keywork
249
static int pmu_bat_evaluate(const void *s) {
250
const struct battery_interval *bi = (const struct battery_interval *)s;
252
clog(LOG_DEBUG, "called %d-%d [%d]\n", bi->min, bi->max, battery_percent);
254
return (battery_percent>=bi->min && battery_percent<=bi->max) ? MATCH : DONT_MATCH;
257
static struct cpufreqd_keyword kw[] = {
258
{ .word = "ac", .parse = &pmu_ac_parse, .evaluate = &pmu_ac_evaluate },
259
{ .word = "battery_interval", .parse = &pmu_bat_parse, .evaluate = &pmu_bat_evaluate },
260
{ .word = NULL, .parse = NULL, .evaluate = NULL }
263
static struct cpufreqd_plugin pmu = {
264
.plugin_name = "pmu_plugin", /* plugin_name */
265
.keywords = kw, /* config_keywords */
266
.plugin_init = &pmu_init, /* plugin_init */
267
.plugin_update = &pmu_update /* plugin_update */
270
struct cpufreqd_plugin *create_plugin (void) {