X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=main.c;h=4a8b952d150aaa56ea9d0e36552bb966aad3fc99;hb=3a836137bd76589725e60064bc4f923ff251ba53;hp=75082ebbfc00a54305b1be2dea6c4a220ccb731a;hpb=063ae4be6676b3b6c48183e3753238b05547b124;p=pandora_liveinfo.git diff --git a/main.c b/main.c index 75082eb..4a8b952 100644 --- a/main.c +++ b/main.c @@ -7,8 +7,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -31,39 +33,40 @@ #define SCREEN_HEIGHT 480 #define WIDTH 80 #define HEIGHT 480 -#define MEM_SIZE (((WIDTH * HEIGHT * 2 * 2) + 0xfff) & ~0xfff) #define Y_STEP 9 static struct fb_var_screeninfo g_vi; static uint16_t *g_screen_base, *g_screen; +static struct { + int x, y, w, h; +} g_layer; +static unsigned int g_mem_size; static unsigned int g_old_mem; -static int g_fd, g_exit; +static int g_flip_id; +static int g_exit, g_hide; +static pthread_cond_t g_cond; +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define PAGE_ALIGN(x) (((x) + 0xfff) & ~0xfff) #define IS_START(buf, str) \ !strncmp(buf, str, sizeof(str) - 1) -static int setup_layer(void) +static void clear_bytes(void *mem, int bytes); + +static int setup_layer(int fd) { - static const char fbname[] = "/dev/fb2"; struct omapfb_plane_info pi; struct omapfb_mem_info mi; struct omapfb_color_key key; int ret; - g_fd = open(fbname, O_RDWR); - if (g_fd == -1) { - fprintf(stderr, "open %s: ", fbname); - perror(NULL); - return 1; - } - - ret = ioctl(g_fd, OMAPFB_QUERY_PLANE, &pi); + ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi); if (ret < 0) { perror("ioctl OMAPFB_QUERY_PLANE"); return 1; } - ret = ioctl(g_fd, OMAPFB_QUERY_MEM, &mi); + ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi); if (ret < 0) { perror("ioctl OMAPFB_QUERY_MEM"); return 1; @@ -72,7 +75,7 @@ static int setup_layer(void) /* must disable when changing stuff */ if (pi.enabled) { pi.enabled = 0; - ret = ioctl(g_fd, OMAPFB_SETUP_PLANE, &pi); + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); if (ret < 0) { perror("ioctl OMAPFB_SETUP_PLANE (d)"); return 1; @@ -80,44 +83,48 @@ static int setup_layer(void) } g_old_mem = mi.size; - if (mi.size < MEM_SIZE) { - mi.size = MEM_SIZE; - ret = ioctl(g_fd, OMAPFB_SETUP_MEM, &mi); + g_mem_size = PAGE_ALIGN(g_layer.w * g_layer.h * 2 * 2); + if (mi.size < g_mem_size) { + mi.size = g_mem_size; + ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); if (ret < 0) { perror("ioctl SETUP_MEM"); return 1; } } - pi.pos_x = SCREEN_WIDTH - WIDTH; - pi.pos_y = 0; - pi.out_width = WIDTH; - pi.out_height = HEIGHT; - ret = ioctl(g_fd, OMAPFB_SETUP_PLANE, &pi); + printf("layer: %d %d %d %d\n", + g_layer.x, g_layer.y, g_layer.w, g_layer.h); + + pi.pos_x = g_layer.x; + pi.pos_y = g_layer.y; + pi.out_width = g_layer.w; + pi.out_height = g_layer.h; + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); if (ret < 0) { perror("ioctl OMAPFB_SETUP_PLANE (e1)"); return 1; } - ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_vi); + ret = ioctl(fd, FBIOGET_VSCREENINFO, &g_vi); if (ret < 0) { perror("ioctl FBIOGET_VSCREENINFO"); return 1; } - g_vi.xres = g_vi.xres_virtual = WIDTH; - g_vi.yres = HEIGHT; - g_vi.yres_virtual = HEIGHT * 2; + g_vi.xres = g_vi.xres_virtual = g_layer.w; + g_vi.yres = g_layer.h; + g_vi.yres_virtual = g_layer.h * 2; g_vi.bits_per_pixel = 16; - ret = ioctl(g_fd, FBIOPUT_VSCREENINFO, &g_vi); + ret = ioctl(fd, FBIOPUT_VSCREENINFO, &g_vi); if (ret < 0) { perror("ioctl FBIOPUT_VSCREENINFO"); return 1; } pi.enabled = 1; - ret = ioctl(g_fd, OMAPFB_SETUP_PLANE, &pi); + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); if (ret < 0) { perror("ioctl OMAPFB_SETUP_PLANE (e2)"); return 1; @@ -127,21 +134,32 @@ static int setup_layer(void) key.key_type = OMAPFB_COLOR_KEY_VID_SRC; key.trans_key = 0x07e0; - ret = ioctl(g_fd, OMAPFB_SET_COLOR_KEY, &key); - if (ret < 0) { - perror("ioctl OMAPFB_SET_COLOR_KEY"); + ret = ioctl(fd, OMAPFB_SET_COLOR_KEY, &key); + if (ret < 0) { + perror("ioctl OMAPFB_SET_COLOR_KEY"); return 1; - } + } + + g_screen_base = mmap(NULL, g_mem_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (g_screen_base == MAP_FAILED) { + perror("mmap"); + g_screen = g_screen_base = NULL; + return 1; + } + clear_bytes(g_screen_base, g_mem_size); + g_screen = g_screen_base; + g_flip_id = 0; return 0; } -static int check_layer(void) +static int check_layer(int fd) { struct omapfb_plane_info pi; int ret; - ret = ioctl(g_fd, OMAPFB_QUERY_PLANE, &pi); + ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi); if (ret < 0) { perror("ioctl OMAPFB_QUERY_PLANE"); return 1; @@ -155,19 +173,24 @@ static int check_layer(void) return 0; } -static void remove_layer(void) +static void remove_layer(int fd) { struct omapfb_plane_info pi; struct omapfb_mem_info mi; int ret; + if (g_screen_base != NULL) { + munmap(g_screen_base, g_mem_size); + g_screen = g_screen_base = NULL; + } + memset(&pi, 0, sizeof(pi)); pi.enabled = 0; - ret = ioctl(g_fd, OMAPFB_SETUP_PLANE, &pi); + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); if (ret < 0) perror("ioctl OMAPFB_SETUP_PLANE (c)"); - ret = ioctl(g_fd, OMAPFB_QUERY_MEM, &mi); + ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi); if (ret < 0) { perror("ioctl OMAPFB_QUERY_MEM"); goto out; @@ -175,35 +198,159 @@ static void remove_layer(void) if (mi.size != g_old_mem) { mi.size = g_old_mem; - ret = ioctl(g_fd, OMAPFB_SETUP_MEM, &mi); + ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); if (ret < 0) { perror("ioctl SETUP_MEM"); goto out; } } -out: - close(g_fd); - g_fd = -1; +out:; } -static void handle_signal(int num) +static void flip_fb(int fd) +{ + g_vi.yoffset = g_flip_id * g_layer.h; + ioctl(fd, FBIOPAN_DISPLAY, &g_vi); + g_flip_id ^= 1; + g_screen = g_screen_base + g_flip_id * g_layer.w * g_layer.h; +} + +static void handle_term(int num) { g_exit = 1; + pthread_cond_signal(&g_cond); } -static void flip_fb(void) +static void handle_usr1(int num) { - static int id; + g_hide = !g_hide; + pthread_cond_signal(&g_cond); +} + +static struct { + char text[16]; + int idle; +} user_msgs[16]; + +static int handle_socket(int sock) +{ + char buf[256], *p; + int i, ret; + + ret = recv(sock, buf, sizeof(buf) - 1, 0); + if (ret < 0) { + perror("recv"); + return ret; + } + if (ret == 0) + return 0; + + buf[ret] = 0; + p = strchr(buf, ':'); + if (p != NULL) { + for (i = 0; i < ARRAY_SIZE(user_msgs); i++) { + if (user_msgs[i].text[0] == 0) + break; + if (!strncmp(user_msgs[i].text, buf, p - buf + 1)) + break; + } + if (i == ARRAY_SIZE(user_msgs)) { + printf("out of user_msg slots\n"); + return 0; + } + memcpy(user_msgs[i].text, buf, sizeof(user_msgs[i].text) - 1); + user_msgs[i].text[sizeof(user_msgs[i].text) - 1] = 0; + user_msgs[i].idle = 0; + } + else if (!strcmp(buf, "poke")) { + // if hidden, show up + // if visible, exit + if (g_hide) { + g_hide = 0; + return 1; + } + g_exit = 1; + return 1; + } + else if (!strcmp(buf, "hide")) { + g_hide = 1; + return 1; + } + else if (!strcmp(buf, "show")) { + g_hide = 0; + return 1; + } + else if (!strcmp(buf, "quit")) { + g_exit = 1; + return 1; + } + else { + printf("unknown command: '%s'\n", buf); + } + + return 0; +} + +static void default_config(void) +{ + g_layer.x = SCREEN_WIDTH - WIDTH; + g_layer.y = 0; + g_layer.w = WIDTH; + g_layer.h = HEIGHT; +} + +static void handle_config(void) +{ + char buf[256], *p; + int x, y, v; + FILE *f; + + default_config(); + + f = fopen("config.cfg", "r"); + if (f == NULL) + return; - g_vi.yoffset = id * HEIGHT; - ioctl(g_fd, FBIOPAN_DISPLAY, &g_vi); - id ^= 1; - g_screen = g_screen_base + id * WIDTH * HEIGHT; + while ((p = fgets(buf, sizeof(buf), f))) { + while (isspace(*p)) + p++; + if (*p == '#' || *p == ';' || *p == 0) + continue; + + if (sscanf(p, "position = %d %d", &x, &y) == 2) { + g_layer.x = x; + g_layer.y = y; + } + else { + printf("unhandled config entry: '%s'\n", p); + } + } + fclose(f); + + v = SCREEN_WIDTH - g_layer.x; + if (v <= 0) { + printf("bad x position in config: %d\n", g_layer.x); + default_config(); + return; + } + if (v < WIDTH) + g_layer.w = v; + + v = SCREEN_HEIGHT - g_layer.y; + if (v <= 0) { + printf("bad y position in config: %d\n", g_layer.y); + default_config(); + return; + } + if (v < HEIGHT) + g_layer.h = v; } -#define s_printf(x, y, fmt, ...) \ - basic_text_out16(g_screen, WIDTH, x, y, fmt, ##__VA_ARGS__); +#define s_printf(x, y, fmt, ...) do { \ + if ((y) <= g_layer.h - 8) \ + basic_text_out16(g_screen, g_layer.w, x, y, fmt, ##__VA_ARGS__); \ +} while (0) static int read_int_file(const char *fn, int *val) { @@ -222,10 +369,10 @@ static int read_int_file(const char *fn, int *val) return 0; } -static void clear(int h) +static void clear_bytes(void *mem, int bytes) { - int *p = (int *)g_screen; - int l = WIDTH * h / 2; + int *p = mem; + int l = bytes / 4; for (; l >= 4; l -= 4, p += 4) p[0] = p[1] = p[2] = p[3] = 0x07e007e0; @@ -233,6 +380,14 @@ static void clear(int h) *p = 0x07e007e0; } +static void clear(int h) +{ + if (h > g_layer.h) + h = g_layer.h; + + clear_bytes(g_screen, g_layer.w * h * 2); +} + struct proc_stat { unsigned long idlesum; unsigned long sys; @@ -645,19 +800,22 @@ static void get_netsgnl(int x, int y) int main(int argc, char *argv[]) { - static const char socket_name[] = "\0livestats"; + static const char socket_name[] = "\0liveinfo"; + static const char fbname[] = "/dev/fb2"; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_cond_t cond; pthread_condattr_t condattr; struct sockaddr_un sun; struct timespec ts; struct pollfd pfd; + const char *p; + int is_hidden = 0; int y = 0, y_max = 0; + int fd = -1; int sock; - int ret; + int i, ret; // look for other instance - sock = socket(PF_UNIX, SOCK_STREAM, 0); + sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (sock == -1) { perror("socket PF_UNIX"); return 1; @@ -669,15 +827,38 @@ int main(int argc, char *argv[]) ret = connect(sock, (struct sockaddr *)&sun, sizeof(sun)); if (ret == 0) { - printf("other instance detected, sending quit command\n"); - ret = send(sock, "quit", 4, 0); + printf("other instance detected, sending poke command\n"); + ret = send(sock, "poke", 4, 0); if (ret != 4) perror("send"); close(sock); - return 0; + return ret == 4 ? 0 : 1; } - // bind/listen for quit command + // load the config + handle_config(); + + fd = open(fbname, O_RDWR); + if (fd == -1) { + fprintf(stderr, "open %s: ", fbname); + perror(NULL); + return 1; + } + + nice(-1); + + // no need for privileges any more + p = getenv("SUDO_UID"); + if (p != NULL) { + ret = atoi(p); + if (ret != 0) { + ret = setuid(ret); + if (ret) + perror("setuid"); + } + } + + // bind/listen for commands ret = bind(sock, (struct sockaddr *)&sun, sizeof(sun)); if (ret != 0) { perror("bind"); @@ -685,43 +866,35 @@ int main(int argc, char *argv[]) return 1; } +#if 0 ret = listen(sock, 1); if (ret != 0) { perror("listen"); close(sock); return 1; } +#endif pfd.fd = sock; pfd.events = POLLIN | POLLPRI; pfd.revents = 0; - // clean up on kill too - signal(SIGTERM, handle_signal); - ret = pthread_condattr_init(&condattr); ret |= pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); - ret |= pthread_cond_init(&cond, &condattr); + ret |= pthread_cond_init(&g_cond, &condattr); pthread_condattr_destroy(&condattr); if (ret != 0) { fprintf(stderr, "cond init failed\n"); return 1; } - ret = setup_layer(); + ret = setup_layer(fd); if (ret) return ret; - g_screen_base = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, - MAP_SHARED, g_fd, 0); - if (g_screen_base == MAP_FAILED) { - perror("mmap"); - return 1; - } - g_screen = g_screen_base; - clear(HEIGHT); - flip_fb(); - clear(HEIGHT); + // clean up on kill too + signal(SIGTERM, handle_term); + signal(SIGUSR1, handle_usr1); pthread_mutex_lock(&mutex); ret = clock_gettime(CLOCK_MONOTONIC, &ts); @@ -730,10 +903,41 @@ int main(int argc, char *argv[]) return 1; } - nice(-1); init_stats(); - while (!g_exit) { + while (!g_exit) + { + // anything on unix socket? + ret = poll(&pfd, 1, 0); + if (ret < 0) { + perror("poll"); + break; + } + if (ret > 0) { + ret = handle_socket(sock); + if (ret < 0) + break; + continue; + } + + // handle hiding + if (g_hide) { + if (!is_hidden) { + remove_layer(fd); + is_hidden = 1; + } + goto do_sleep; + } + else if (is_hidden) { + ret = setup_layer(fd); + if (ret) + break; + is_hidden = 0; + } + + if (check_layer(fd) != 0) + break; + collect_stats(); y += Y_STEP; @@ -774,22 +978,34 @@ int main(int argc, char *argv[]) get_bwatts (0, y += Y_STEP); get_btemp (0, y += Y_STEP); - flip_fb(); - - if (check_layer() != 0) - break; - ret = poll(&pfd, 1, 0); - if (ret != 0) { - printf("poll returned %d\n", ret); - break; + // print user messages + y += Y_STEP; + for (i = 0; i < ARRAY_SIZE(user_msgs); i++) { + if (user_msgs[i].text[0] == 0) + break; + user_msgs[i].idle++; + if (user_msgs[i].idle > 6) { + // drop old entry, shift others up + memmove(&user_msgs[i], &user_msgs[i + 1], + (ARRAY_SIZE(user_msgs) - i - 1) * sizeof(user_msgs[0])); + user_msgs[ARRAY_SIZE(user_msgs) - 1].text[0] = 0; + // reprocess + i--; + continue; + } + + s_printf(0, y += Y_STEP, user_msgs[i].text); } + flip_fb(fd); + +do_sleep: ts.tv_sec++; - pthread_cond_timedwait(&cond, &mutex, &ts); + pthread_cond_timedwait(&g_cond, &mutex, &ts); } - munmap(g_screen_base, MEM_SIZE); - remove_layer(); + remove_layer(fd); + close(fd); close(sock); return 0;