|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/pow/pow.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
1 /*- 2 * Copyright (c) 2009, Kohsuke Ohtani 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the author nor the names of any co-contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * pow.c - power server 32 */ 33 34 #include <sys/prex.h> 35 #include <sys/mount.h> 36 #include <sys/ioctl.h> 37 #include <ipc/proc.h> 38 #include <ipc/pow.h> 39 #include <ipc/exec.h> 40 #include <ipc/ipc.h> 41 42 #include <unistd.h> 43 #include <string.h> 44 #include <stdlib.h> 45 #include <stdio.h> 46 #include <signal.h> 47 #include <errno.h> 48 49 /* #define DEBUG_POW 1 */ 50 51 #ifdef DEBUG_POW 52 #define DPRINTF(a) dprintf a 53 #else 54 #define DPRINTF(a) 55 #endif 56 57 /* 58 * Action for each power event. 59 */ 60 struct power_action { 61 int pwrbtn; /* state for power button press */ 62 int slpbtn; /* state for sleep button press */ 63 int lcdclose; /* state for LCD close */ 64 int lowbatt; /* state for low battery */ 65 }; 66 67 static int pow_noop(struct msg *); 68 static int pow_set_power(struct msg *); 69 static int pow_get_policy(struct msg *); 70 static int pow_set_policy(struct msg *); 71 static int pow_get_sustmr(struct msg *); 72 static int pow_set_sustmr(struct msg *); 73 static int pow_get_dimtmr(struct msg *); 74 static int pow_set_dimtmr(struct msg *); 75 static int pow_battery_lvl(struct msg *); 76 static int pow_debug(struct msg *); 77 78 static void set_power_state(int); 79 static void shutdown_server(const char *); 80 81 /* 82 * Message mapping 83 */ 84 struct msg_map { 85 int code; 86 int (*func)(struct msg *); 87 }; 88 89 static const struct msg_map powermsg_map[] = { 90 {POW_SET_POWER, pow_set_power}, 91 {POW_GET_POLICY, pow_get_policy}, 92 {POW_SET_POLICY, pow_set_policy}, 93 {POW_GET_SUSTMR, pow_get_sustmr}, 94 {POW_SET_SUSTMR, pow_set_sustmr}, 95 {POW_GET_DIMTMR, pow_get_dimtmr}, 96 {POW_SET_DIMTMR, pow_set_dimtmr}, 97 {POW_BATTERY_LVL, pow_battery_lvl}, 98 {STD_DEBUG, pow_debug}, 99 {0, pow_noop}, 100 }; 101 102 static struct power_action pmact; 103 static device_t pmdev; 104 105 static int 106 pow_noop(struct msg *msg) 107 { 108 return 0; 109 } 110 111 static int 112 pow_set_power(struct msg *msg) 113 { 114 int state; 115 116 state = msg->data[0]; 117 set_power_state(state); 118 return 0; 119 } 120 121 static int 122 pow_get_policy(struct msg *msg) 123 { 124 int policy; 125 126 device_ioctl(pmdev, PMIOC_GET_POLICY, &policy); 127 msg->data[0] = policy; 128 return 0; 129 } 130 131 static int 132 pow_set_policy(struct msg *msg) 133 { 134 int policy; 135 136 policy = msg->data[0]; 137 device_ioctl(pmdev, PMIOC_SET_POLICY, &policy); 138 return 0; 139 } 140 141 static int 142 pow_get_sustmr(struct msg *msg) 143 { 144 int timeout; 145 146 device_ioctl(pmdev, PMIOC_GET_SUSTMR, &timeout); 147 msg->data[0] = timeout; 148 return 0; 149 } 150 151 static int 152 pow_set_sustmr(struct msg *msg) 153 { 154 int timeout; 155 156 timeout = msg->data[0]; 157 device_ioctl(pmdev, PMIOC_SET_SUSTMR, &timeout); 158 return 0; 159 } 160 161 static int 162 pow_get_dimtmr(struct msg *msg) 163 { 164 int timeout; 165 166 device_ioctl(pmdev, PMIOC_GET_DIMTMR, &timeout); 167 msg->data[0] = timeout; 168 return 0; 169 } 170 171 static int 172 pow_set_dimtmr(struct msg *msg) 173 { 174 int timeout; 175 176 timeout = msg->data[0]; 177 device_ioctl(pmdev, PMIOC_SET_DIMTMR, &timeout); 178 return 0; 179 } 180 181 static int 182 pow_battery_lvl(struct msg *msg) 183 { 184 /* TODO: Get current battery level from battery driver. */ 185 return 0; 186 } 187 188 static void 189 set_power_state(int state) 190 { 191 192 if (pmdev != NODEV) { 193 DPRINTF(("set_power_state: state=%d\n", state)); 194 195 sync(); 196 if (state == PWR_OFF || state == PWR_REBOOT) { 197 kill(-1, SIGTERM); 198 shutdown_server("!exec"); 199 shutdown_server("!fs"); 200 shutdown_server("!proc"); 201 } 202 device_ioctl(pmdev, PMIOC_SET_POWER, &state); 203 } 204 } 205 206 static void 207 exception_handler(int sig) 208 { 209 210 if (sig == SIGPWR) { 211 DPRINTF(("SIGPWR!\n")); 212 } 213 exception_return(); 214 } 215 216 static void 217 power_thread(void) 218 { 219 int sig, event, state; 220 221 DPRINTF(("power_thread: start\n")); 222 223 for (;;) { 224 /* 225 * Wait signals from PM driver. 226 */ 227 exception_wait(&sig); 228 DPRINTF(("power_thread: sig=%d\n", sig)); 229 230 if (sig == SIGPWR) { 231 /* 232 * Query PM events. 233 */ 234 device_ioctl(pmdev, PMIOC_QUERY_EVENT, &event); 235 DPRINTF(("power_thread: event=%d\n", event)); 236 237 /* 238 * Do action for current power settings. 239 */ 240 state = PWR_ON; 241 switch (event) { 242 case PME_PWRBTN_PRESS: 243 state = pmact.pwrbtn; 244 break; 245 case PME_LOW_BATTERY: 246 state = pmact.lowbatt; 247 break; 248 case PME_SLPBTN_PRESS: 249 state = pmact.slpbtn; 250 break; 251 case PME_LCD_CLOSE: 252 state = pmact.lcdclose; 253 break; 254 } 255 if (state != PWR_ON) 256 set_power_state(state); 257 258 } 259 } 260 } 261 262 /* 263 * Run specified routine as a thread. 264 */ 265 static int 266 run_thread(void (*entry)(void)) 267 { 268 task_t self; 269 thread_t t; 270 void *stack, *sp; 271 int error; 272 273 self = task_self(); 274 if ((error = thread_create(self, &t)) != 0) 275 return error; 276 if ((error = vm_allocate(self, &stack, DFLSTKSZ, 1)) != 0) 277 return error; 278 279 sp = (void *)((u_long)stack + DFLSTKSZ - sizeof(u_long) * 3); 280 if ((error = thread_load(t, entry, sp)) != 0) 281 return error; 282 283 return thread_resume(t); 284 } 285 286 static void 287 pow_init(void) 288 { 289 task_t self; 290 291 /* 292 * Set default power actions 293 */ 294 pmact.pwrbtn = PWR_OFF; 295 pmact.slpbtn = PWR_SUSPEND; 296 pmact.lcdclose = PWR_SUSPEND; 297 pmact.lowbatt = PWR_OFF; 298 299 /* 300 * Connect to the pm driver to get all power events. 301 */ 302 if (device_open("pm", 0, &pmdev) != 0) { 303 /* 304 * Bad config... 305 */ 306 sys_panic("pow: no pm driver"); 307 } 308 self = task_self(); 309 device_ioctl(pmdev, PMIOC_CONNECT, &self); 310 311 /* 312 * Setup exception to receive signals from pm driver. 313 */ 314 exception_setup(exception_handler); 315 316 /* 317 * Start power thread. 318 */ 319 if (run_thread(power_thread)) 320 sys_panic("pow_init"); 321 } 322 323 static void 324 register_process(void) 325 { 326 struct msg m; 327 object_t obj; 328 int error; 329 330 error = object_lookup("!proc", &obj); 331 if (error) 332 sys_panic("pow: no proc found"); 333 334 m.hdr.code = PS_REGISTER; 335 msg_send(obj, &m, sizeof(m)); 336 } 337 338 /* 339 * Wait until specified server starts. 340 */ 341 static void 342 wait_server(const char *name, object_t *pobj) 343 { 344 int i, error = 0; 345 346 /* Give chance to run other servers. */ 347 thread_yield(); 348 349 /* 350 * Wait for server loading. timeout is 1 sec. 351 */ 352 for (i = 0; i < 100; i++) { 353 error = object_lookup((char *)name, pobj); 354 if (error == 0) 355 break; 356 357 /* Wait 10msec */ 358 timer_sleep(10, 0); 359 thread_yield(); 360 } 361 if (error) 362 sys_panic("pow: server not found"); 363 } 364 365 static void 366 shutdown_server(const char *name) 367 { 368 struct msg m; 369 object_t obj; 370 int error; 371 372 DPRINTF(("pow: shutdown %s\n", name)); 373 error = object_lookup((char *)name, &obj); 374 if (error != 0) 375 return; 376 377 m.hdr.code = STD_SHUTDOWN; 378 error = msg_send(obj, &m, sizeof(m)); 379 if (error) 380 sys_panic("pow: shutdown error"); 381 } 382 383 static int 384 pow_debug(struct msg *msg) 385 { 386 return 0; 387 } 388 389 /* 390 * Main routine for power server. 391 */ 392 int 393 main(int argc, char *argv[]) 394 { 395 static struct msg msg; 396 const struct msg_map *map; 397 object_t obj; 398 struct bind_msg bm; 399 object_t execobj, procobj; 400 int error; 401 402 sys_log("Starting power server\n"); 403 404 /* Boost thread priority. */ 405 thread_setpri(thread_self(), PRI_POW); 406 407 /* 408 * Wait until all required system servers 409 * become available. 410 */ 411 wait_server("!proc", &procobj); 412 wait_server("!exec", &execobj); 413 414 /* 415 * Request to bind a new capabilities for us. 416 */ 417 bm.hdr.code = EXEC_BINDCAP; 418 strlcpy(bm.path, "/boot/pow", sizeof(bm.path)); 419 msg_send(execobj, &bm, sizeof(bm)); 420 421 /* 422 * Register to process server 423 */ 424 register_process(); 425 426 /* 427 * Initialize power service. 428 */ 429 pow_init(); 430 431 /* 432 * Create an object to expose our service. 433 */ 434 error = object_create("!pow", &obj); 435 if (error) 436 sys_panic("fail to create object"); 437 438 /* 439 * Message loop 440 */ 441 for (;;) { 442 /* 443 * Wait for an incoming request. 444 */ 445 error = msg_receive(obj, &msg, sizeof(msg)); 446 if (error) 447 continue; 448 449 DPRINTF(("pow: msg code=%x task=%x\n", 450 msg.hdr.code, msg.hdr.task)); 451 452 453 /* Check client's capability. */ 454 if (task_chkcap(msg.hdr.task, CAP_POWERMGMT) != 0) { 455 map = NULL; 456 error = EPERM; 457 } else { 458 error = EINVAL; 459 map = &powermsg_map[0]; 460 while (map->code != 0) { 461 if (map->code == msg.hdr.code) { 462 error = (*map->func)(&msg); 463 break; 464 } 465 map++; 466 } 467 } 468 /* 469 * Reply to the client. 470 */ 471 msg.hdr.status = error; 472 msg_reply(obj, &msg, sizeof(msg)); 473 #ifdef DEBUG_POWER 474 if (map != NULL && error != 0) 475 DPRINTF(("pow: msg code=%x error=%d\n", 476 map->code, error)); 477 #endif 478 } 479 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |