HIDDEN int mem_poll(FBIO *ifp) { if (MI(ifp)->write_thru) { return fb_poll(MI(ifp)->fbp); } return 0; }
static void sigalarm(int UNUSED(code)) { printf("alarm %s\n", fb_server_fbp ? "FBP" : "NULL"); if ( fb_server_fbp != FB_NULL ) { fb_poll(fb_server_fbp); } #ifdef SIGALRM (void)signal( SIGALRM, sigalarm ); /* some systems remove handler */ #endif alarm(1); }
/* * Loop forever handling clients as they come and go. * Access to the framebuffer may be interleaved, if the user * wants it that way. */ static void main_loop(void) { int nopens = 0; int ncloses = 0; while ( !fb_server_got_fb_free ) { long refresh_rate = 60000000; /* old default */ fd_set infds; struct timeval tv; int i; if (fb_server_fbp) { if (fb_poll_rate(fb_server_fbp) > 0) refresh_rate = fb_poll_rate(fb_server_fbp); } infds = select_list; /* struct copy */ tv.tv_sec = 0L; tv.tv_usec = refresh_rate; if ((select( max_fd+1, &infds, (fd_set *)0, (fd_set *)0, (struct timeval *)&tv ) == 0)) { /* Process fb events while waiting for client */ /*printf("select timeout waiting for client\n");*/ if (fb_server_fbp) { if (fb_poll(fb_server_fbp)) { return; } } continue; } /* Handle any events from the framebuffer */ if (fb_is_set_fd(fb_server_fbp, &infds)) { fb_poll(fb_server_fbp); } /* Accept any new client connections */ if (netfd > 0 && FD_ISSET(netfd, &infds)) { new_client( pkg_getclient( netfd, fb_server_pkg_switch, comm_error, 0 ) ); nopens++; } /* Process arrivals from existing clients */ /* First, pull the data out of the kernel buffers */ for (i = MAX_CLIENTS-1; i >= 0; i--) { if (clients[i] == NULL ) continue; if (pkg_process( clients[i] ) < 0) { fprintf(stderr, "pkg_process error encountered (1)\n"); } if (! FD_ISSET( clients[i]->pkc_fd, &infds )) continue; if (pkg_suckin( clients[i] ) <= 0) { /* Probably EOF */ drop_client( i ); ncloses++; continue; } } /* Second, process all the finished ones that we just got */ for (i = MAX_CLIENTS-1; i >= 0; i--) { if (clients[i] == NULL ) continue; if (pkg_process( clients[i] ) < 0) { fprintf(stderr, "pkg_process error encountered (2)\n"); } } if (once_only && nopens > 1 && ncloses > 1) return; } }
static void fb_wait(GP_Backend *self) { struct fb_priv *fb = GP_BACKEND_PRIV(self); struct pollfd fd = {.fd = fb->con_fd, .events = POLLIN, .revents = 0}; if (poll(&fd, 1, -1) > 0) fb_poll(self); else GP_WARN("poll(): %s", strerror(errno)); } static void fb_exit(GP_Backend *self) { struct fb_priv *fb = GP_BACKEND_PRIV(self); /* unmap framebuffer */ munmap(fb->context.pixels, fb->bsize); close(fb->fb_fd); /* reset keyboard */ ioctl(fb->con_fd, KDSETMODE, KD_TEXT); /* restore keyboard mode */ if (fb->flag) { if (ioctl(fb->con_fd, KDSKBMODE, fb->saved_kb_mode) < 0) { GP_DEBUG(1, "Failed to ioctl KDSKBMODE (restore KBMODE)" " /dev/tty%i: %s", fb->con_nr, strerror(errno)); } } /* switch back console */ if (fb->last_con_nr != -1) ioctl(fb->con_fd, VT_ACTIVATE, fb->last_con_nr); close(fb->con_fd); free(self); } GP_Backend *GP_BackendLinuxFBInit(const char *path, int flag) { GP_Backend *backend; struct fb_priv *fb; struct fb_fix_screeninfo fscri; struct fb_var_screeninfo vscri; int fd; backend = malloc(sizeof(GP_Backend) + sizeof(struct fb_priv) + strlen(path) + 1); if (backend == NULL) return NULL; fb = GP_BACKEND_PRIV(backend); if (allocate_console(fb, flag)) goto err1; /* open and mmap framebuffer */ GP_DEBUG(1, "Opening framebuffer '%s'", path); fd = open(path, O_RDWR); if (fd < 0) { GP_DEBUG(1, "Opening framebuffer failed: %s", strerror(errno)); goto err2; } if (ioctl(fd, FBIOGET_FSCREENINFO, &fscri) < 0) { GP_DEBUG(1, "Failed to ioctl FBIOGET_FSCREENINFO: %s", strerror(errno)); goto err3; } if (ioctl(fd, FBIOGET_VSCREENINFO, &vscri) < 0) { GP_DEBUG(1, "Failed to ioctl FBIOGET_VSCREENINFO: %s", strerror(errno)); goto err3; } GP_DEBUG(1, "Have framebufer %ix%i %s %ibpp", vscri.xres, vscri.yres, vscri.grayscale ? "Gray" : "RGB", vscri.bits_per_pixel); /* * Framebuffer is grayscale. */ if (vscri.grayscale) { //TODO goto err3; } enum GP_PixelType pixel_type; pixel_type = GP_PixelRGBLookup(vscri.red.length, vscri.red.offset, vscri.green.length, vscri.green.offset, vscri.blue.length, vscri.blue.offset, vscri.transp.length, vscri.transp.offset, vscri.bits_per_pixel); if (pixel_type == GP_PIXEL_UNKNOWN) { GP_DEBUG(1, "Unknown pixel type\n"); goto err3; } fb->context.pixels = mmap(NULL, fscri.smem_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); if (fb->context.pixels == MAP_FAILED) { GP_DEBUG(1, "mmaping framebuffer failed: %s", strerror(errno)); goto err3; } fb->fb_fd = fd; fb->bsize = fscri.smem_len; strcpy(fb->path, path); fb->flag = flag; fb->context.w = vscri.xres; fb->context.h = vscri.yres; fb->context.axes_swap = 0; fb->context.x_swap = 0; fb->context.y_swap = 0; fb->context.bpp = vscri.bits_per_pixel; fb->context.bytes_per_row = fscri.line_length; fb->context.pixel_type = pixel_type; /* update API */ backend->name = "Linux FB"; backend->context = &fb->context; backend->Flip = NULL; backend->UpdateRect = NULL; backend->Exit = fb_exit; backend->SetAttributes = NULL; backend->ResizeAck = NULL; backend->Poll = flag ? fb_poll : NULL; backend->Wait = flag ? fb_wait : NULL; backend->fd = fb->con_fd; backend->timers = NULL; GP_EventQueueInit(&backend->event_queue, vscri.xres, vscri.yres, 0); return backend; err3: close(fd); err2: close(fb->con_fd); /* reset keyboard */ ioctl(fb->con_fd, KDSETMODE, KD_TEXT); /* switch back console */ if (fb->last_con_nr != -1) ioctl(fb->con_fd, VT_ACTIVATE, fb->last_con_nr); err1: free(backend); return NULL; }
static void fb_wait(GP_Backend *self) { struct fb_priv *fb = GP_BACKEND_PRIV(self); struct pollfd fd = {.fd = fb->con_fd, .events = POLLIN, .revents = 0}; if (poll(&fd, 1, -1) > 0) fb_poll(self); else GP_WARN("poll(): %s", strerror(errno)); } static void fb_exit(GP_Backend *self) { struct fb_priv *fb = GP_BACKEND_PRIV(self); if (fb->flags & GP_FB_SHADOW) free(fb->context.pixels); /* unmap framebuffer */ munmap(fb->fb_mem, fb->bsize); close(fb->fb_fd); if (fb->flags & GP_FB_INPUT_KBD) exit_kbd(fb); free_console(fb); free(self); } static void fb_flip_shadow(GP_Backend *self) { struct fb_priv *fb = GP_BACKEND_PRIV(self); GP_DEBUG(2, "Flipping buffer"); memcpy(fb->fb_mem, fb->context.pixels, fb->bsize); } static void fb_update_rect_shadow(GP_Backend *self, GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1) { struct fb_priv *fb = GP_BACKEND_PRIV(self); GP_DEBUG(2, "Flipping buffer"); size_t size = ((x1 - x0) * fb->context.bpp) / 8; for (;y0 <= y1; y0++) { void *src = GP_PIXEL_ADDR(&fb->context, x0, y0); void *dst = (char*)fb->fb_mem + y0 * fb->context.bytes_per_row + (x0 * fb->context.bpp)/8; memcpy(dst, src, size); } } GP_Backend *GP_BackendLinuxFBInit(const char *path, int flags) { GP_Backend *backend; struct fb_priv *fb; struct fb_fix_screeninfo fscri; struct fb_var_screeninfo vscri; int fd; backend = malloc(sizeof(GP_Backend) + sizeof(struct fb_priv) + strlen(path) + 1); if (backend == NULL) return NULL; fb = GP_BACKEND_PRIV(backend); if (allocate_console(fb, flags)) goto err0; if (flags & GP_FB_INPUT_KBD) { if (init_kbd(fb)) goto err1; } /* open and mmap framebuffer */ GP_DEBUG(1, "Opening framebuffer '%s'", path); fd = open(path, O_RDWR); if (fd < 0) { GP_DEBUG(1, "Opening framebuffer failed: %s", strerror(errno)); goto err2; } if (ioctl(fd, FBIOGET_FSCREENINFO, &fscri) < 0) { GP_DEBUG(1, "Failed to ioctl FBIOGET_FSCREENINFO: %s", strerror(errno)); goto err3; } if (ioctl(fd, FBIOGET_VSCREENINFO, &vscri) < 0) { GP_DEBUG(1, "Failed to ioctl FBIOGET_VSCREENINFO: %s", strerror(errno)); goto err3; } GP_DEBUG(1, "Have framebufer %ix%i %s %ibpp", vscri.xres, vscri.yres, vscri.grayscale ? "Gray" : "RGB", vscri.bits_per_pixel); /* * Framebuffer is grayscale. */ if (vscri.grayscale) { GP_WARN("Grayscale not implemented!"); goto err3; } enum GP_PixelType pixel_type; pixel_type = GP_PixelRGBLookup(vscri.red.length, vscri.red.offset, vscri.green.length, vscri.green.offset, vscri.blue.length, vscri.blue.offset, vscri.transp.length, vscri.transp.offset, vscri.bits_per_pixel); if (pixel_type == GP_PIXEL_UNKNOWN) { GP_DEBUG(1, "Unknown pixel type\n"); goto err3; } if (flags & GP_FB_SHADOW) { fb->context.pixels = malloc(fscri.smem_len); if (!fb->context.pixels) { GP_DEBUG(1, "Malloc failed :("); goto err3; } } fb->fb_mem = mmap(NULL, fscri.smem_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); if (fb->fb_mem == MAP_FAILED) { GP_DEBUG(1, "mmaping framebuffer failed: %s", strerror(errno)); goto err4; } fb->fb_fd = fd; fb->bsize = fscri.smem_len; strcpy(fb->path, path); fb->flags = flags; if (!(flags & GP_FB_SHADOW)) fb->context.pixels = fb->fb_mem; fb->context.w = vscri.xres; fb->context.h = vscri.yres; fb->context.axes_swap = 0; fb->context.x_swap = 0; fb->context.y_swap = 0; fb->context.bpp = vscri.bits_per_pixel; fb->context.bytes_per_row = fscri.line_length; fb->context.pixel_type = pixel_type; int shadow = flags & GP_FB_SHADOW; int kbd = flags & GP_FB_INPUT_KBD; /* update API */ backend->name = "Linux FB"; backend->context = &fb->context; backend->Flip = shadow ? fb_flip_shadow : NULL; backend->UpdateRect = shadow ? fb_update_rect_shadow : NULL; backend->Exit = fb_exit; backend->SetAttributes = NULL; backend->ResizeAck = NULL; backend->Poll = kbd ? fb_poll : NULL; backend->Wait = kbd ? fb_wait : NULL; backend->fd = fb->con_fd; backend->timers = NULL; GP_EventQueueInit(&backend->event_queue, vscri.xres, vscri.yres, 0); return backend; err4: if (flags & GP_FB_SHADOW) free(fb->context.pixels); err3: close(fd); err2: if (flags & GP_FB_INPUT_KBD) exit_kbd(fb); err1: free_console(fb); err0: free(backend); return NULL; }