wok-6.x view busybox/stuff/busybox-1.23-fbvnc.u @ rev 19008

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