This source file includes following definitions.
- pow_noop
- pow_set_power
- pow_get_policy
- pow_set_policy
- pow_get_sustmr
- pow_set_sustmr
- pow_get_dimtmr
- pow_set_dimtmr
- pow_battery_lvl
- set_power_state
- exception_handler
- power_thread
- run_thread
- pow_init
- register_process
- wait_server
- shutdown_server
- pow_debug
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
50
51 #ifdef DEBUG_POW
52 #define DPRINTF(a) dprintf a
53 #else
54 #define DPRINTF(a)
55 #endif
56
57
58
59
60 struct power_action {
61 int pwrbtn;
62 int slpbtn;
63 int lcdclose;
64 int lowbatt;
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
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
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
226
227 exception_wait(&sig);
228 DPRINTF(("power_thread: sig=%d\n", sig));
229
230 if (sig == SIGPWR) {
231
232
233
234 device_ioctl(pmdev, PMIOC_QUERY_EVENT, &event);
235 DPRINTF(("power_thread: event=%d\n", event));
236
237
238
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
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
293
294 pmact.pwrbtn = PWR_OFF;
295 pmact.slpbtn = PWR_SUSPEND;
296 pmact.lcdclose = PWR_SUSPEND;
297 pmact.lowbatt = PWR_OFF;
298
299
300
301
302 if (device_open("pm", 0, &pmdev) != 0) {
303
304
305
306 sys_panic("pow: no pm driver");
307 }
308 self = task_self();
309 device_ioctl(pmdev, PMIOC_CONNECT, &self);
310
311
312
313
314 exception_setup(exception_handler);
315
316
317
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
340
341 static void
342 wait_server(const char *name, object_t *pobj)
343 {
344 int i, error = 0;
345
346
347 thread_yield();
348
349
350
351
352 for (i = 0; i < 100; i++) {
353 error = object_lookup((char *)name, pobj);
354 if (error == 0)
355 break;
356
357
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
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
405 thread_setpri(thread_self(), PRI_POW);
406
407
408
409
410
411 wait_server("!proc", &procobj);
412 wait_server("!exec", &execobj);
413
414
415
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
423
424 register_process();
425
426
427
428
429 pow_init();
430
431
432
433
434 error = object_create("!pow", &obj);
435 if (error)
436 sys_panic("fail to create object");
437
438
439
440
441 for (;;) {
442
443
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
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
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 }
|