priv drop, hide on USR1 signal
[pandora_liveinfo.git] / main.c
CommitLineData
063ae4be 1/*
2 * pandora live info
3 * (C) notaz, 2014
4 *
5 * This work is licensed under the terms of 3-clause BSD license.
6 * See COPYING file in the top-level directory.
7 */
8
9#include <stdio.h>
15f42220 10#include <stdlib.h>
063ae4be 11#include <string.h>
12#include <stdarg.h>
13#include <pthread.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <fcntl.h>
17#include <sys/ioctl.h>
18#include <sys/mman.h>
19#include <unistd.h>
20#include <sys/time.h>
21#include <time.h>
22#include <sys/socket.h>
23#include <sys/un.h>
24#include <signal.h>
25#include <poll.h>
26#include <linux/fb.h>
27#include <linux/omapfb.h>
28#include <stdint.h>
29#include "fonts.h"
30
31#define SCREEN_WIDTH 800
32#define SCREEN_HEIGHT 480
33#define WIDTH 80
34#define HEIGHT 480
35#define MEM_SIZE (((WIDTH * HEIGHT * 2 * 2) + 0xfff) & ~0xfff)
36#define Y_STEP 9
37
38static struct fb_var_screeninfo g_vi;
39static uint16_t *g_screen_base, *g_screen;
40static unsigned int g_old_mem;
15f42220 41static int g_flip_id;
42static int g_exit, g_hide;
43static pthread_cond_t g_cond;
063ae4be 44
45#define IS_START(buf, str) \
46 !strncmp(buf, str, sizeof(str) - 1)
47
15f42220 48static void clear_bytes(void *mem, int bytes);
49
50static int setup_layer(int fd)
063ae4be 51{
063ae4be 52 struct omapfb_plane_info pi;
53 struct omapfb_mem_info mi;
54 struct omapfb_color_key key;
55 int ret;
56
15f42220 57 ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
063ae4be 58 if (ret < 0) {
59 perror("ioctl OMAPFB_QUERY_PLANE");
60 return 1;
61 }
62
15f42220 63 ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
063ae4be 64 if (ret < 0) {
65 perror("ioctl OMAPFB_QUERY_MEM");
66 return 1;
67 }
68
69 /* must disable when changing stuff */
70 if (pi.enabled) {
71 pi.enabled = 0;
15f42220 72 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
063ae4be 73 if (ret < 0) {
74 perror("ioctl OMAPFB_SETUP_PLANE (d)");
75 return 1;
76 }
77 }
78
79 g_old_mem = mi.size;
80 if (mi.size < MEM_SIZE) {
81 mi.size = MEM_SIZE;
15f42220 82 ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
063ae4be 83 if (ret < 0) {
84 perror("ioctl SETUP_MEM");
85 return 1;
86 }
87 }
88
89 pi.pos_x = SCREEN_WIDTH - WIDTH;
90 pi.pos_y = 0;
91 pi.out_width = WIDTH;
92 pi.out_height = HEIGHT;
15f42220 93 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
063ae4be 94 if (ret < 0) {
95 perror("ioctl OMAPFB_SETUP_PLANE (e1)");
96 return 1;
97 }
98
15f42220 99 ret = ioctl(fd, FBIOGET_VSCREENINFO, &g_vi);
063ae4be 100 if (ret < 0) {
101 perror("ioctl FBIOGET_VSCREENINFO");
102 return 1;
103 }
104
105 g_vi.xres = g_vi.xres_virtual = WIDTH;
106 g_vi.yres = HEIGHT;
107 g_vi.yres_virtual = HEIGHT * 2;
108 g_vi.bits_per_pixel = 16;
109
15f42220 110 ret = ioctl(fd, FBIOPUT_VSCREENINFO, &g_vi);
063ae4be 111 if (ret < 0) {
112 perror("ioctl FBIOPUT_VSCREENINFO");
113 return 1;
114 }
115
116 pi.enabled = 1;
15f42220 117 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
063ae4be 118 if (ret < 0) {
119 perror("ioctl OMAPFB_SETUP_PLANE (e2)");
120 return 1;
121 }
122
123 memset(&key, 0, sizeof(key));
124 key.key_type = OMAPFB_COLOR_KEY_VID_SRC;
125 key.trans_key = 0x07e0;
126
15f42220 127 ret = ioctl(fd, OMAPFB_SET_COLOR_KEY, &key);
128 if (ret < 0) {
129 perror("ioctl OMAPFB_SET_COLOR_KEY");
063ae4be 130 return 1;
15f42220 131 }
132
133 g_screen_base = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE,
134 MAP_SHARED, fd, 0);
135 if (g_screen_base == MAP_FAILED) {
136 perror("mmap");
137 g_screen = g_screen_base = NULL;
138 return 1;
139 }
140 clear_bytes(g_screen_base, MEM_SIZE);
141 g_screen = g_screen_base;
142 g_flip_id = 0;
063ae4be 143
144 return 0;
145}
146
15f42220 147static int check_layer(int fd)
063ae4be 148{
149 struct omapfb_plane_info pi;
150 int ret;
151
15f42220 152 ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
063ae4be 153 if (ret < 0) {
154 perror("ioctl OMAPFB_QUERY_PLANE");
155 return 1;
156 }
157
158 if (!pi.enabled) {
159 printf("something disabled the layer (tv-out?), quitting\n");
160 return 1;
161 }
162
163 return 0;
164}
165
15f42220 166static void remove_layer(int fd)
063ae4be 167{
168 struct omapfb_plane_info pi;
169 struct omapfb_mem_info mi;
170 int ret;
171
15f42220 172 if (g_screen_base != NULL) {
173 munmap(g_screen_base, MEM_SIZE);
174 g_screen = g_screen_base = NULL;
175 }
176
063ae4be 177 memset(&pi, 0, sizeof(pi));
178 pi.enabled = 0;
15f42220 179 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
063ae4be 180 if (ret < 0)
181 perror("ioctl OMAPFB_SETUP_PLANE (c)");
182
15f42220 183 ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
063ae4be 184 if (ret < 0) {
185 perror("ioctl OMAPFB_QUERY_MEM");
186 goto out;
187 }
188
189 if (mi.size != g_old_mem) {
190 mi.size = g_old_mem;
15f42220 191 ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
063ae4be 192 if (ret < 0) {
193 perror("ioctl SETUP_MEM");
194 goto out;
195 }
196 }
197
15f42220 198out:;
063ae4be 199}
200
15f42220 201static void flip_fb(int fd)
063ae4be 202{
15f42220 203 g_vi.yoffset = g_flip_id * HEIGHT;
204 ioctl(fd, FBIOPAN_DISPLAY, &g_vi);
205 g_flip_id ^= 1;
206 g_screen = g_screen_base + g_flip_id * WIDTH * HEIGHT;
063ae4be 207}
208
15f42220 209static void handle_term(int num)
063ae4be 210{
15f42220 211 g_exit = 1;
212 pthread_cond_signal(&g_cond);
213}
063ae4be 214
15f42220 215static void handle_usr1(int num)
216{
217 g_hide = !g_hide;
218 pthread_cond_signal(&g_cond);
063ae4be 219}
220
221#define s_printf(x, y, fmt, ...) \
222 basic_text_out16(g_screen, WIDTH, x, y, fmt, ##__VA_ARGS__);
223
224static int read_int_file(const char *fn, int *val)
225{
226 FILE *f;
227 int ret;
228
229 *val = 0;
230 f = fopen(fn, "r");
231 if (f == NULL)
232 return 1;
233 ret = fscanf(f, "%d", val);
234 fclose(f);
235 if (ret != 1)
236 return 1;
237
238 return 0;
239}
240
15f42220 241static void clear_bytes(void *mem, int bytes)
063ae4be 242{
15f42220 243 int *p = mem;
244 int l = bytes / 4;
063ae4be 245
246 for (; l >= 4; l -= 4, p += 4)
247 p[0] = p[1] = p[2] = p[3] = 0x07e007e0;
248 for (; l > 0; l--, p++)
249 *p = 0x07e007e0;
250}
251
15f42220 252static void clear(int h)
253{
254 clear_bytes(g_screen, WIDTH * h * 2);
255}
256
063ae4be 257struct proc_stat {
258 unsigned long idlesum;
259 unsigned long sys;
260 unsigned long irqs;
261 unsigned long ctxt;
262};
263
264static struct {
265 struct proc_stat last_st;
266 int cpu_usage;
267 int cpu_sys;
268 int irqs;
269 int ctxt;
270 int mem_free;
271 int mem_huge;
272 int mem_free_swap;
273} stats;
274
275static void collect_proc_stat(void)
276{
277 static long hz;
278 struct proc_stat st;
279 char buf[256];
280 unsigned long wait;
281 unsigned long iowait;
282 FILE *f;
283
284 if (hz == 0) {
285 hz = sysconf(_SC_CLK_TCK);
286 printf("hz: %ld\n", hz);
287 }
288
289 f = fopen("/proc/stat", "r");
290 if (f == NULL)
291 return;
292
293 if (fscanf(f, "cpu %*s %*s %lu %lu %lu",
294 &st.sys, &wait, &iowait) != 3)
295 goto out;
296 do {
297 if (fgets(buf, sizeof(buf), f) == NULL)
298 goto out;
299 } while (fscanf(f, "intr %lu", &st.irqs) != 1);
300 do {
301 if (fgets(buf, sizeof(buf), f) == NULL)
302 goto out;
303 } while (fscanf(f, "ctxt %lu", &st.ctxt) != 1);
304
305 st.idlesum = wait + iowait;
306
307 stats.cpu_usage = hz - (st.idlesum - stats.last_st.idlesum);
308 stats.cpu_sys = st.sys - stats.last_st.sys;
309 if (hz != 100) {
310 stats.cpu_usage = stats.cpu_usage * 100 / hz;
311 stats.cpu_sys = stats.cpu_sys * 100 / hz;
312 }
313 stats.irqs = st.irqs - stats.last_st.irqs;
314 stats.ctxt = st.ctxt - stats.last_st.ctxt;
315
316out:
317 stats.last_st = st;
318 fclose(f);
319}
320
321static void collect_mem_stat(void)
322{
323 static const char fn[] = "/proc/meminfo";
324 uint32_t total = 0, free = 0, buffers = 0, cached = 0;
325 uint32_t anonhuge = 0, hugetot = 0, hugefree = 0, hugepgsz = 0;
326 uint32_t free_swap = 0;
327 char buf[128];
328 FILE *f;
329
330 f = fopen(fn, "r");
331 if (f == NULL)
332 return;
333
334 while (fgets(buf, sizeof(buf), f)) {
335 if (total == 0 && sscanf(buf, "MemTotal: %u", &total) == 1)
336 continue;
337 if (free == 0 && sscanf(buf, "MemFree: %u", &free) == 1)
338 continue;
339 if (buffers == 0 && sscanf(buf, "Buffers: %u", &buffers) == 1)
340 continue;
341 if (cached == 0 && sscanf(buf, "Cached: %u", &cached) == 1)
342 continue;
343 if (free_swap == 0 && sscanf(buf, "SwapFree: %u", &free_swap) == 1)
344 continue;
345 if (anonhuge == 0 && sscanf(buf, "AnonHugePages: %u", &anonhuge) == 1)
346 continue;
347 if (hugetot == 0 && sscanf(buf, "HugePages_Total: %u", &hugetot) == 1)
348 continue;
349 if (hugefree == 0 && sscanf(buf, "HugePages_Free: %u", &hugefree) == 1)
350 continue;
351 if (hugepgsz == 0 && sscanf(buf, "Hugepagesize: %u", &hugepgsz) == 1)
352 continue;
353 }
354
355 fclose(f);
356
357 hugetot = (hugetot - hugefree) * hugepgsz;
358 free += buffers + cached;
359 stats.mem_free = free >> 10;
360 stats.mem_huge = hugetot >> 10;
361 stats.mem_free_swap = free_swap >> 10;
362}
363
364struct io_stat {
365 unsigned long sec_r;
366 unsigned long sec_w;
367};
368
369static struct {
370 struct io_stat last_st;
371 int read; // kB/s
372 int write;
373} io_stats;
374
375static void collect_io_stat(void)
376{
377 unsigned long sec_r, sec_w;
378 struct io_stat st = { 0, };
379 char buf[128];
380 FILE *f;
381 int i;
382
383 for (i = 0; i < 2; i++) {
384 snprintf(buf, sizeof(buf), "/sys/block/mmcblk%d/stat", i);
385 f = fopen(buf, "r");
386 if (f == NULL)
387 continue;
388
389 if (fscanf(f, "%*s %*s %lu %*s %*s %*s %lu",
390 &sec_r, &sec_w) == 2)
391 {
392 st.sec_r += sec_r;
393 st.sec_w += sec_w;
394 }
395 fclose(f);
396 }
397
398 io_stats.read = st.sec_r - io_stats.last_st.sec_r;
399 io_stats.write = st.sec_w - io_stats.last_st.sec_w;
400 // assuming 512 byte sectors..
401 io_stats.read >>= 1;
402 io_stats.write >>= 1;
403
404 io_stats.last_st = st;
405}
406
407struct net_stat {
408 unsigned long rx;
409 unsigned long tx;
410};
411
412static struct {
413 struct net_stat last_st;
414 int down; // kB/s
415 int up;
416 int have_wlan;
417 int link;
418 int level;
419} net_stats;
420
421static void collect_net_stat(void)
422{
423 struct net_stat st = { 0, };
424 unsigned long rx, tx;
425 int found = 0;
426 char buf[256];
427 FILE *f;
428
429 net_stats.down = net_stats.up =
430 net_stats.have_wlan = net_stats.link = net_stats.level = 0;
431
432 f = fopen("/proc/net/dev", "r");
433 if (f == NULL)
434 return;
435
436 while (!feof(f)) {
437 static const char fmt[] =
438 "%255s %lu %*s %*s %*s %*s %*s %*s %lu";
439 if (fscanf(f, fmt, buf, &rx, &tx) != 3)
440 continue;
441 if (IS_START(buf, "lo"))
442 continue;
443 st.rx += rx;
444 st.tx += tx;
445 found = 1;
446 }
447 fclose(f);
448
449 if (found) {
450 net_stats.down = st.rx - net_stats.last_st.rx;
451 net_stats.up = st.tx - net_stats.last_st.tx;
452 }
453 net_stats.last_st = st;
454
455 f = fopen("/proc/net/wireless", "r");
456 if (f == NULL)
457 return;
458
459 while (!feof(f)) {
460 int lnk, lvl;
461 if (fscanf(f, "%255s %*x %d. %d.", buf, &lnk, &lvl) != 3)
462 continue;
463 if (IS_START(buf, "lo"))
464 continue;
465 // first one should be enough
466 net_stats.have_wlan = 1;
467 net_stats.link = lnk;
468 net_stats.level = lvl;
469 break;
470 }
471 fclose(f);
472}
473
474static void collect_stats(void)
475{
476 collect_proc_stat();
477 collect_mem_stat();
478 collect_io_stat();
479 collect_net_stat();
480}
481
482static char cpu_reg_path[64];
483
484static void init_stats(void)
485{
486 char buf[64];
487 int found;
488 FILE *f;
489 int i;
490
491 // find the CPU regulator
492 for (i = found = 0; ; i++) {
493 snprintf(buf, sizeof(buf),
494 "/sys/class/regulator/regulator.%d/name", i);
495 f = fopen(buf, "r");
496 if (f == NULL)
497 break;
498 fgets(buf, sizeof(buf), f);
499 fclose(f);
500 if (IS_START(buf, "vdd_mpu")) {
501 found = 1;
502 break;
503 }
504 }
505
506 if (found)
507 snprintf(cpu_reg_path, sizeof(cpu_reg_path),
508 "/sys/class/regulator/regulator.%d/microvolts", i);
509
510 // do collect so differential stats get sane values
511 collect_stats();
512}
513
514static void get_time(int x, int y)
515{
516 struct timeval tv;
517 struct tm *t;
518 char buf[16];
519
520 gettimeofday(&tv, NULL);
521 t = localtime(&tv.tv_sec);
522 strftime(buf, sizeof(buf), "%T", t);
523 s_printf(x, y, " %s", buf);
524}
525
526static void get_cpu(int x, int y)
527{
528 s_printf(x, y, "CPU:%5d%%", stats.cpu_usage);
529}
530
531static void get_sys(int x, int y)
532{
533 s_printf(x, y, "SYS:%5d%%", stats.cpu_sys);
534}
535
536static void get_irq(int x, int y)
537{
538 s_printf(x, y, "IRQ:%5u", stats.irqs);
539}
540
541static void get_cs(int x, int y)
542{
543 s_printf(x, y, "CS:%6u", stats.ctxt);
544}
545
546static void get_cpuf(int x, int y)
547{
548 static const char fn[] =
549 "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq";
550 int f;
551
552 if (read_int_file(fn, &f))
553 return;
554 s_printf(x, y, "f:%7dM", f / 1000);
555}
556
557static void get_cpuv(int x, int y)
558{
559 int v = 0;
560
561 if (!cpu_reg_path[0] || read_int_file(cpu_reg_path, &v))
562 return;
563 s_printf(x, y, "V:%7.3fV", (float)v / 1000000.0f);
564}
565
566static void get_memfree(int x, int y)
567{
568 s_printf(x, y, "M:%7dM", stats.mem_free);
569}
570
571static void get_memhuge(int x, int y)
572{
573 s_printf(x, y, "H:%7dM", stats.mem_huge);
574}
575
576static void get_memswap(int x, int y)
577{
578 s_printf(x, y, "S:%7dM", stats.mem_free_swap);
579}
580
581#define PS_BASE "/sys/class/power_supply/bq27500-0/"
582
583static void get_bcap(int x, int y)
584{
585 static const char fnc[] = PS_BASE "capacity";
586 int c;
587
588 if (read_int_file(fnc, &c))
589 return;
590 s_printf(x, y, "C:%7d%%", c);
591}
592
593static void get_btime(int x, int y)
594{
595 static const char fne[] = PS_BASE "time_to_empty_now";
596 static const char fnf[] = PS_BASE "time_to_full_now";
597 int t = 0;
598
599 if (read_int_file(fne, &t) || t == 0) {
600 if (read_int_file(fnf, &t))
601 return;
602 }
603 s_printf(x, y, "t:%4d:%02d", t / 3600, t / 60 % 60);
604}
605
606static void get_bvolts(int x, int y)
607{
608 static const char fnv[] = PS_BASE "voltage_now";
609 int volt = 0;
610
611 if (read_int_file(fnv, &volt))
612 return;
613
614 s_printf(x, y, "V:%7.3fV", (float)volt / 1000000.0f);
615}
616
617static void get_bwatts(int x, int y)
618{
619 static const char fnc[] = PS_BASE "current_now";
620 static const char fnv[] = PS_BASE "voltage_now";
621 int w, cur = 0, volt = 0;
622
623 if (read_int_file(fnc, &cur))
624 return;
625 if (read_int_file(fnv, &volt))
626 return;
627
628 w = (cur / 1000) * (volt / 1000);
629 s_printf(x, y, "P:%7.3fW", (float)w / 1000000.0f);
630}
631
632static void get_btemp(int x, int y)
633{
634 static const char fnt[] = PS_BASE "temp";
635 int t;
636
637 if (read_int_file(fnt, &t))
638 return;
639 s_printf(x, y, "T:%7.1fC", (float)t / 10.0f);
640}
641
642static void get_ioread(int x, int y)
643{
644 s_printf(x, y, "R:%5.1fM/s", (float)io_stats.read / 1000.0f);
645}
646
647static void get_iowrite(int x, int y)
648{
649 s_printf(x, y, "W:%5.1fM/s", (float)io_stats.write / 1000.0f);
650}
651
652static void get_netdown(int x, int y)
653{
654 s_printf(x, y, "D:%5uK/s", net_stats.down / 1000);
655}
656
657static void get_netup(int x, int y)
658{
659 s_printf(x, y, "U:%5uK/s", net_stats.up / 1000);
660}
661
662static void get_netsgnl(int x, int y)
663{
664 s_printf(x, y, "S:%5ddBm", net_stats.level);
665}
666
667int main(int argc, char *argv[])
668{
15f42220 669 static const char socket_name[] = "\0liveinfo";
670 static const char fbname[] = "/dev/fb2";
063ae4be 671 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
063ae4be 672 pthread_condattr_t condattr;
673 struct sockaddr_un sun;
674 struct timespec ts;
675 struct pollfd pfd;
15f42220 676 const char *p;
677 int is_hidden = 0;
063ae4be 678 int y = 0, y_max = 0;
15f42220 679 int fd = -1;
063ae4be 680 int sock;
681 int ret;
682
683 // look for other instance
684 sock = socket(PF_UNIX, SOCK_STREAM, 0);
685 if (sock == -1) {
686 perror("socket PF_UNIX");
687 return 1;
688 }
689
690 memset(&sun, 0, sizeof(sun));
691 sun.sun_family = AF_UNIX;
692 memcpy(sun.sun_path, socket_name, sizeof(socket_name));
693
694 ret = connect(sock, (struct sockaddr *)&sun, sizeof(sun));
695 if (ret == 0) {
15f42220 696 printf("other instance detected, sending poke command\n");
697 ret = send(sock, "poke", 5, 0);
698 if (ret != 5)
063ae4be 699 perror("send");
700 close(sock);
15f42220 701 return ret == 5 ? 0 : 1;
702 }
703
704 fd = open(fbname, O_RDWR);
705 if (fd == -1) {
706 fprintf(stderr, "open %s: ", fbname);
707 perror(NULL);
708 return 1;
063ae4be 709 }
710
15f42220 711 nice(-1);
712
713 // no need for privileges any more
714 p = getenv("SUDO_UID");
715 if (p != NULL) {
716 ret = atoi(p);
717 if (ret != 0) {
718 ret = setuid(ret);
719 if (ret)
720 perror("setuid");
721 }
722 }
723
724 // bind/listen for commands
063ae4be 725 ret = bind(sock, (struct sockaddr *)&sun, sizeof(sun));
726 if (ret != 0) {
727 perror("bind");
728 close(sock);
729 return 1;
730 }
731
732 ret = listen(sock, 1);
733 if (ret != 0) {
734 perror("listen");
735 close(sock);
736 return 1;
737 }
738
739 pfd.fd = sock;
740 pfd.events = POLLIN | POLLPRI;
741 pfd.revents = 0;
742
063ae4be 743 ret = pthread_condattr_init(&condattr);
744 ret |= pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
15f42220 745 ret |= pthread_cond_init(&g_cond, &condattr);
063ae4be 746 pthread_condattr_destroy(&condattr);
747 if (ret != 0) {
748 fprintf(stderr, "cond init failed\n");
749 return 1;
750 }
751
15f42220 752 ret = setup_layer(fd);
063ae4be 753 if (ret)
754 return ret;
755
15f42220 756 // clean up on kill too
757 signal(SIGTERM, handle_term);
758 signal(SIGUSR1, handle_usr1);
063ae4be 759
760 pthread_mutex_lock(&mutex);
761 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
762 if (ret != 0) {
763 perror("clock_gettime CLOCK_MONOTONIC");
764 return 1;
765 }
766
063ae4be 767 init_stats();
768
15f42220 769 while (!g_exit)
770 {
771 // handle hiding
772 if (g_hide) {
773 if (!is_hidden) {
774 remove_layer(fd);
775 is_hidden = 1;
776 }
777 goto do_sleep;
778 }
779 else if (is_hidden) {
780 ret = setup_layer(fd);
781 if (ret)
782 break;
783 is_hidden = 0;
784 }
785
063ae4be 786 collect_stats();
787
788 y += Y_STEP;
789 if (y > y_max)
790 y_max = y;
791 clear(y_max);
792
793 y = 0;
794 get_time (0, y += Y_STEP);
795 y += Y_STEP / 2;
796 get_cpu (0, y += Y_STEP);
797 get_sys (0, y += Y_STEP);
798 get_irq (0, y += Y_STEP);
799 get_cs (0, y += Y_STEP);
800 get_cpuf (0, y += Y_STEP);
801 get_cpuv (0, y += Y_STEP);
802 y += Y_STEP / 2;
803 s_printf(0, y += Y_STEP, "mem");
804 get_memfree(0, y += Y_STEP);
805 get_memswap(0, y += Y_STEP);
806 if (stats.mem_huge)
807 get_memhuge(0, y += Y_STEP);
808 y += Y_STEP / 2;
809 s_printf(0, y += Y_STEP, "i/o");
810 get_ioread (0, y += Y_STEP);
811 get_iowrite(0, y += Y_STEP);
812 y += Y_STEP / 2;
813 s_printf(0, y += Y_STEP, "net");
814 get_netdown(0, y += Y_STEP);
815 get_netup (0, y += Y_STEP);
816 if (net_stats.have_wlan)
817 get_netsgnl(0, y += Y_STEP);
818 y += Y_STEP / 2;
819 s_printf(0, y += Y_STEP, "batt");
820 get_bcap (0, y += Y_STEP);
821 get_btime (0, y += Y_STEP);
822 get_bvolts (0, y += Y_STEP);
823 get_bwatts (0, y += Y_STEP);
824 get_btemp (0, y += Y_STEP);
825
15f42220 826 flip_fb(fd);
063ae4be 827
15f42220 828 if (check_layer(fd) != 0)
063ae4be 829 break;
15f42220 830
831 // anything on unix socket?
063ae4be 832 ret = poll(&pfd, 1, 0);
833 if (ret != 0) {
834 printf("poll returned %d\n", ret);
835 break;
836 }
837
15f42220 838do_sleep:
063ae4be 839 ts.tv_sec++;
15f42220 840 pthread_cond_timedwait(&g_cond, &mutex, &ts);
063ae4be 841 }
842
15f42220 843 remove_layer(fd);
844 close(fd);
063ae4be 845 close(sock);
846
847 return 0;
848}
849
850// vim:expandtab:sw=2:ts=2