# HG changeset patch # User Pascal Bellard # Date 1414160800 -7200 # Node ID 5189478b714aaff1680619a03b1114d82ede6cf4 # Parent 7c22b419238422515d8c1efb87e002d1c45ded69 busybox: add fbvnc diff -r 7c22b4192384 -r 5189478b714a busybox/receipt --- a/busybox/receipt Fri Oct 24 12:46:53 2014 +0200 +++ b/busybox/receipt Fri Oct 24 16:26:40 2014 +0200 @@ -44,7 +44,7 @@ diet.u losetup.u fatattr.u -dpkg_deb-xz.u +fbvnc.u EOT cp $stuff/$PACKAGE-${VERSION%.*}.config .config } diff -r 7c22b4192384 -r 5189478b714a busybox/stuff/busybox-1.22-fbvnc.u --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/busybox/stuff/busybox-1.22-fbvnc.u Fri Oct 24 16:26:40 2014 +0200 @@ -0,0 +1,681 @@ + text data bss dec hex filename + 3118 0 0 3118 c2e util-linux/fbvnc.o +--- /dev/null ++++ busybox/util-linux/fbvnc.c +@@ -0,0 +1,551 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * A small linux framebuffer VNC viewer ++ * ++ * pascal.bellard@ads-lu.com ++ * ++ * Based on Ali Gholami Rudi's fbvnc.c ++ * http://repo.or.cz/w/fbvnc.git ++ * ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree. ++ */ ++ ++//applet:IF_FBVNC(APPLET(fbvnc, BB_DIR_BIN, BB_SUID_DROP)) ++ ++//kbuild:lib-$(CONFIG_FBVNC) += fbvnc.o ++ ++//config:config FBVNC ++//config: bool "fbvnc" ++//config: default n ++//config: depends on PLATFORM_LINUX ++//config: help ++//config: A linux framebuffer VNC viewer. ++ ++//usage:#define fbvnc_trivial_usage ++//usage: "[VNC_SERVER] [PORT]" ++//usage:#define fbvnc_full_usage "\n\n" ++//usage: "A linux framebuffer VNC viewer." ++//usage: "\nTo exit, move mouse to upper left corner and press ESC." ++ ++#include "libbb.h" ++#include "vnc.h" ++ ++/* Stuff stolen from the kernel's fb.h */ ++#define FB_ACTIVATE_ALL 64 ++enum { ++ FBIOGET_VSCREENINFO = 0x4600, ++ FBIOPUT_VSCREENINFO = 0x4601, ++ FBIOGET_FSCREENINFO = 0x4602, ++ FBIOGETCMAP = 0x4604, ++ FBIOPUTCMAP = 0x4605 ++}; ++ ++struct fb_bitfield { ++ uint32_t offset; /* beginning of bitfield */ ++ uint32_t length; /* length of bitfield */ ++ uint32_t msb_right; /* !=0: Most significant bit is right */ ++}; ++struct fb_var_screeninfo { ++ uint32_t xres; /* visible resolution */ ++ uint32_t yres; ++ uint32_t xres_virtual; /* virtual resolution */ ++ uint32_t yres_virtual; ++ uint32_t xoffset; /* offset from virtual to visible */ ++ uint32_t yoffset; /* resolution */ ++ ++ uint32_t bits_per_pixel; ++ uint32_t grayscale; /* !=0 Graylevels instead of colors */ ++ ++ struct fb_bitfield red; /* bitfield in fb mem if true color, */ ++ struct fb_bitfield green; /* else only length is significant */ ++ struct fb_bitfield blue; ++ struct fb_bitfield transp; /* transparency */ ++ ++ uint32_t nonstd; /* !=0 Non standard pixel format */ ++ ++ uint32_t activate; /* see FB_ACTIVATE_x */ ++ ++ uint32_t height; /* height of picture in mm */ ++ uint32_t width; /* width of picture in mm */ ++ ++ uint32_t accel_flags; /* acceleration flags (hints) */ ++ ++ /* Timing: All values in pixclocks, except pixclock (of course) */ ++ uint32_t pixclock; /* pixel clock in ps (pico seconds) */ ++ uint32_t left_margin; /* time from sync to picture */ ++ uint32_t right_margin; /* time from picture to sync */ ++ uint32_t upper_margin; /* time from sync to picture */ ++ uint32_t lower_margin; ++ uint32_t hsync_len; /* length of horizontal sync */ ++ uint32_t vsync_len; /* length of vertical sync */ ++ uint32_t sync; /* see FB_SYNC_x */ ++ uint32_t vmode; /* see FB_VMODE_x */ ++ uint32_t reserved[6]; /* Reserved for future compatibility */ ++}; ++ ++#define DEFAULTFBDEV FB_0 ++ ++struct fb_fix_screeninfo { ++ char id[16]; /* identification string eg "TT Builtin" */ ++ unsigned long smem_start; /* Start of frame buffer mem */ ++ /* (physical address) */ ++ uint32_t smem_len; /* Length of frame buffer mem */ ++ uint32_t type; /* see FB_TYPE_* */ ++ uint32_t type_aux; /* Interleave for interleaved Planes */ ++ uint32_t visual; /* see FB_VISUAL_* */ ++ uint16_t xpanstep; /* zero if no hardware panning */ ++ uint16_t ypanstep; /* zero if no hardware panning */ ++ uint16_t ywrapstep; /* zero if no hardware ywrap */ ++ uint32_t line_length; /* length of a line in bytes */ ++ unsigned long mmio_start; /* Start of Memory Mapped I/O */ ++ /* (physical address) */ ++ uint32_t mmio_len; /* Length of Memory Mapped I/O */ ++ uint32_t accel; /* Indicate to driver which */ ++ /* specific chip/card we have */ ++ uint16_t reserved[3]; /* Reserved for future compatibility */ ++}; ++ ++struct fb_cmap { ++ uint32_t start; /* First entry */ ++ uint32_t len; /* Number of entries */ ++ uint16_t *red; /* Red values */ ++ uint16_t *green; ++ uint16_t *blue; ++ uint16_t *transp; /* transparency, can be NULL */ ++}; ++ ++#define FB_VISUAL_TRUECOLOR 2 /* True color */ ++ ++#define COLORLEVELS (1 << 8) ++ ++struct scroll_data { ++ int size; ++ int srv_size; ++ int offset; ++ int pos; ++}; ++ ++struct globals { ++ struct termios term_orig; ++ struct pollfd ufds[3]; ++#define kbd_fd ufds[0].fd ++#define vnc_fd ufds[1].fd ++#define rat_fd ufds[2].fd ++ struct scroll_data scroll[2]; ++#define cols scroll[0].size ++#define srv_cols scroll[0].srv_size ++#define oc scroll[0].offset ++#define mc scroll[0].pos ++#define rows scroll[1].size ++#define srv_rows scroll[1].srv_size ++#define or scroll[1].offset ++#define mr scroll[1].pos ++ int fb_fd; ++ void *fb_ptr; ++ int bpp; ++ int nr, ng, nb; ++ struct fb_var_screeninfo vinfo; ++ struct fb_fix_screeninfo finfo; ++ unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS]; ++}; ++ ++#define G (*ptr_to_globals) ++#define INIT_G() do { \ ++ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ ++} while (0) ++ ++static int fb_len(void) ++{ ++ return G.finfo.line_length * G.vinfo.yres_virtual; ++} ++ ++static void fb_ioctl_cmap(int fct, struct fb_cmap *cmap) ++{ ++ if (G.finfo.visual == FB_VISUAL_TRUECOLOR) ++ return; ++ cmap->start = 0; ++ cmap->len = MAX(G.nr, MAX(G.ng, G.nb)); ++ cmap->transp = NULL; ++ xioctl(G.fb_fd, fct, cmap); ++} ++ ++static void fb_cmap_save(int save) ++{ ++ struct fb_cmap cmap; ++ ++ cmap.red = G.red; ++ cmap.green = G.green; ++ cmap.blue = G.blue; ++ fb_ioctl_cmap(save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap); ++} ++ ++static void fb_build_cmap(unsigned short *color, int n) ++{ ++ int i, inc = 65535 / (n - 1); ++ ++ for (i = 0; n--; i += inc) ++ *color++ = i; ++} ++ ++static void fb_cmap(void) ++{ ++ unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS]; ++ struct fb_cmap cmap; ++ ++ fb_build_cmap(cmap.red = red, G.nr); ++ fb_build_cmap(cmap.green = green, G.ng); ++ fb_build_cmap(cmap.blue = blue, G.nb); ++ fb_ioctl_cmap(FBIOPUTCMAP, &cmap); ++} ++ ++static void fb_init(void) ++{ ++ G.fb_fd = xopen(DEFAULTFBDEV, O_RDWR); ++ xioctl(G.fb_fd, FBIOGET_VSCREENINFO, &G.vinfo); ++ xioctl(G.fb_fd, FBIOGET_FSCREENINFO, &G.finfo); ++ close_on_exec_on(G.fb_fd); ++ G.fb_ptr = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, G.fb_fd, 0); ++ if (G.fb_ptr == MAP_FAILED) ++ bb_perror_msg_and_die("mmap"); ++ G.bpp = (G.vinfo.bits_per_pixel + 7) >> 3; ++ G.nr = 1 << G.vinfo.red.length; ++ G.nb = 1 << G.vinfo.blue.length; ++ G.ng = 1 << G.vinfo.green.length; ++ fb_cmap_save(1); ++ fb_cmap(); ++} ++ ++static void fb_free(void) ++{ ++ fb_cmap_save(0); ++ munmap(G.fb_ptr, fb_len()); ++ close(G.fb_fd); ++} ++ ++#define fb_rows vinfo.yres ++#define fb_cols vinfo.xres ++ ++static void fb_set(int r, int c, void *mem, int len) ++{ ++ memcpy(G.fb_ptr + (r + G.vinfo.yoffset) * G.finfo.line_length + ++ (c + G.vinfo.xoffset) * G.bpp, mem, len * G.bpp); ++} ++ ++#define line_buffer bb_common_bufsiz1 ++#define MAXPIX (sizeof(line_buffer)/sizeof(uint32_t)) ++ ++static void skip(int len) ++{ ++ int n; ++ while (len > 0 && (n = read(G.vnc_fd, line_buffer, ++ MIN(len, sizeof(line_buffer)))) > 0) ++ len -= n; ++} ++ ++static void vnc_init(void) ++{ ++ struct vnc_client_init clientinit; ++ struct vnc_server_init serverinit; ++ struct vnc_client_pixelfmt pixfmt_cmd; ++ int connstat = VNC_CONN_FAILED; ++ ++ write(G.vnc_fd, "RFB 003.003\n", 12); ++ skip(12); ++ ++ xread(G.vnc_fd, &connstat, sizeof(connstat)); ++ ++ if (ntohl(connstat) != VNC_CONN_NOAUTH) ++ bb_perror_msg_and_die("vnc auth"); ++ ++ clientinit.shared = 1; ++ write(G.vnc_fd, &clientinit, sizeof(clientinit)); ++ read(G.vnc_fd, &serverinit, sizeof(serverinit)); ++ ++ fb_init(); ++ G.srv_cols = ntohs(serverinit.w); ++ G.srv_rows = ntohs(serverinit.h); ++ G.cols = MIN(G.srv_cols, G.fb_cols); ++ G.rows = MIN(G.srv_rows, G.fb_rows); ++ G.mr = G.rows / 2; ++ G.mc = G.cols / 2; ++ ++ skip(ntohl(serverinit.len)); ++ pixfmt_cmd.type = VNC_CLIENT_PIXFMT; ++ pixfmt_cmd.format.bigendian = 0; ++ pixfmt_cmd.format.truecolor = 1; ++ pixfmt_cmd.format.bpp = ++ pixfmt_cmd.format.depth = G.bpp << 3; ++ pixfmt_cmd.format.rmax = htons(G.nr - 1); ++ pixfmt_cmd.format.gmax = htons(G.ng - 1); ++ pixfmt_cmd.format.bmax = htons(G.nb - 1); ++ pixfmt_cmd.format.rshl = G.vinfo.red.offset; ++ pixfmt_cmd.format.gshl = G.vinfo.green.offset; ++ pixfmt_cmd.format.bshl = G.vinfo.blue.offset; ++ write(G.vnc_fd, &pixfmt_cmd, sizeof(pixfmt_cmd)); ++} ++ ++static void vnc_refresh(int inc) ++{ ++ struct vnc_client_fbup fbup_req; ++ fbup_req.type = VNC_CLIENT_FBUP; ++ fbup_req.inc = inc; ++ fbup_req.x = htons(G.oc); ++ fbup_req.y = htons(G.or); ++ fbup_req.w = htons(G.oc + G.cols); ++ fbup_req.h = htons(G.or + G.rows); ++ write(G.vnc_fd, &fbup_req, sizeof(fbup_req)); ++} ++ ++static void cleanup(void) ++{ ++ const char *reset = "\x1b[?25h" "\x1b[2J\x1b[H"; ++ fb_free(); ++ tcsetattr_stdin_TCSANOW(&G.term_orig); ++ write(STDOUT_FILENO, reset, strlen(reset)); ++ if (ENABLE_FEATURE_CLEAN_UP) { ++ close(G.vnc_fd); ++ close(G.rat_fd); ++ } ++} ++ ++static void killed(int code) NORETURN; ++static void killed(int code) ++{ ++ cleanup(); ++ if (code > EXIT_FAILURE) ++ kill_myself_with_sig(code); ++ exit(code); ++} ++ ++static void vnc_event(void) ++{ ++ struct vnc_rect uprect; ++ union { ++ struct vnc_server_fbup fbup; ++ struct vnc_server_cuttext cuttext; ++ struct vnc_server_colormap colormap; ++ } msg; ++ int n; ++ ++ switch (xread_char(G.vnc_fd)) { ++ case VNC_SERVER_FBUP: ++ xread(G.vnc_fd, &msg.fbup.pad, sizeof(msg.fbup) - 1); ++ n = ntohs(msg.fbup.n); ++ while (n--) { ++ int x, y, w, h, l, i; ++ xread(G.vnc_fd, &uprect, sizeof(uprect)); ++ if (uprect.enc != 0) ++ killed(1); ++ i = 0; ++ x = ntohs(uprect.x) - G.oc; ++ y = ntohs(uprect.y) - G.or; ++ w = ntohs(uprect.w); ++ h = ntohs(uprect.h); ++ l = MIN(w, G.cols - x); ++ if (x < 0) { ++ l = MIN(w + x, G.cols); ++ i = -x; ++ x = 0; ++ } ++ for (; h--; y++) { ++ int a, b, c = i; ++ for (a = b = 0; w > b; b += a, c = 0) { ++ int len; ++ a = MIN(w - b, MAXPIX); ++ len = MIN(a, l - b) - c; ++ xread(G.vnc_fd, line_buffer, a * G.bpp); ++ if (y >= 0 && y < G.rows && len > 0) ++ fb_set(y, x + b, ++ line_buffer + (c * G.bpp), ++ len); ++ } ++ } ++ } ++ break; ++ case VNC_SERVER_BELL: ++ break; ++ case VNC_SERVER_CUTTEXT: ++ xread(G.vnc_fd, &msg.cuttext.pad1, sizeof(msg.cuttext) - 1); ++ skip(ntohl(msg.cuttext.len)); ++ break; ++ case VNC_SERVER_COLORMAP: ++ xread(G.vnc_fd, &msg.colormap.pad, sizeof(msg.colormap) - 1); ++ skip(ntohs(msg.colormap.n) * 3 * 2); ++ break; ++ default: ++ killed(1); ++ } ++} ++ ++static int update_scroll(struct scroll_data *s) ++{ ++ int shift = s->size / 5; ++ int max = s->srv_size - s->size; ++ int status = 0; ++ if (s->pos < s->offset) { ++ if ((s->offset -= shift) < 0) ++ s->offset = 0; ++ } ++ else if (s->pos >= s->offset + s->size && s->offset < max) { ++ if ((s->offset += shift) > max) ++ s->offset = max; ++ } ++ else status++; ++ s->pos = MAX(s->offset, MIN(s->offset + s->size - 1, s->pos)); ++ return status; ++} ++ ++static void rat_event(void) ++{ ++ signed char ie[3]; ++ struct vnc_client_ratevent me = {VNC_CLIENT_RATEVENT}; ++ int mask = 0; ++ int refresh; ++ ++ xread(G.rat_fd, &ie, sizeof(ie)); ++ G.mc += ie[1]; ++ G.mr -= ie[2]; ++ refresh = 2 - update_scroll(&G.scroll[0]) - update_scroll(&G.scroll[1]); ++ if (ie[0] & 0x01) ++ mask |= VNC_BUTTON1_MASK; ++ if (ie[0] & 0x04) ++ mask |= VNC_BUTTON2_MASK; ++ if (ie[0] & 0x02) ++ mask |= VNC_BUTTON3_MASK; ++ me.y = htons(G.mr); ++ me.x = htons(G.mc); ++ me.mask = mask; ++ write(G.vnc_fd, &me, sizeof(me)); ++ if (refresh) ++ vnc_refresh(0); ++} ++ ++static int press(int key, int down) ++{ ++ struct vnc_client_keyevent ke = {VNC_CLIENT_KEYEVENT}; ++ ke.key = htonl(key); ++ ke.down = down; ++ return write(G.vnc_fd, &ke, sizeof(ke)); ++} ++ ++static void kbd_event(void) ++{ ++ char key[1024]; ++ int i, nr; ++ ++ if ((nr = read(0, key, sizeof(key))) <= 0 ) ++ killed(1); ++ for (i = 0; i < nr; i++) { ++ int k = -1; ++ int mod[4]; ++ int nmod = 0; ++ switch (key[i]) { ++ case 0x08: ++ case 0x7f: ++ k = 0xff08; ++ break; ++ case 0x09: ++ k = 0xff09; ++ break; ++ case 0x1b: ++ if (G.oc + G.mc + G.or + G.mr == 0) ++ killed(0); ++ if (i + 2 < nr && key[i + 1] == '[') { ++ if (key[i + 2] == 'A') ++ k = 0xff52; ++ if (key[i + 2] == 'B') ++ k = 0xff54; ++ if (key[i + 2] == 'C') ++ k = 0xff53; ++ if (key[i + 2] == 'D') ++ k = 0xff51; ++ if (key[i + 2] == 'H') ++ k = 0xff50; ++ if (k > 0) { ++ i += 2; ++ break; ++ } ++ } ++ k = 0xff1b; ++ if (i + 1 < nr) { ++ mod[nmod++] = 0xffe9; ++ k = key[++i]; ++ } ++ break; ++ case 0x0d: ++ k = 0xff0d; ++ break; ++ case 0x0c: /* ^L: redraw */ ++ vnc_refresh(0); ++ default: ++ k = (unsigned char) key[i]; ++ } ++ if ((k >= 'A' && k <= 'Z') || strchr(":\"<>?{}|+_()*&^%$#@!~", k)) ++ mod[nmod++] = 0xffe1; ++ if (k >= 1 && k <= 26) { ++ k += 'a' - 1; ++ mod[nmod++] = 0xffe3; ++ } ++ if (k > 0) { ++ int j; ++ mod[nmod] = k; ++ for (j = 0; j <= nmod; j++) ++ press(mod[j], 1); ++ press(k, 0); ++ for (j = 0; j < nmod; j++) ++ press(mod[j], 0); ++ } ++ } ++} ++ ++static void term_setup(void) ++{ ++ struct termios termios; ++ const char *init = "\x1b[?25l" "\x1b[2J\x1b[H" "** fbvnc **"; ++ ++ write(STDOUT_FILENO, init, strlen(init)); ++ tcgetattr (STDIN_FILENO, &termios); ++ G.term_orig = termios; ++ cfmakeraw(&termios); ++ tcsetattr_stdin_TCSANOW(&termios); ++} ++ ++int fbvnc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; ++int fbvnc_main(int argc, char **argv) ++{ ++ char *host = (char *) "127.0.0.1"; ++ int port, pending = 0; ++ ++ INIT_G(); ++ if (argc >= 2) ++ host = argv[1]; ++ port = bb_lookup_port((argc >= 3) ? argv[2] : "vnc", "tcp", 5900); ++ G.vnc_fd = create_and_connect_stream_or_die(host, port); ++ vnc_init(); ++ G.rat_fd = open("/dev/input/mice", O_RDONLY); ++ term_setup(); ++ atexit(cleanup); ++ bb_signals(BB_FATAL_SIGS, killed); ++ ++ G.ufds[0].events = ++ G.ufds[1].events = ++ G.ufds[2].events = POLLIN; ++ vnc_refresh(0); ++ while (1) { ++ int status = poll(G.ufds, 3, 500); ++ if (status == -1 && errno != EINTR) ++ killed(1); ++ if (!status) ++ continue; ++ if (G.ufds[0].revents & POLLIN) ++ kbd_event(); ++ if (G.ufds[1].revents & POLLIN) { ++ vnc_event(); ++ pending = 0; ++ } ++ if (G.ufds[2].revents & POLLIN) ++ rat_event(); ++ if (!pending++) ++ vnc_refresh(1); ++ } ++} +--- /dev/null ++++ busybox/util-linux/vnc.h +@@ -0,0 +1,122 @@ ++#define VNC_CONN_FAILED 0 ++#define VNC_CONN_NOAUTH 1 ++#define VNC_CONN_AUTH 2 ++ ++#define VNC_AUTH_OK 0 ++#define VNC_AUTH_FAILED 1 ++#define VNC_AUTH_TOOMANY 2 ++ ++#define VNC_SERVER_FBUP 0 ++#define VNC_SERVER_COLORMAP 1 ++#define VNC_SERVER_BELL 2 ++#define VNC_SERVER_CUTTEXT 3 ++ ++#define VNC_CLIENT_PIXFMT 0 ++#define VNC_CLIENT_COLORMAP 1 ++#define VNC_CLIENT_SETENC 2 ++#define VNC_CLIENT_FBUP 3 ++#define VNC_CLIENT_KEYEVENT 4 ++#define VNC_CLIENT_RATEVENT 5 ++#define VNC_CLIENT_CUTTEXT 6 ++ ++#define VNC_ENC_RAW 0 ++#define VNC_ENC_COPYRECT 1 ++#define VNC_ENC_RRE 2 ++#define VNC_ENC_CORRE 4 ++#define VNC_ENC_HEXTILE 5 ++ ++#define VNC_BUTTON1_MASK 0x1 ++#define VNC_BUTTON2_MASK 0x2 ++#define VNC_BUTTON3_MASK 0x4 ++ ++typedef unsigned char u8; ++typedef unsigned short u16; ++typedef unsigned int u32; ++ ++struct vnc_pixelfmt { ++ u8 bpp; ++ u8 depth; ++ u8 bigendian; ++ u8 truecolor; ++ u16 rmax; ++ u16 gmax; ++ u16 bmax; ++ u8 rshl; ++ u8 gshl; ++ u8 bshl; ++ ++ u8 pad1; ++ u16 pad2; ++}; ++ ++struct vnc_client_init { ++ u8 shared; ++}; ++ ++struct vnc_server_init { ++ u16 w; ++ u16 h; ++ struct vnc_pixelfmt fmt; ++ u32 len; ++ /* char name[len]; */ ++}; ++ ++struct vnc_rect { ++ u16 x, y; ++ u16 w, h; ++ u32 enc; ++ /* rect bytes */ ++}; ++ ++struct vnc_server_fbup { ++ u8 type; ++ u8 pad; ++ u16 n; ++ /* struct vnc_rect rects[n]; */ ++}; ++ ++struct vnc_server_cuttext { ++ u8 type; ++ u8 pad1; ++ u16 pad2; ++ u32 len; ++ /* char text[length] */ ++}; ++ ++struct vnc_server_colormap { ++ u8 type; ++ u8 pad; ++ u16 first; ++ u16 n; ++ /* u8 colors[n * 3 * 2]; */ ++}; ++ ++struct vnc_client_pixelfmt { ++ u8 type; ++ u8 pad1; ++ u16 pad2; ++ struct vnc_pixelfmt format; ++}; ++ ++struct vnc_client_fbup { ++ u8 type; ++ u8 inc; ++ u16 x; ++ u16 y; ++ u16 w; ++ u16 h; ++}; ++ ++struct vnc_client_keyevent { ++ u8 type; ++ u8 down; ++ u16 pad; ++ u32 key; ++}; ++ ++struct vnc_client_ratevent { ++ u8 type; ++ u8 mask; ++ u16 x; ++ u16 y; ++}; diff -r 7c22b4192384 -r 5189478b714a busybox/stuff/busybox-1.22.config --- a/busybox/stuff/busybox-1.22.config Fri Oct 24 12:46:53 2014 +0200 +++ b/busybox/stuff/busybox-1.22.config Fri Oct 24 16:26:40 2014 +0200 @@ -527,6 +527,7 @@ # Linux System Utilities # CONFIG_BLOCKDEV=y +CONFIG_FBVNC=y CONFIG_FSTRIM=y # CONFIG_MDEV is not set # CONFIG_FEATURE_MDEV_CONF is not set diff -r 7c22b4192384 -r 5189478b714a busybox/stuff/busybox-1.22.config-ssfs --- a/busybox/stuff/busybox-1.22.config-ssfs Fri Oct 24 12:46:53 2014 +0200 +++ b/busybox/stuff/busybox-1.22.config-ssfs Fri Oct 24 16:26:40 2014 +0200 @@ -527,6 +527,7 @@ # Linux System Utilities # # CONFIG_BLOCKDEV is not set +# CONFIG_FBVNC is not set # CONFIG_FSTRIM is not set # CONFIG_MDEV is not set # CONFIG_FEATURE_MDEV_CONF is not set diff -r 7c22b4192384 -r 5189478b714a busybox/stuff/busybox-1.22.config-static --- a/busybox/stuff/busybox-1.22.config-static Fri Oct 24 12:46:53 2014 +0200 +++ b/busybox/stuff/busybox-1.22.config-static Fri Oct 24 16:26:40 2014 +0200 @@ -527,6 +527,7 @@ # Linux System Utilities # # CONFIG_BLOCKDEV is not set +# CONFIG_FBVNC is not set # CONFIG_FSTRIM is not set # CONFIG_MDEV is not set # CONFIG_FEATURE_MDEV_CONF is not set