wok-undigest annotate busybox/stuff/busybox-1.22-fbvnc.u @ rev 1138

Add busybox with "# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set"
author Aleksej Bobylev <al.bobylev@gmail.com>
date Fri Jan 16 02:51:58 2015 +0200 (2015-01-16)
parents
children
rev   line source
al@1138 1 text data bss dec hex filename
al@1138 2 3118 0 0 3118 c2e util-linux/fbvnc.o
al@1138 3 --- /dev/null
al@1138 4 +++ busybox/util-linux/fbvnc.c
al@1138 5 @@ -0,0 +1,551 @@
al@1138 6 +/* vi: set sw=4 ts=4: */
al@1138 7 +/*
al@1138 8 + * A small linux framebuffer VNC viewer
al@1138 9 + *
al@1138 10 + * pascal.bellard@ads-lu.com
al@1138 11 + *
al@1138 12 + * Based on Ali Gholami Rudi's fbvnc.c
al@1138 13 + * http://repo.or.cz/w/fbvnc.git
al@1138 14 + *
al@1138 15 + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
al@1138 16 + */
al@1138 17 +
al@1138 18 +//applet:IF_FBVNC(APPLET(fbvnc, BB_DIR_BIN, BB_SUID_DROP))
al@1138 19 +
al@1138 20 +//kbuild:lib-$(CONFIG_FBVNC) += fbvnc.o
al@1138 21 +
al@1138 22 +//config:config FBVNC
al@1138 23 +//config: bool "fbvnc"
al@1138 24 +//config: default n
al@1138 25 +//config: depends on PLATFORM_LINUX
al@1138 26 +//config: help
al@1138 27 +//config: A linux framebuffer VNC viewer.
al@1138 28 +
al@1138 29 +//usage:#define fbvnc_trivial_usage
al@1138 30 +//usage: "[VNC_SERVER] [PORT]"
al@1138 31 +//usage:#define fbvnc_full_usage "\n\n"
al@1138 32 +//usage: "A linux framebuffer VNC viewer."
al@1138 33 +//usage: "\nTo exit, move mouse to upper left corner and press ESC."
al@1138 34 +
al@1138 35 +#include "libbb.h"
al@1138 36 +#include "vnc.h"
al@1138 37 +
al@1138 38 +/* Stuff stolen from the kernel's fb.h */
al@1138 39 +#define FB_ACTIVATE_ALL 64
al@1138 40 +enum {
al@1138 41 + FBIOGET_VSCREENINFO = 0x4600,
al@1138 42 + FBIOPUT_VSCREENINFO = 0x4601,
al@1138 43 + FBIOGET_FSCREENINFO = 0x4602,
al@1138 44 + FBIOGETCMAP = 0x4604,
al@1138 45 + FBIOPUTCMAP = 0x4605
al@1138 46 +};
al@1138 47 +
al@1138 48 +struct fb_bitfield {
al@1138 49 + uint32_t offset; /* beginning of bitfield */
al@1138 50 + uint32_t length; /* length of bitfield */
al@1138 51 + uint32_t msb_right; /* !=0: Most significant bit is right */
al@1138 52 +};
al@1138 53 +struct fb_var_screeninfo {
al@1138 54 + uint32_t xres; /* visible resolution */
al@1138 55 + uint32_t yres;
al@1138 56 + uint32_t xres_virtual; /* virtual resolution */
al@1138 57 + uint32_t yres_virtual;
al@1138 58 + uint32_t xoffset; /* offset from virtual to visible */
al@1138 59 + uint32_t yoffset; /* resolution */
al@1138 60 +
al@1138 61 + uint32_t bits_per_pixel;
al@1138 62 + uint32_t grayscale; /* !=0 Graylevels instead of colors */
al@1138 63 +
al@1138 64 + struct fb_bitfield red; /* bitfield in fb mem if true color, */
al@1138 65 + struct fb_bitfield green; /* else only length is significant */
al@1138 66 + struct fb_bitfield blue;
al@1138 67 + struct fb_bitfield transp; /* transparency */
al@1138 68 +
al@1138 69 + uint32_t nonstd; /* !=0 Non standard pixel format */
al@1138 70 +
al@1138 71 + uint32_t activate; /* see FB_ACTIVATE_x */
al@1138 72 +
al@1138 73 + uint32_t height; /* height of picture in mm */
al@1138 74 + uint32_t width; /* width of picture in mm */
al@1138 75 +
al@1138 76 + uint32_t accel_flags; /* acceleration flags (hints) */
al@1138 77 +
al@1138 78 + /* Timing: All values in pixclocks, except pixclock (of course) */
al@1138 79 + uint32_t pixclock; /* pixel clock in ps (pico seconds) */
al@1138 80 + uint32_t left_margin; /* time from sync to picture */
al@1138 81 + uint32_t right_margin; /* time from picture to sync */
al@1138 82 + uint32_t upper_margin; /* time from sync to picture */
al@1138 83 + uint32_t lower_margin;
al@1138 84 + uint32_t hsync_len; /* length of horizontal sync */
al@1138 85 + uint32_t vsync_len; /* length of vertical sync */
al@1138 86 + uint32_t sync; /* see FB_SYNC_x */
al@1138 87 + uint32_t vmode; /* see FB_VMODE_x */
al@1138 88 + uint32_t reserved[6]; /* Reserved for future compatibility */
al@1138 89 +};
al@1138 90 +
al@1138 91 +#define DEFAULTFBDEV FB_0
al@1138 92 +
al@1138 93 +struct fb_fix_screeninfo {
al@1138 94 + char id[16]; /* identification string eg "TT Builtin" */
al@1138 95 + unsigned long smem_start; /* Start of frame buffer mem */
al@1138 96 + /* (physical address) */
al@1138 97 + uint32_t smem_len; /* Length of frame buffer mem */
al@1138 98 + uint32_t type; /* see FB_TYPE_* */
al@1138 99 + uint32_t type_aux; /* Interleave for interleaved Planes */
al@1138 100 + uint32_t visual; /* see FB_VISUAL_* */
al@1138 101 + uint16_t xpanstep; /* zero if no hardware panning */
al@1138 102 + uint16_t ypanstep; /* zero if no hardware panning */
al@1138 103 + uint16_t ywrapstep; /* zero if no hardware ywrap */
al@1138 104 + uint32_t line_length; /* length of a line in bytes */
al@1138 105 + unsigned long mmio_start; /* Start of Memory Mapped I/O */
al@1138 106 + /* (physical address) */
al@1138 107 + uint32_t mmio_len; /* Length of Memory Mapped I/O */
al@1138 108 + uint32_t accel; /* Indicate to driver which */
al@1138 109 + /* specific chip/card we have */
al@1138 110 + uint16_t reserved[3]; /* Reserved for future compatibility */
al@1138 111 +};
al@1138 112 +
al@1138 113 +struct fb_cmap {
al@1138 114 + uint32_t start; /* First entry */
al@1138 115 + uint32_t len; /* Number of entries */
al@1138 116 + uint16_t *red; /* Red values */
al@1138 117 + uint16_t *green;
al@1138 118 + uint16_t *blue;
al@1138 119 + uint16_t *transp; /* transparency, can be NULL */
al@1138 120 +};
al@1138 121 +
al@1138 122 +#define FB_VISUAL_TRUECOLOR 2 /* True color */
al@1138 123 +
al@1138 124 +#define COLORLEVELS (1 << 8)
al@1138 125 +
al@1138 126 +struct scroll_data {
al@1138 127 + int size;
al@1138 128 + int srv_size;
al@1138 129 + int offset;
al@1138 130 + int pos;
al@1138 131 +};
al@1138 132 +
al@1138 133 +struct globals {
al@1138 134 + struct termios term_orig;
al@1138 135 + struct pollfd ufds[3];
al@1138 136 +#define kbd_fd ufds[0].fd
al@1138 137 +#define vnc_fd ufds[1].fd
al@1138 138 +#define rat_fd ufds[2].fd
al@1138 139 + struct scroll_data scroll[2];
al@1138 140 +#define cols scroll[0].size
al@1138 141 +#define srv_cols scroll[0].srv_size
al@1138 142 +#define oc scroll[0].offset
al@1138 143 +#define mc scroll[0].pos
al@1138 144 +#define rows scroll[1].size
al@1138 145 +#define srv_rows scroll[1].srv_size
al@1138 146 +#define or scroll[1].offset
al@1138 147 +#define mr scroll[1].pos
al@1138 148 + int fb_fd;
al@1138 149 + void *fb_ptr;
al@1138 150 + int bpp;
al@1138 151 + int nr, ng, nb;
al@1138 152 + struct fb_var_screeninfo vinfo;
al@1138 153 + struct fb_fix_screeninfo finfo;
al@1138 154 + unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS];
al@1138 155 +};
al@1138 156 +
al@1138 157 +#define G (*ptr_to_globals)
al@1138 158 +#define INIT_G() do { \
al@1138 159 + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
al@1138 160 +} while (0)
al@1138 161 +
al@1138 162 +static int fb_len(void)
al@1138 163 +{
al@1138 164 + return G.finfo.line_length * G.vinfo.yres_virtual;
al@1138 165 +}
al@1138 166 +
al@1138 167 +static void fb_ioctl_cmap(int fct, struct fb_cmap *cmap)
al@1138 168 +{
al@1138 169 + if (G.finfo.visual == FB_VISUAL_TRUECOLOR)
al@1138 170 + return;
al@1138 171 + cmap->start = 0;
al@1138 172 + cmap->len = MAX(G.nr, MAX(G.ng, G.nb));
al@1138 173 + cmap->transp = NULL;
al@1138 174 + xioctl(G.fb_fd, fct, cmap);
al@1138 175 +}
al@1138 176 +
al@1138 177 +static void fb_cmap_save(int save)
al@1138 178 +{
al@1138 179 + struct fb_cmap cmap;
al@1138 180 +
al@1138 181 + cmap.red = G.red;
al@1138 182 + cmap.green = G.green;
al@1138 183 + cmap.blue = G.blue;
al@1138 184 + fb_ioctl_cmap(save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap);
al@1138 185 +}
al@1138 186 +
al@1138 187 +static void fb_build_cmap(unsigned short *color, int n)
al@1138 188 +{
al@1138 189 + int i, inc = 65535 / (n - 1);
al@1138 190 +
al@1138 191 + for (i = 0; n--; i += inc)
al@1138 192 + *color++ = i;
al@1138 193 +}
al@1138 194 +
al@1138 195 +static void fb_cmap(void)
al@1138 196 +{
al@1138 197 + unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS];
al@1138 198 + struct fb_cmap cmap;
al@1138 199 +
al@1138 200 + fb_build_cmap(cmap.red = red, G.nr);
al@1138 201 + fb_build_cmap(cmap.green = green, G.ng);
al@1138 202 + fb_build_cmap(cmap.blue = blue, G.nb);
al@1138 203 + fb_ioctl_cmap(FBIOPUTCMAP, &cmap);
al@1138 204 +}
al@1138 205 +
al@1138 206 +static void fb_init(void)
al@1138 207 +{
al@1138 208 + G.fb_fd = xopen(DEFAULTFBDEV, O_RDWR);
al@1138 209 + xioctl(G.fb_fd, FBIOGET_VSCREENINFO, &G.vinfo);
al@1138 210 + xioctl(G.fb_fd, FBIOGET_FSCREENINFO, &G.finfo);
al@1138 211 + close_on_exec_on(G.fb_fd);
al@1138 212 + G.fb_ptr = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, G.fb_fd, 0);
al@1138 213 + if (G.fb_ptr == MAP_FAILED)
al@1138 214 + bb_perror_msg_and_die("mmap");
al@1138 215 + G.bpp = (G.vinfo.bits_per_pixel + 7) >> 3;
al@1138 216 + G.nr = 1 << G.vinfo.red.length;
al@1138 217 + G.nb = 1 << G.vinfo.blue.length;
al@1138 218 + G.ng = 1 << G.vinfo.green.length;
al@1138 219 + fb_cmap_save(1);
al@1138 220 + fb_cmap();
al@1138 221 +}
al@1138 222 +
al@1138 223 +static void fb_free(void)
al@1138 224 +{
al@1138 225 + fb_cmap_save(0);
al@1138 226 + munmap(G.fb_ptr, fb_len());
al@1138 227 + close(G.fb_fd);
al@1138 228 +}
al@1138 229 +
al@1138 230 +#define fb_rows vinfo.yres
al@1138 231 +#define fb_cols vinfo.xres
al@1138 232 +
al@1138 233 +static void fb_set(int r, int c, void *mem, int len)
al@1138 234 +{
al@1138 235 + memcpy(G.fb_ptr + (r + G.vinfo.yoffset) * G.finfo.line_length +
al@1138 236 + (c + G.vinfo.xoffset) * G.bpp, mem, len * G.bpp);
al@1138 237 +}
al@1138 238 +
al@1138 239 +#define line_buffer bb_common_bufsiz1
al@1138 240 +#define MAXPIX (sizeof(line_buffer)/sizeof(uint32_t))
al@1138 241 +
al@1138 242 +static void skip(int len)
al@1138 243 +{
al@1138 244 + int n;
al@1138 245 + while (len > 0 && (n = read(G.vnc_fd, line_buffer,
al@1138 246 + MIN(len, sizeof(line_buffer)))) > 0)
al@1138 247 + len -= n;
al@1138 248 +}
al@1138 249 +
al@1138 250 +static void vnc_init(void)
al@1138 251 +{
al@1138 252 + struct vnc_client_init clientinit;
al@1138 253 + struct vnc_server_init serverinit;
al@1138 254 + struct vnc_client_pixelfmt pixfmt_cmd;
al@1138 255 + int connstat = VNC_CONN_FAILED;
al@1138 256 +
al@1138 257 + write(G.vnc_fd, "RFB 003.003\n", 12);
al@1138 258 + skip(12);
al@1138 259 +
al@1138 260 + xread(G.vnc_fd, &connstat, sizeof(connstat));
al@1138 261 +
al@1138 262 + if (ntohl(connstat) != VNC_CONN_NOAUTH)
al@1138 263 + bb_perror_msg_and_die("vnc auth");
al@1138 264 +
al@1138 265 + clientinit.shared = 1;
al@1138 266 + write(G.vnc_fd, &clientinit, sizeof(clientinit));
al@1138 267 + read(G.vnc_fd, &serverinit, sizeof(serverinit));
al@1138 268 +
al@1138 269 + fb_init();
al@1138 270 + G.srv_cols = ntohs(serverinit.w);
al@1138 271 + G.srv_rows = ntohs(serverinit.h);
al@1138 272 + G.cols = MIN(G.srv_cols, G.fb_cols);
al@1138 273 + G.rows = MIN(G.srv_rows, G.fb_rows);
al@1138 274 + G.mr = G.rows / 2;
al@1138 275 + G.mc = G.cols / 2;
al@1138 276 +
al@1138 277 + skip(ntohl(serverinit.len));
al@1138 278 + pixfmt_cmd.type = VNC_CLIENT_PIXFMT;
al@1138 279 + pixfmt_cmd.format.bigendian = 0;
al@1138 280 + pixfmt_cmd.format.truecolor = 1;
al@1138 281 + pixfmt_cmd.format.bpp =
al@1138 282 + pixfmt_cmd.format.depth = G.bpp << 3;
al@1138 283 + pixfmt_cmd.format.rmax = htons(G.nr - 1);
al@1138 284 + pixfmt_cmd.format.gmax = htons(G.ng - 1);
al@1138 285 + pixfmt_cmd.format.bmax = htons(G.nb - 1);
al@1138 286 + pixfmt_cmd.format.rshl = G.vinfo.red.offset;
al@1138 287 + pixfmt_cmd.format.gshl = G.vinfo.green.offset;
al@1138 288 + pixfmt_cmd.format.bshl = G.vinfo.blue.offset;
al@1138 289 + write(G.vnc_fd, &pixfmt_cmd, sizeof(pixfmt_cmd));
al@1138 290 +}
al@1138 291 +
al@1138 292 +static void vnc_refresh(int inc)
al@1138 293 +{
al@1138 294 + struct vnc_client_fbup fbup_req;
al@1138 295 + fbup_req.type = VNC_CLIENT_FBUP;
al@1138 296 + fbup_req.inc = inc;
al@1138 297 + fbup_req.x = htons(G.oc);
al@1138 298 + fbup_req.y = htons(G.or);
al@1138 299 + fbup_req.w = htons(G.oc + G.cols);
al@1138 300 + fbup_req.h = htons(G.or + G.rows);
al@1138 301 + write(G.vnc_fd, &fbup_req, sizeof(fbup_req));
al@1138 302 +}
al@1138 303 +
al@1138 304 +static void cleanup(void)
al@1138 305 +{
al@1138 306 + const char *reset = "\x1b[?25h" "\x1b[2J\x1b[H";
al@1138 307 + fb_free();
al@1138 308 + tcsetattr_stdin_TCSANOW(&G.term_orig);
al@1138 309 + write(STDOUT_FILENO, reset, strlen(reset));
al@1138 310 + if (ENABLE_FEATURE_CLEAN_UP) {
al@1138 311 + close(G.vnc_fd);
al@1138 312 + close(G.rat_fd);
al@1138 313 + }
al@1138 314 +}
al@1138 315 +
al@1138 316 +static void killed(int code) NORETURN;
al@1138 317 +static void killed(int code)
al@1138 318 +{
al@1138 319 + cleanup();
al@1138 320 + if (code > EXIT_FAILURE)
al@1138 321 + kill_myself_with_sig(code);
al@1138 322 + exit(code);
al@1138 323 +}
al@1138 324 +
al@1138 325 +static void vnc_event(void)
al@1138 326 +{
al@1138 327 + struct vnc_rect uprect;
al@1138 328 + union {
al@1138 329 + struct vnc_server_fbup fbup;
al@1138 330 + struct vnc_server_cuttext cuttext;
al@1138 331 + struct vnc_server_colormap colormap;
al@1138 332 + } msg;
al@1138 333 + int n;
al@1138 334 +
al@1138 335 + switch (xread_char(G.vnc_fd)) {
al@1138 336 + case VNC_SERVER_FBUP:
al@1138 337 + xread(G.vnc_fd, &msg.fbup.pad, sizeof(msg.fbup) - 1);
al@1138 338 + n = ntohs(msg.fbup.n);
al@1138 339 + while (n--) {
al@1138 340 + int x, y, w, h, l, i;
al@1138 341 + xread(G.vnc_fd, &uprect, sizeof(uprect));
al@1138 342 + if (uprect.enc != 0)
al@1138 343 + killed(1);
al@1138 344 + i = 0;
al@1138 345 + x = ntohs(uprect.x) - G.oc;
al@1138 346 + y = ntohs(uprect.y) - G.or;
al@1138 347 + w = ntohs(uprect.w);
al@1138 348 + h = ntohs(uprect.h);
al@1138 349 + l = MIN(w, G.cols - x);
al@1138 350 + if (x < 0) {
al@1138 351 + l = MIN(w + x, G.cols);
al@1138 352 + i = -x;
al@1138 353 + x = 0;
al@1138 354 + }
al@1138 355 + for (; h--; y++) {
al@1138 356 + int a, b, c = i;
al@1138 357 + for (a = b = 0; w > b; b += a, c = 0) {
al@1138 358 + int len;
al@1138 359 + a = MIN(w - b, MAXPIX);
al@1138 360 + len = MIN(a, l - b) - c;
al@1138 361 + xread(G.vnc_fd, line_buffer, a * G.bpp);
al@1138 362 + if (y >= 0 && y < G.rows && len > 0)
al@1138 363 + fb_set(y, x + b,
al@1138 364 + line_buffer + (c * G.bpp),
al@1138 365 + len);
al@1138 366 + }
al@1138 367 + }
al@1138 368 + }
al@1138 369 + break;
al@1138 370 + case VNC_SERVER_BELL:
al@1138 371 + break;
al@1138 372 + case VNC_SERVER_CUTTEXT:
al@1138 373 + xread(G.vnc_fd, &msg.cuttext.pad1, sizeof(msg.cuttext) - 1);
al@1138 374 + skip(ntohl(msg.cuttext.len));
al@1138 375 + break;
al@1138 376 + case VNC_SERVER_COLORMAP:
al@1138 377 + xread(G.vnc_fd, &msg.colormap.pad, sizeof(msg.colormap) - 1);
al@1138 378 + skip(ntohs(msg.colormap.n) * 3 * 2);
al@1138 379 + break;
al@1138 380 + default:
al@1138 381 + killed(1);
al@1138 382 + }
al@1138 383 +}
al@1138 384 +
al@1138 385 +static int update_scroll(struct scroll_data *s)
al@1138 386 +{
al@1138 387 + int shift = s->size / 5;
al@1138 388 + int max = s->srv_size - s->size;
al@1138 389 + int status = 0;
al@1138 390 + if (s->pos < s->offset) {
al@1138 391 + if ((s->offset -= shift) < 0)
al@1138 392 + s->offset = 0;
al@1138 393 + }
al@1138 394 + else if (s->pos >= s->offset + s->size && s->offset < max) {
al@1138 395 + if ((s->offset += shift) > max)
al@1138 396 + s->offset = max;
al@1138 397 + }
al@1138 398 + else status++;
al@1138 399 + s->pos = MAX(s->offset, MIN(s->offset + s->size - 1, s->pos));
al@1138 400 + return status;
al@1138 401 +}
al@1138 402 +
al@1138 403 +static void rat_event(void)
al@1138 404 +{
al@1138 405 + signed char ie[3];
al@1138 406 + struct vnc_client_ratevent me = {VNC_CLIENT_RATEVENT};
al@1138 407 + int mask = 0;
al@1138 408 + int refresh;
al@1138 409 +
al@1138 410 + xread(G.rat_fd, &ie, sizeof(ie));
al@1138 411 + G.mc += ie[1];
al@1138 412 + G.mr -= ie[2];
al@1138 413 + refresh = 2 - update_scroll(&G.scroll[0]) - update_scroll(&G.scroll[1]);
al@1138 414 + if (ie[0] & 0x01)
al@1138 415 + mask |= VNC_BUTTON1_MASK;
al@1138 416 + if (ie[0] & 0x04)
al@1138 417 + mask |= VNC_BUTTON2_MASK;
al@1138 418 + if (ie[0] & 0x02)
al@1138 419 + mask |= VNC_BUTTON3_MASK;
al@1138 420 + me.y = htons(G.mr);
al@1138 421 + me.x = htons(G.mc);
al@1138 422 + me.mask = mask;
al@1138 423 + write(G.vnc_fd, &me, sizeof(me));
al@1138 424 + if (refresh)
al@1138 425 + vnc_refresh(0);
al@1138 426 +}
al@1138 427 +
al@1138 428 +static int press(int key, int down)
al@1138 429 +{
al@1138 430 + struct vnc_client_keyevent ke = {VNC_CLIENT_KEYEVENT};
al@1138 431 + ke.key = htonl(key);
al@1138 432 + ke.down = down;
al@1138 433 + return write(G.vnc_fd, &ke, sizeof(ke));
al@1138 434 +}
al@1138 435 +
al@1138 436 +static void kbd_event(void)
al@1138 437 +{
al@1138 438 + char key[1024];
al@1138 439 + int i, nr;
al@1138 440 +
al@1138 441 + if ((nr = read(0, key, sizeof(key))) <= 0 )
al@1138 442 + killed(1);
al@1138 443 + for (i = 0; i < nr; i++) {
al@1138 444 + int k = -1;
al@1138 445 + int mod[4];
al@1138 446 + int nmod = 0;
al@1138 447 + switch (key[i]) {
al@1138 448 + case 0x08:
al@1138 449 + case 0x7f:
al@1138 450 + k = 0xff08;
al@1138 451 + break;
al@1138 452 + case 0x09:
al@1138 453 + k = 0xff09;
al@1138 454 + break;
al@1138 455 + case 0x1b:
al@1138 456 + if (G.oc + G.mc + G.or + G.mr == 0)
al@1138 457 + killed(0);
al@1138 458 + if (i + 2 < nr && key[i + 1] == '[') {
al@1138 459 + if (key[i + 2] == 'A')
al@1138 460 + k = 0xff52;
al@1138 461 + if (key[i + 2] == 'B')
al@1138 462 + k = 0xff54;
al@1138 463 + if (key[i + 2] == 'C')
al@1138 464 + k = 0xff53;
al@1138 465 + if (key[i + 2] == 'D')
al@1138 466 + k = 0xff51;
al@1138 467 + if (key[i + 2] == 'H')
al@1138 468 + k = 0xff50;
al@1138 469 + if (k > 0) {
al@1138 470 + i += 2;
al@1138 471 + break;
al@1138 472 + }
al@1138 473 + }
al@1138 474 + k = 0xff1b;
al@1138 475 + if (i + 1 < nr) {
al@1138 476 + mod[nmod++] = 0xffe9;
al@1138 477 + k = key[++i];
al@1138 478 + }
al@1138 479 + break;
al@1138 480 + case 0x0d:
al@1138 481 + k = 0xff0d;
al@1138 482 + break;
al@1138 483 + case 0x0c: /* ^L: redraw */
al@1138 484 + vnc_refresh(0);
al@1138 485 + default:
al@1138 486 + k = (unsigned char) key[i];
al@1138 487 + }
al@1138 488 + if ((k >= 'A' && k <= 'Z') || strchr(":\"<>?{}|+_()*&^%$#@!~", k))
al@1138 489 + mod[nmod++] = 0xffe1;
al@1138 490 + if (k >= 1 && k <= 26) {
al@1138 491 + k += 'a' - 1;
al@1138 492 + mod[nmod++] = 0xffe3;
al@1138 493 + }
al@1138 494 + if (k > 0) {
al@1138 495 + int j;
al@1138 496 + mod[nmod] = k;
al@1138 497 + for (j = 0; j <= nmod; j++)
al@1138 498 + press(mod[j], 1);
al@1138 499 + press(k, 0);
al@1138 500 + for (j = 0; j < nmod; j++)
al@1138 501 + press(mod[j], 0);
al@1138 502 + }
al@1138 503 + }
al@1138 504 +}
al@1138 505 +
al@1138 506 +static void term_setup(void)
al@1138 507 +{
al@1138 508 + struct termios termios;
al@1138 509 + const char *init = "\x1b[?25l" "\x1b[2J\x1b[H" "** fbvnc **";
al@1138 510 +
al@1138 511 + write(STDOUT_FILENO, init, strlen(init));
al@1138 512 + tcgetattr (STDIN_FILENO, &termios);
al@1138 513 + G.term_orig = termios;
al@1138 514 + cfmakeraw(&termios);
al@1138 515 + tcsetattr_stdin_TCSANOW(&termios);
al@1138 516 +}
al@1138 517 +
al@1138 518 +int fbvnc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
al@1138 519 +int fbvnc_main(int argc, char **argv)
al@1138 520 +{
al@1138 521 + char *host = (char *) "127.0.0.1";
al@1138 522 + int port, pending = 0;
al@1138 523 +
al@1138 524 + INIT_G();
al@1138 525 + if (argc >= 2)
al@1138 526 + host = argv[1];
al@1138 527 + port = bb_lookup_port((argc >= 3) ? argv[2] : "vnc", "tcp", 5900);
al@1138 528 + G.vnc_fd = create_and_connect_stream_or_die(host, port);
al@1138 529 + vnc_init();
al@1138 530 + G.rat_fd = open("/dev/input/mice", O_RDONLY);
al@1138 531 + term_setup();
al@1138 532 + atexit(cleanup);
al@1138 533 + bb_signals(BB_FATAL_SIGS, killed);
al@1138 534 +
al@1138 535 + G.ufds[0].events =
al@1138 536 + G.ufds[1].events =
al@1138 537 + G.ufds[2].events = POLLIN;
al@1138 538 + vnc_refresh(0);
al@1138 539 + while (1) {
al@1138 540 + int status = poll(G.ufds, 3, 500);
al@1138 541 + if (status == -1 && errno != EINTR)
al@1138 542 + killed(1);
al@1138 543 + if (!status)
al@1138 544 + continue;
al@1138 545 + if (G.ufds[0].revents & POLLIN)
al@1138 546 + kbd_event();
al@1138 547 + if (G.ufds[1].revents & POLLIN) {
al@1138 548 + vnc_event();
al@1138 549 + pending = 0;
al@1138 550 + }
al@1138 551 + if (G.ufds[2].revents & POLLIN)
al@1138 552 + rat_event();
al@1138 553 + if (!pending++)
al@1138 554 + vnc_refresh(1);
al@1138 555 + }
al@1138 556 +}
al@1138 557 --- /dev/null
al@1138 558 +++ busybox/util-linux/vnc.h
al@1138 559 @@ -0,0 +1,122 @@
al@1138 560 +#define VNC_CONN_FAILED 0
al@1138 561 +#define VNC_CONN_NOAUTH 1
al@1138 562 +#define VNC_CONN_AUTH 2
al@1138 563 +
al@1138 564 +#define VNC_AUTH_OK 0
al@1138 565 +#define VNC_AUTH_FAILED 1
al@1138 566 +#define VNC_AUTH_TOOMANY 2
al@1138 567 +
al@1138 568 +#define VNC_SERVER_FBUP 0
al@1138 569 +#define VNC_SERVER_COLORMAP 1
al@1138 570 +#define VNC_SERVER_BELL 2
al@1138 571 +#define VNC_SERVER_CUTTEXT 3
al@1138 572 +
al@1138 573 +#define VNC_CLIENT_PIXFMT 0
al@1138 574 +#define VNC_CLIENT_COLORMAP 1
al@1138 575 +#define VNC_CLIENT_SETENC 2
al@1138 576 +#define VNC_CLIENT_FBUP 3
al@1138 577 +#define VNC_CLIENT_KEYEVENT 4
al@1138 578 +#define VNC_CLIENT_RATEVENT 5
al@1138 579 +#define VNC_CLIENT_CUTTEXT 6
al@1138 580 +
al@1138 581 +#define VNC_ENC_RAW 0
al@1138 582 +#define VNC_ENC_COPYRECT 1
al@1138 583 +#define VNC_ENC_RRE 2
al@1138 584 +#define VNC_ENC_CORRE 4
al@1138 585 +#define VNC_ENC_HEXTILE 5
al@1138 586 +
al@1138 587 +#define VNC_BUTTON1_MASK 0x1
al@1138 588 +#define VNC_BUTTON2_MASK 0x2
al@1138 589 +#define VNC_BUTTON3_MASK 0x4
al@1138 590 +
al@1138 591 +typedef unsigned char u8;
al@1138 592 +typedef unsigned short u16;
al@1138 593 +typedef unsigned int u32;
al@1138 594 +
al@1138 595 +struct vnc_pixelfmt {
al@1138 596 + u8 bpp;
al@1138 597 + u8 depth;
al@1138 598 + u8 bigendian;
al@1138 599 + u8 truecolor;
al@1138 600 + u16 rmax;
al@1138 601 + u16 gmax;
al@1138 602 + u16 bmax;
al@1138 603 + u8 rshl;
al@1138 604 + u8 gshl;
al@1138 605 + u8 bshl;
al@1138 606 +
al@1138 607 + u8 pad1;
al@1138 608 + u16 pad2;
al@1138 609 +};
al@1138 610 +
al@1138 611 +struct vnc_client_init {
al@1138 612 + u8 shared;
al@1138 613 +};
al@1138 614 +
al@1138 615 +struct vnc_server_init {
al@1138 616 + u16 w;
al@1138 617 + u16 h;
al@1138 618 + struct vnc_pixelfmt fmt;
al@1138 619 + u32 len;
al@1138 620 + /* char name[len]; */
al@1138 621 +};
al@1138 622 +
al@1138 623 +struct vnc_rect {
al@1138 624 + u16 x, y;
al@1138 625 + u16 w, h;
al@1138 626 + u32 enc;
al@1138 627 + /* rect bytes */
al@1138 628 +};
al@1138 629 +
al@1138 630 +struct vnc_server_fbup {
al@1138 631 + u8 type;
al@1138 632 + u8 pad;
al@1138 633 + u16 n;
al@1138 634 + /* struct vnc_rect rects[n]; */
al@1138 635 +};
al@1138 636 +
al@1138 637 +struct vnc_server_cuttext {
al@1138 638 + u8 type;
al@1138 639 + u8 pad1;
al@1138 640 + u16 pad2;
al@1138 641 + u32 len;
al@1138 642 + /* char text[length] */
al@1138 643 +};
al@1138 644 +
al@1138 645 +struct vnc_server_colormap {
al@1138 646 + u8 type;
al@1138 647 + u8 pad;
al@1138 648 + u16 first;
al@1138 649 + u16 n;
al@1138 650 + /* u8 colors[n * 3 * 2]; */
al@1138 651 +};
al@1138 652 +
al@1138 653 +struct vnc_client_pixelfmt {
al@1138 654 + u8 type;
al@1138 655 + u8 pad1;
al@1138 656 + u16 pad2;
al@1138 657 + struct vnc_pixelfmt format;
al@1138 658 +};
al@1138 659 +
al@1138 660 +struct vnc_client_fbup {
al@1138 661 + u8 type;
al@1138 662 + u8 inc;
al@1138 663 + u16 x;
al@1138 664 + u16 y;
al@1138 665 + u16 w;
al@1138 666 + u16 h;
al@1138 667 +};
al@1138 668 +
al@1138 669 +struct vnc_client_keyevent {
al@1138 670 + u8 type;
al@1138 671 + u8 down;
al@1138 672 + u16 pad;
al@1138 673 + u32 key;
al@1138 674 +};
al@1138 675 +
al@1138 676 +struct vnc_client_ratevent {
al@1138 677 + u8 type;
al@1138 678 + u8 mask;
al@1138 679 + u16 x;
al@1138 680 + u16 y;
al@1138 681 +};