#include <config.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <linux/soundcard.h>
#include <glib.h>
#include <liberdm/erdm.h>
#include <liberipc/eripcpowermgr.h>
#include <liberipc/eripcbusyd.h>
#include <liberipc/eripccontentlister.h>
#include <liberipc/eripctoolbar.h>
#include "powerMgr.h"
#include "toolbar.h"
Go to the source code of this file.
Defines | |
| #define | DBG(x) |
| #define | ERROR(x) printf x |
| #define | ENABLE_CPU_THROTTLE |
| #define | CPU_SPEED_LOW "100000" |
| #define | CPU_SPEED_HIGH "400000" |
| #define | IDLE_PERCENTAGE_SPEED_UP 50 |
| #define | IDLE_PERCENTAGE_THROTTLE 95 |
| #define | SAMPLE_INTERVAL_LONG 1000 |
| #define | SAMPLE_INTERVAL_SHORT 100 |
| #define | MS_PER_IDLE_TICK 10 |
| #define | IDLE_THRESHOLD_SPEED_UP (SAMPLE_INTERVAL_SHORT * IDLE_PERCENTAGE_SPEED_UP / 100 / MS_PER_IDLE_TICK) |
| #define | IDLE_THRESHOLD_THROTTLE (SAMPLE_INTERVAL_LONG * IDLE_PERCENTAGE_THROTTLE / 100 / MS_PER_IDLE_TICK) |
Enumerations | |
| enum | { e_cpu_low, e_cpu_high } |
Functions | |
| static int | getDeviceState (board_status_t *ereader, int evt_fd, int pwr_fd) |
| static int | setAC97Amp (int enabled) |
| static int | setMMC (int enabled, int pwr_fd, board_status_t *ereader) |
| static void | set_cpu_speed (const char *kHz) |
| void | powerMgrMsgRxd (erServerChannel_t channel, int source_fd) |
| int | powerMgrInstallIpcServer () |
| static guint64 | get_cpu_idle_count (void) |
| static void | cpu_throttle (void) |
| static void | check_battery_status (unsigned int charge_status, unsigned int time_left, short current) |
| static void * | eventPoller (void *arg) |
| int | main (int argc, char *argv[]) |
Variables | |
| static erServerChannel_t | theServerChannel |
| static erClientChannel_t | contentListerChannel |
| static board_status_t | g_ereader |
| static enum { ... } | g_cpu_speed |
Copyright (C) 2005-2008 iRex Technologies B.V. All rights reserved.
Definition in file powerMgr.c.
| #define CPU_SPEED_HIGH "400000" |
Definition at line 68 of file powerMgr.c.
| #define CPU_SPEED_LOW "100000" |
Definition at line 67 of file powerMgr.c.
| #define DBG | ( | x | ) |
eReader Powermanagement daemon
Definition at line 55 of file powerMgr.c.
| #define ENABLE_CPU_THROTTLE |
Definition at line 64 of file powerMgr.c.
| #define ERROR | ( | x | ) | printf x |
Definition at line 57 of file powerMgr.c.
| #define IDLE_PERCENTAGE_SPEED_UP 50 |
Definition at line 70 of file powerMgr.c.
| #define IDLE_PERCENTAGE_THROTTLE 95 |
Definition at line 71 of file powerMgr.c.
| #define IDLE_THRESHOLD_SPEED_UP (SAMPLE_INTERVAL_SHORT * IDLE_PERCENTAGE_SPEED_UP / 100 / MS_PER_IDLE_TICK) |
Definition at line 77 of file powerMgr.c.
| #define IDLE_THRESHOLD_THROTTLE (SAMPLE_INTERVAL_LONG * IDLE_PERCENTAGE_THROTTLE / 100 / MS_PER_IDLE_TICK) |
Definition at line 78 of file powerMgr.c.
| #define MS_PER_IDLE_TICK 10 |
Definition at line 76 of file powerMgr.c.
| #define SAMPLE_INTERVAL_LONG 1000 |
Definition at line 73 of file powerMgr.c.
| #define SAMPLE_INTERVAL_SHORT 100 |
Definition at line 74 of file powerMgr.c.
| anonymous enum |
| static void check_battery_status | ( | unsigned int | charge_status, | |
| unsigned int | time_left, | |||
| short | current | |||
| ) | [static] |
Definition at line 317 of file powerMgr.c.
00318 { 00319 static int iconState_previous = 0; // for battery iconState = 0 is grey 00320 int iconState; 00321 00322 DBG(("check_battery_status(): charge [%u] time left [%u] current [%hd]\n", charge_status, time_left, current)); 00323 00324 // update toolbar icon: 0 - 20 - 40 - 60 - 80 - 100% 00325 // round 0 .. 14 downward 00326 // round 15 .. 19 upward 00327 if (charge_status >= 0 && charge_status <= 100) 00328 { 00329 iconState = 1 + ((charge_status + 4) / 20); 00330 } 00331 else 00332 { 00333 // invalid battery charge: icon grey 00334 iconState = 0; 00335 } 00336 00337 // show toolbar icon 00338 if (iconState != iconState_previous) 00339 { 00340 iconState_previous = iconState; 00341 toolbar_setIconState(iconID_battery, iconState); 00342 usleep(200*1000); // wait for toolbar to update the icon 00343 dmDisplay(dmCmdPriorLow, dmQTyping); 00344 } 00345 00346 // tell contentlister when battery almost empty 00347 if ((charge_status <= BATTERY_LOW_WARNING) && (current < BATTERY_CHARGING)) 00348 { 00349 ERROR(("Battery charge is %u, threshold is %u (time left is %u, current is %hd)\n", charge_status, BATTERY_LOW_WARNING, time_left, current)); 00350 00351 if (charge_status <= BATTERY_LOW_EMERGENCY) 00352 { 00353 // this should not happen, seems like contentlister did not respond to our shutdown message 00354 // do a forced shutdown now to avoid the battery gets completely discharged 00355 ERROR(("\n\n --- EMERGENCY SHUTDOWN: battery charge is %d%% ---\n\n", charge_status)); 00356 system("halt"); 00357 } 00358 else if (charge_status <= BATTERY_LOW_SHUTDOWN) 00359 { 00360 // contentlister must shutdown the device immediately 00361 clBatteryLow(contentListerChannel, ccClBattery_shutdown, charge_status, time_left); 00362 } 00363 else 00364 { 00365 // contentlister must warn the user about the battery status 00366 clBatteryLow(contentListerChannel, ccClBattery_warning, charge_status, time_left); 00367 } 00368 } 00369 }

| static void cpu_throttle | ( | void | ) | [static] |
Definition at line 284 of file powerMgr.c.
00285 { 00286 guint64 idle_diff; 00287 00288 idle_diff = get_cpu_idle_count(); 00289 if (idle_diff >= 0) 00290 { 00291 switch (g_cpu_speed) 00292 { 00293 case e_cpu_low: 00294 if (idle_diff <= IDLE_THRESHOLD_SPEED_UP) 00295 { 00296 set_cpu_speed(CPU_SPEED_HIGH); 00297 g_cpu_speed = e_cpu_high; 00298 } 00299 break; 00300 case e_cpu_high: 00301 if (idle_diff >= IDLE_THRESHOLD_THROTTLE) 00302 { 00303 set_cpu_speed(CPU_SPEED_LOW); 00304 g_cpu_speed = e_cpu_low; 00305 } 00306 break; 00307 default: 00308 ; // ignore 00309 } 00310 } 00311 }

| static void* eventPoller | ( | void * | arg | ) | [static] |
Definition at line 371 of file powerMgr.c.
00372 { 00373 static int battery_poll_ticks = 20; // delay first update till contentLister started 00374 static int next_second_ticks = 0; 00375 unsigned int battery_charge_status; 00376 unsigned int battery_time_left; 00377 unsigned int battery_current; 00378 short current; 00379 00380 board_status_t* ereader = (board_status_t *) arg; 00381 int evt_fd; 00382 int pwr_fd; 00383 int status; 00384 int oldstatus; 00385 int ret; 00386 00387 // init event and power mgmt interfaces 00388 evt_fd = open(DEVEVTIFACE, O_RDWR | O_NONBLOCK); 00389 if (evt_fd < 0) 00390 { 00391 perror("Error opening /dev/buttons"); 00392 pthread_exit(NULL); 00393 } 00394 00395 pwr_fd = open(POWERMGMTIFACE, O_RDWR); 00396 if (pwr_fd < 0) 00397 { 00398 perror("Error opening /dev/battery"); 00399 pthread_exit(NULL); 00400 } 00401 00402 // Get initial device state 00403 oldstatus = getDeviceState(ereader, evt_fd, pwr_fd); 00404 00405 // Initialise cpu speed 00406 set_cpu_speed(CPU_SPEED_HIGH); 00407 g_cpu_speed = e_cpu_high; 00408 00409 while (1) 00410 { 00411 if (g_cpu_speed == e_cpu_low) 00412 { 00413 // low cpu frequency: short interval so we can speed up when cpu load changes 00414 usleep(SAMPLE_INTERVAL_SHORT * 1000L); 00415 cpu_throttle(); 00416 if (--next_second_ticks > 0) 00417 { 00418 continue; //next while iteration 00419 } 00420 } 00421 else 00422 { 00423 // high cpu frequency: long interval so we do not disturb other processing 00424 usleep(SAMPLE_INTERVAL_LONG * 1000L); 00425 cpu_throttle(); 00426 } 00427 next_second_ticks = (1000 / SAMPLE_INTERVAL_SHORT); 00428 00429 /* Check the battery status */ 00430 if (--battery_poll_ticks <= 0) 00431 { 00432 battery_poll_ticks = 60; // seconds 00433 00434 // battery measurement works reliably only at full cpu speed 00435 if (g_cpu_speed == e_cpu_low) 00436 { 00437 set_cpu_speed(CPU_SPEED_HIGH); 00438 } 00439 00440 // read battery status 00441 if (ioctl(pwr_fd, BATTERY_IOCTL_READ_CHARGE, &battery_charge_status) == -1) // percentage 0 ... 100 00442 { 00443 perror("ioctl read charge failed"); 00444 } 00445 if (ioctl(pwr_fd, BATTERY_IOCTL_READ_TIME, &battery_time_left) == -1) // in minutes, 65535 = charging 00446 { 00447 perror("ioctl read time failed"); 00448 } 00449 if (ioctl(pwr_fd, BATTERY_IOCTL_READ_CURRENT, &battery_current) == -1) // in milliamps, positive or negative 00450 { 00451 perror("ioctl read current failed"); 00452 } 00453 current = battery_current & 0xFFFF; // convert from unsigned int to short 00454 00455 // back to low cpu speed when needed 00456 if (g_cpu_speed == e_cpu_low) 00457 { 00458 set_cpu_speed(CPU_SPEED_LOW); 00459 } 00460 00461 // check battery status and set toolbar icon 00462 check_battery_status(battery_charge_status, battery_time_left, current); 00463 } 00464 00465 /* Check the buttons */ 00466 ret = ioctl(evt_fd, BUTTON_IOCTL_GET_STATUS, &status); 00467 if (ret < 0) 00468 { 00469 perror("ioctl invalid status"); 00470 } 00471 else 00472 { 00473 //DBG(("decode status: [P = %x] [CF = %x] [MMC = %x]\n", GETPENDETECT(status), GETCFDETECT(status), GETMMCDETECT(status))); 00474 00475 if (GETMMCDETECT(status) ^ GETMMCDETECT(oldstatus)) 00476 { 00477 if (GETMMCDETECT(status)) 00478 { 00479 ERROR(("MMC card inserted\n")); 00480 ereader->mmc_card = INSERTED; 00481 00482 /* a card was inserted, mount it and tell contentLister */ 00483 if (ereader->mmc_ctrl == UNPOWERED) 00484 { 00485 setMMC(POWERED, pwr_fd, ereader); 00486 } 00487 system("/usr/bin/mountmmc.sh"); 00488 clStoragePresent(contentListerChannel, SD_ID, 1); 00489 } 00490 else 00491 { 00492 ERROR(("MMC card gone\n")); 00493 ereader->mmc_card = GONE; 00494 00495 /* a card was removed, unmount it and tell contentLister */ 00496 system("/usr/bin/umountmmc.sh"); 00497 clStoragePresent(contentListerChannel, SD_ID, 0); 00498 if (ereader->mmc_ctrl == POWERED) 00499 { 00500 setMMC(UNPOWERED, pwr_fd, ereader); 00501 } 00502 } 00503 } 00504 } 00505 oldstatus = status; 00506 } // while 00507 00508 /* cleanup */ 00509 close(evt_fd); 00510 close(pwr_fd); 00511 00512 pthread_exit(NULL); 00513 }

| static guint64 get_cpu_idle_count | ( | void | ) | [static] |
Definition at line 242 of file powerMgr.c.
00243 { 00244 static guint64 idle_previous = 0; 00245 00246 guint64 idle_current; 00247 guint64 idle_diff = 0; 00248 FILE *fp; 00249 char buf[200]; 00250 char *cp; 00251 00252 fp = fopen("/proc/stat", "r"); 00253 if (fp) 00254 { 00255 cp = fgets(buf, sizeof(buf), fp); 00256 if (cp == buf) 00257 { 00258 cp = strtok(buf, " "); 00259 if (strcmp(cp, "cpu") == 0) 00260 { 00261 cp = strtok(NULL, " "); 00262 cp = strtok(NULL, " "); 00263 cp = strtok(NULL, " "); 00264 cp = strtok(NULL, " "); 00265 idle_current = g_ascii_strtoull(cp, NULL, 10); 00266 00267 idle_diff = idle_current - idle_previous; 00268 if (idle_diff < 0) 00269 { 00270 printf("--> Illegal cpu idle count [%s] [%llu], previous [%llu]\n", 00271 cp, idle_current, idle_previous); 00272 idle_diff = 0; 00273 } 00274 00275 idle_previous = idle_current; 00276 } 00277 } 00278 fclose(fp); 00279 } 00280 00281 return idle_diff; 00282 }
| static int getDeviceState | ( | board_status_t * | ereader, | |
| int | evt_fd, | |||
| int | pwr_fd | |||
| ) | [static] |
Query device state at boot time
Definition at line 518 of file powerMgr.c.
00519 { 00520 int ret, status; 00521 00522 ret = ioctl(evt_fd, BUTTON_IOCTL_GET_STATUS, &status); 00523 if (ret < 0) 00524 perror("ioctl on event interface"); 00525 00526 DBG(("Got initial state 0x%x\n", status)); 00527 00528 ereader->ac97_amp = POWERED; 00529 DBG(("- AC97 powered on\n")); 00530 00531 if (GETMMCDETECT(status)) 00532 { 00533 ereader->mmc_card = INSERTED; 00534 ereader->mmc_ctrl = POWERED; 00535 DBG(("- MMC card present, MMC controller powered\n")); 00536 /* MMC present at boot time, mount it! */ 00537 system("/usr/bin/mountmmc.sh"); 00538 } 00539 else 00540 { 00541 ereader->mmc_card = GONE; 00542 ereader->mmc_ctrl = POWERED; 00543 DBG(("- MMC card gone, MMC controller powered\n")); 00544 } 00545 return status; 00546 }
| int main | ( | int | argc, | |
| char * | argv[] | |||
| ) |
Definition at line 549 of file powerMgr.c.
00550 { 00551 pthread_t pollThread; 00552 //pthread_t timerThread; 00553 pthread_attr_t my_attr; 00554 00555 toolbar_init(); 00556 00557 erIpcStartClient(erIpcGetChannel(ER_CONTENT_LISTER_UA_ID), &contentListerChannel); 00558 00559 /* start polling thread */ 00560 if (0 != pthread_attr_init(&my_attr)) 00561 { 00562 perror("pthread_attr_init"); 00563 } 00564 if (0 != pthread_attr_setdetachstate(&my_attr, PTHREAD_CREATE_DETACHED)) 00565 { 00566 perror("thread set detach state"); 00567 } 00568 if (0 != pthread_create(&pollThread, &my_attr, eventPoller, (void *) &g_ereader)) 00569 { 00570 perror("pthread_create"); 00571 } 00572 00573 /* setup ipc */ 00574 powerMgrInstallIpcServer(); 00575 00576 return 0; /* we never get here */ 00577 }

| int powerMgrInstallIpcServer | ( | ) |
Definition at line 211 of file powerMgr.c.
00212 { 00213 int returnValue; 00214 int fd = -1; 00215 fd_set readfds; 00216 00217 returnValue = 00218 erIpcOpenServerChannel(ER_POWERMGR_CHANNEL, &theServerChannel); 00219 00220 if (returnValue != (-1)) 00221 { 00222 fd = erIpcGetServerFd(theServerChannel); 00223 00224 FD_ZERO(&readfds); 00225 FD_SET(fd, &readfds); 00226 00227 while (1) 00228 { 00229 select(fd + 1, &readfds, NULL, NULL, NULL); 00230 powerMgrMsgRxd(theServerChannel, fd); 00231 } 00232 } 00233 else 00234 { 00235 fprintf(stderr, "Could not open server channel\n"); 00236 return -1; 00237 } 00238 return 0; 00239 }

| void powerMgrMsgRxd | ( | erServerChannel_t | channel, | |
| int | source_fd | |||
| ) |
This callback is invoked when there is data to read on file descriptor source_fd. The channel info is passed via parameter 'data'
Definition at line 165 of file powerMgr.c.
00166 { 00167 char szBuffer[SERVER_BUFFER_SIZE]; 00168 int nBuf = SERVER_BUFFER_SIZE; 00169 erIpcCmd_t command; 00170 int enabled; 00171 int MHz; 00172 00173 erIpcGetMessage(channel, szBuffer, &nBuf); 00174 00175 if (pwrParseCommand(szBuffer, &command) >= 0) 00176 { 00177 switch (command.cc) 00178 { 00179 case ccPwrAC97: 00180 enabled = atoi(command.arg[0]); 00181 setAC97Amp(enabled); 00182 break; 00183 00184 case ccPwrIdleMode: 00185 MHz = atoi(command.arg[0]); 00186 if (MHz * 1000 == atoi(CPU_SPEED_LOW)) 00187 { 00188 set_cpu_speed(CPU_SPEED_LOW); 00189 g_cpu_speed = e_cpu_low; 00190 } 00191 else if (MHz * 1000 == atoi(CPU_SPEED_HIGH)) 00192 { 00193 set_cpu_speed(CPU_SPEED_HIGH); 00194 g_cpu_speed = e_cpu_high; 00195 } 00196 else 00197 { 00198 printf("Invalid cpu speed requested [%s]\n", command.arg[0]); 00199 set_cpu_speed(CPU_SPEED_HIGH); 00200 g_cpu_speed = e_cpu_high; 00201 } 00202 break; 00203 00204 default: 00205 printf("UNKNOWN COMMAND %d\n", command.cc); 00206 break; 00207 } 00208 } 00209 }

| static void set_cpu_speed | ( | const char * | kHz | ) | [static] |
Definition at line 138 of file powerMgr.c.
00139 { 00140 #ifdef ENABLE_CPU_THROTTLE 00141 FILE *fp; 00142 00143 if (kHz == NULL) 00144 { 00145 return; 00146 } 00147 00148 fp = fopen("/proc/sys/cpu/0/speed", "w"); 00149 if (fp) 00150 { 00151 fputs(kHz, fp); 00152 fclose(fp); 00153 } 00154 #else 00155 // Never set CPU speed 00156 return; 00157 #endif 00158 }
| static int setAC97Amp | ( | int | enabled | ) | [static] |
Definition at line 86 of file powerMgr.c.
00087 { 00088 int mixer_device = 0; 00089 00090 DBG(("Setting AC97 to %s\n", (enabled) ? "enabled" : "disabled")); 00091 mixer_device = open("/dev/dsp", O_RDWR); 00092 if (mixer_device == -1) 00093 { 00094 perror("opening mixer device.\n"); 00095 return -1; 00096 } 00097 00098 if(!enabled) 00099 { 00100 if (ioctl(mixer_device, SNDCTL_POWER_OFF)) 00101 { 00102 perror("Ioctl on mixer device"); 00103 } 00104 } 00105 else 00106 { 00107 if (ioctl(mixer_device, SNDCTL_POWER_ON)) 00108 { 00109 perror("Ioctl on mixer device"); 00110 } 00111 } 00112 00113 // if (ioctl(audio_device, SOUND_MIXER_PRIVATE1, &i)) 00114 // { 00115 // perror("Ioctl on audio device"); 00116 // return -1; 00117 // } 00118 close(mixer_device); 00119 return 0; 00120 }
| static int setMMC | ( | int | enabled, | |
| int | pwr_fd, | |||
| board_status_t * | ereader | |||
| ) | [static] |
Definition at line 122 of file powerMgr.c.
00123 { 00124 DBG(("Setting MMC controller to %s\n", (enabled == POWERED) ? "enabled" : "disabled")); 00125 if (enabled == POWERED) 00126 { 00127 // if ( 0 == ioctl (pwr_fd, BATTERY_IOCTL_ENABLE_MMC, &status)) 00128 ereader->mmc_ctrl = POWERED; 00129 } 00130 else 00131 { 00132 // if ( 0 == ioctl (pwr_fd, BATTERY_IOCTL_DISABLE_MMC, &status)) 00133 ereader->mmc_ctrl = UNPOWERED; 00134 } 00135 return 0; 00136 }
erClientChannel_t contentListerChannel [static] |
Definition at line 60 of file powerMgr.c.
enum { ... } g_cpu_speed [static] |
board_status_t g_ereader [static] |
Definition at line 61 of file powerMgr.c.
erServerChannel_t theServerChannel [static] |
Definition at line 59 of file powerMgr.c.
1.5.6