direct-io.hg

view tools/ioemu/vnc.c @ 11624:bd811e94d293

[HVM][VNC] Fix typo.

Signed-off-by: Steven Smith <sos22@cam.ac.uk>
author Steven Smith <ssmith@xensource.com>
date Tue Sep 26 19:50:07 2006 +0100 (2006-09-26)
parents a1154318cd80
children a95dfbc8dca8
line source
1 /*
2 * QEMU VNC display driver
3 *
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
6 * Copyright (C) 2006 Christian Limpach <Christian.Limpach@xensource.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
27 #include "vl.h"
28 #include "qemu_socket.h"
29 #include <assert.h>
31 /* The refresh interval starts at BASE. If we scan the buffer and
32 find no change, we increase by INC, up to MAX. If the mouse moves
33 or we get a keypress, the interval is set back to BASE. If we find
34 an update, halve the interval.
36 All times in milliseconds. */
37 #define VNC_REFRESH_INTERVAL_BASE 30
38 #define VNC_REFRESH_INTERVAL_INC 50
39 #define VNC_REFRESH_INTERVAL_MAX 2000
41 /* Wait at most one second between updates, so that we can detect a
42 minimised vncviewer reasonably quickly. */
43 #define VNC_MAX_UPDATE_INTERVAL 5000
45 #include "vnc_keysym.h"
46 #include "keymaps.c"
48 #define XK_MISCELLANY
49 #define XK_LATIN1
50 #include <X11/keysymdef.h>
52 typedef struct Buffer
53 {
54 size_t capacity;
55 size_t offset;
56 char *buffer;
57 } Buffer;
59 typedef struct VncState VncState;
61 typedef int VncReadEvent(VncState *vs, char *data, size_t len);
63 typedef void VncWritePixels(VncState *vs, void *data, int size);
65 typedef void VncSendHextileTile(VncState *vs,
66 int x, int y, int w, int h,
67 uint32_t *last_bg,
68 uint32_t *last_fg,
69 int *has_bg, int *has_fg);
71 #if 0
72 #define VNC_MAX_WIDTH 2048
73 #define VNC_MAX_HEIGHT 2048
74 #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
75 #endif
77 struct VncState
78 {
79 QEMUTimer *timer;
80 int timer_interval;
81 int64_t last_update_time;
82 int lsock;
83 int csock;
84 DisplayState *ds;
85 int width;
86 int height;
87 uint64_t *dirty_row; /* screen regions which are possibly dirty */
88 int dirty_pixel_shift;
89 uint64_t *update_row; /* outstanding updates */
90 int has_update; /* there's outstanding updates in the
91 * visible area */
92 char *old_data;
93 int depth; /* internal VNC frame buffer byte per pixel */
94 int has_resize;
95 int has_hextile;
96 Buffer output;
97 Buffer input;
98 kbd_layout_t *kbd_layout;
99 /* current output mode information */
100 VncWritePixels *write_pixels;
101 VncSendHextileTile *send_hextile_tile;
102 int pix_bpp, pix_big_endian;
103 int red_shift, red_max, red_shift1;
104 int green_shift, green_max, green_shift1;
105 int blue_shift, blue_max, blue_shift1;
107 VncReadEvent *read_handler;
108 size_t read_handler_expect;
110 int visible_x;
111 int visible_y;
112 int visible_w;
113 int visible_h;
115 int ctl_keys; /* Ctrl+Alt starts calibration */
116 };
118 #define DIRTY_PIXEL_BITS 64
119 #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
120 #define X2DP_UP(vs, x) \
121 (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
122 #define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
124 /* TODO
125 1) Get the queue working for IO.
126 2) there is some weirdness when using the -S option (the screen is grey
127 and not totally invalidated
128 */
130 static void vnc_write(VncState *vs, const void *data, size_t len);
131 static void vnc_write_u32(VncState *vs, uint32_t value);
132 static void vnc_write_s32(VncState *vs, int32_t value);
133 static void vnc_write_u16(VncState *vs, uint16_t value);
134 static void vnc_write_u8(VncState *vs, uint8_t value);
135 static void vnc_flush(VncState *vs);
136 static void _vnc_update_client(void *opaque);
137 static void vnc_update_client(void *opaque);
138 static void vnc_client_read(void *opaque);
139 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
141 #if 0
142 static inline void vnc_set_bit(uint32_t *d, int k)
143 {
144 d[k >> 5] |= 1 << (k & 0x1f);
145 }
147 static inline void vnc_clear_bit(uint32_t *d, int k)
148 {
149 d[k >> 5] &= ~(1 << (k & 0x1f));
150 }
152 static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
153 {
154 int j;
156 j = 0;
157 while (n >= 32) {
158 d[j++] = -1;
159 n -= 32;
160 }
161 if (n > 0)
162 d[j++] = (1 << n) - 1;
163 while (j < nb_words)
164 d[j++] = 0;
165 }
167 static inline int vnc_get_bit(const uint32_t *d, int k)
168 {
169 return (d[k >> 5] >> (k & 0x1f)) & 1;
170 }
172 static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
173 int nb_words)
174 {
175 int i;
176 for(i = 0; i < nb_words; i++) {
177 if ((d1[i] & d2[i]) != 0)
178 return 1;
179 }
180 return 0;
181 }
182 #endif
184 static void set_bits_in_row(VncState *vs, uint64_t *row,
185 int x, int y, int w, int h)
186 {
187 int x1, x2;
188 uint64_t mask;
190 if (w == 0)
191 return;
193 x1 = X2DP_DOWN(vs, x);
194 x2 = X2DP_UP(vs, x + w);
196 if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS)
197 mask = ((1ULL << (x2 - x1)) - 1) << x1;
198 else
199 mask = ~(0ULL);
201 h += y;
202 for (; y < h; y++)
203 row[y] |= mask;
204 }
206 static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
207 {
208 VncState *vs = ds->opaque;
210 set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
211 }
213 static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
214 int32_t encoding)
215 {
216 vnc_write_u16(vs, x);
217 vnc_write_u16(vs, y);
218 vnc_write_u16(vs, w);
219 vnc_write_u16(vs, h);
221 vnc_write_s32(vs, encoding);
222 }
224 static void vnc_dpy_resize(DisplayState *ds, int w, int h)
225 {
226 VncState *vs = ds->opaque;
227 int o;
229 ds->data = realloc(ds->data, w * h * vs->depth);
230 vs->old_data = realloc(vs->old_data, w * h * vs->depth);
231 vs->dirty_row = realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
232 vs->update_row = realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
234 if (ds->data == NULL || vs->old_data == NULL ||
235 vs->dirty_row == NULL || vs->update_row == NULL) {
236 fprintf(stderr, "vnc: memory allocation failed\n");
237 exit(1);
238 }
240 if (ds->depth != vs->depth * 8) {
241 ds->depth = vs->depth * 8;
242 set_color_table(ds);
243 }
244 ds->width = w;
245 ds->height = h;
246 ds->linesize = w * vs->depth;
247 if (vs->csock != -1 && vs->has_resize) {
248 vnc_write_u8(vs, 0); /* msg id */
249 vnc_write_u8(vs, 0);
250 vnc_write_u16(vs, 1); /* number of rects */
251 vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
252 vnc_flush(vs);
253 vs->width = ds->width;
254 vs->height = ds->height;
255 }
256 vs->dirty_pixel_shift = 0;
257 for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
258 vs->dirty_pixel_shift++;
259 framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
260 }
262 /* fastest code */
263 static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
264 {
265 vnc_write(vs, pixels, size);
266 }
268 /* slowest but generic code. */
269 static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
270 {
271 unsigned int r, g, b;
273 r = (v >> vs->red_shift1) & vs->red_max;
274 g = (v >> vs->green_shift1) & vs->green_max;
275 b = (v >> vs->blue_shift1) & vs->blue_max;
276 v = (r << vs->red_shift) |
277 (g << vs->green_shift) |
278 (b << vs->blue_shift);
279 switch(vs->pix_bpp) {
280 case 1:
281 buf[0] = v;
282 break;
283 case 2:
284 if (vs->pix_big_endian) {
285 buf[0] = v >> 8;
286 buf[1] = v;
287 } else {
288 buf[1] = v >> 8;
289 buf[0] = v;
290 }
291 break;
292 default:
293 case 4:
294 if (vs->pix_big_endian) {
295 buf[0] = v >> 24;
296 buf[1] = v >> 16;
297 buf[2] = v >> 8;
298 buf[3] = v;
299 } else {
300 buf[3] = v >> 24;
301 buf[2] = v >> 16;
302 buf[1] = v >> 8;
303 buf[0] = v;
304 }
305 break;
306 }
307 }
309 static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
310 {
311 uint32_t *pixels = pixels1;
312 uint8_t buf[4];
313 int n, i;
315 n = size >> 2;
316 for(i = 0; i < n; i++) {
317 vnc_convert_pixel(vs, buf, pixels[i]);
318 vnc_write(vs, buf, vs->pix_bpp);
319 }
320 }
322 static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
323 {
324 int i;
325 char *row;
327 vnc_framebuffer_update(vs, x, y, w, h, 0);
329 row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
330 for (i = 0; i < h; i++) {
331 vs->write_pixels(vs, row, w * vs->depth);
332 row += vs->ds->linesize;
333 }
334 }
336 static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
337 {
338 ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
339 ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
340 }
342 #define BPP 8
343 #include "vnchextile.h"
344 #undef BPP
346 #define BPP 16
347 #include "vnchextile.h"
348 #undef BPP
350 #define BPP 32
351 #include "vnchextile.h"
352 #undef BPP
354 #define GENERIC
355 #define BPP 32
356 #include "vnchextile.h"
357 #undef BPP
358 #undef GENERIC
360 static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
361 {
362 int i, j;
363 int has_fg, has_bg;
364 uint32_t last_fg32, last_bg32;
366 vnc_framebuffer_update(vs, x, y, w, h, 5);
368 has_fg = has_bg = 0;
369 for (j = y; j < (y + h); j += 16) {
370 for (i = x; i < (x + w); i += 16) {
371 vs->send_hextile_tile(vs, i, j,
372 MIN(16, x + w - i), MIN(16, y + h - j),
373 &last_bg32, &last_fg32, &has_bg, &has_fg);
374 }
375 }
376 }
378 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
379 {
380 if (vs->has_hextile)
381 send_framebuffer_update_hextile(vs, x, y, w, h);
382 else
383 send_framebuffer_update_raw(vs, x, y, w, h);
384 }
386 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
387 {
388 int src, dst;
389 char *src_row;
390 char *dst_row;
391 char *old_row;
392 int y = 0;
393 int pitch = ds->linesize;
394 VncState *vs = ds->opaque;
395 int updating_client = 1;
397 if (src_x < vs->visible_x || src_y < vs->visible_y ||
398 dst_x < vs->visible_x || dst_y < vs->visible_y ||
399 (src_x + w) > (vs->visible_x + vs->visible_w) ||
400 (src_y + h) > (vs->visible_y + vs->visible_h) ||
401 (dst_x + w) > (vs->visible_x + vs->visible_w) ||
402 (dst_y + h) > (vs->visible_y + vs->visible_h))
403 updating_client = 0;
405 if (updating_client)
406 _vnc_update_client(vs);
408 if (dst_y > src_y) {
409 y = h - 1;
410 pitch = -pitch;
411 }
413 src = (ds->linesize * (src_y + y) + vs->depth * src_x);
414 dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
416 src_row = ds->data + src;
417 dst_row = ds->data + dst;
418 old_row = vs->old_data + dst;
420 for (y = 0; y < h; y++) {
421 memmove(old_row, src_row, w * vs->depth);
422 memmove(dst_row, src_row, w * vs->depth);
423 src_row += pitch;
424 dst_row += pitch;
425 old_row += pitch;
426 }
428 if (updating_client && vs->csock != -1 && !vs->has_update) {
429 vnc_write_u8(vs, 0); /* msg id */
430 vnc_write_u8(vs, 0);
431 vnc_write_u16(vs, 1); /* number of rects */
432 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
433 vnc_write_u16(vs, src_x);
434 vnc_write_u16(vs, src_y);
435 vnc_flush(vs);
436 } else
437 framebuffer_set_updated(vs, dst_x, dst_y, w, h);
438 }
440 static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x)
441 {
442 int h;
444 for (h = 1; y + h < maxy; h++) {
445 int tmp_x;
446 if (!(vs->update_row[y + h] & (1ULL << last_x)))
447 break;
448 for (tmp_x = last_x; tmp_x < x; tmp_x++)
449 vs->update_row[y + h] &= ~(1ULL << tmp_x);
450 }
452 return h;
453 }
455 static void _vnc_update_client(void *opaque)
456 {
457 VncState *vs = opaque;
458 int64_t now;
459 int y;
460 char *row;
461 char *old_row;
462 uint64_t width_mask;
463 int n_rectangles;
464 int saved_offset;
465 int maxx, maxy;
466 int tile_bytes = vs->depth * DP2X(vs, 1);
468 if (vs->csock == -1)
469 return;
471 now = qemu_get_clock(rt_clock);
473 if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
474 width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
475 else
476 width_mask = ~(0ULL);
478 /* Walk through the dirty map and eliminate tiles that really
479 aren't dirty */
480 row = vs->ds->data;
481 old_row = vs->old_data;
483 for (y = 0; y < vs->ds->height; y++) {
484 if (vs->dirty_row[y] & width_mask) {
485 int x;
486 char *ptr, *old_ptr;
488 ptr = row;
489 old_ptr = old_row;
491 for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
492 if (vs->dirty_row[y] & (1ULL << x)) {
493 if (memcmp(old_ptr, ptr, tile_bytes)) {
494 vs->has_update = 1;
495 vs->update_row[y] |= (1ULL << x);
496 memcpy(old_ptr, ptr, tile_bytes);
497 }
498 vs->dirty_row[y] &= ~(1ULL << x);
499 }
501 ptr += tile_bytes;
502 old_ptr += tile_bytes;
503 }
504 }
506 row += vs->ds->linesize;
507 old_row += vs->ds->linesize;
508 }
510 if (!vs->has_update || vs->visible_y >= vs->ds->height ||
511 vs->visible_x >= vs->ds->width)
512 goto backoff;
514 /* Count rectangles */
515 n_rectangles = 0;
516 vnc_write_u8(vs, 0); /* msg id */
517 vnc_write_u8(vs, 0);
518 saved_offset = vs->output.offset;
519 vnc_write_u16(vs, 0);
521 maxy = vs->visible_y + vs->visible_h;
522 if (maxy > vs->ds->height)
523 maxy = vs->ds->height;
524 maxx = vs->visible_x + vs->visible_w;
525 if (maxx > vs->ds->width)
526 maxx = vs->ds->width;
528 for (y = vs->visible_y; y < maxy; y++) {
529 int x;
530 int last_x = -1;
531 for (x = X2DP_DOWN(vs, vs->visible_x);
532 x < X2DP_UP(vs, maxx); x++) {
533 if (vs->update_row[y] & (1ULL << x)) {
534 if (last_x == -1)
535 last_x = x;
536 vs->update_row[y] &= ~(1ULL << x);
537 } else {
538 if (last_x != -1) {
539 int h = find_update_height(vs, y, maxy, last_x, x);
540 if (h != 0) {
541 send_framebuffer_update(vs, DP2X(vs, last_x), y,
542 DP2X(vs, (x - last_x)), h);
543 n_rectangles++;
544 }
545 }
546 last_x = -1;
547 }
548 }
549 if (last_x != -1) {
550 int h = find_update_height(vs, y, maxy, last_x, x);
551 if (h != 0) {
552 send_framebuffer_update(vs, DP2X(vs, last_x), y,
553 DP2X(vs, (x - last_x)), h);
554 n_rectangles++;
555 }
556 }
557 }
558 vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
559 vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
561 if (n_rectangles == 0)
562 goto backoff;
564 vs->has_update = 0;
565 vnc_flush(vs);
566 vs->last_update_time = now;
568 vs->timer_interval /= 2;
569 if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)
570 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
572 return;
574 backoff:
575 /* No update -> back off a bit */
576 vs->timer_interval += VNC_REFRESH_INTERVAL_INC;
577 if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) {
578 vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;
579 if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {
580 /* Send a null update. If the client is no longer
581 interested (e.g. minimised) it'll ignore this, and we
582 can stop scanning the buffer until it sends another
583 update request. */
584 /* It turns out that there's a bug in realvncviewer 4.1.2
585 which means that if you send a proper null update (with
586 no update rectangles), it gets a bit out of sync and
587 never sends any further requests, regardless of whether
588 it needs one or not. Fix this by sending a single 1x1
589 update rectangle instead. */
590 vnc_write_u8(vs, 0);
591 vnc_write_u8(vs, 0);
592 vnc_write_u16(vs, 1);
593 send_framebuffer_update(vs, 0, 0, 1, 1);
594 vnc_flush(vs);
595 vs->last_update_time = now;
596 return;
597 }
598 }
599 qemu_mod_timer(vs->timer, now + vs->timer_interval);
600 return;
601 }
603 static void vnc_update_client(void *opaque)
604 {
605 VncState *vs = opaque;
607 vs->ds->dpy_refresh(vs->ds);
608 _vnc_update_client(vs);
609 }
611 static void vnc_timer_init(VncState *vs)
612 {
613 if (vs->timer == NULL) {
614 vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
615 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
616 }
617 }
619 static void vnc_dpy_refresh(DisplayState *ds)
620 {
621 vga_hw_update();
622 }
624 static int vnc_listen_poll(void *opaque)
625 {
626 VncState *vs = opaque;
627 if (vs->csock == -1)
628 return 1;
629 return 0;
630 }
632 static void buffer_reserve(Buffer *buffer, size_t len)
633 {
634 if ((buffer->capacity - buffer->offset) < len) {
635 buffer->capacity += (len + 1024);
636 buffer->buffer = realloc(buffer->buffer, buffer->capacity);
637 if (buffer->buffer == NULL) {
638 fprintf(stderr, "vnc: out of memory\n");
639 exit(1);
640 }
641 }
642 }
644 static int buffer_empty(Buffer *buffer)
645 {
646 return buffer->offset == 0;
647 }
649 static char *buffer_end(Buffer *buffer)
650 {
651 return buffer->buffer + buffer->offset;
652 }
654 static void buffer_reset(Buffer *buffer)
655 {
656 buffer->offset = 0;
657 }
659 static void buffer_append(Buffer *buffer, const void *data, size_t len)
660 {
661 memcpy(buffer->buffer + buffer->offset, data, len);
662 buffer->offset += len;
663 }
665 static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
666 {
667 if (ret == 0 || ret == -1) {
668 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
669 return 0;
671 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
672 closesocket(vs->csock);
673 vs->csock = -1;
674 buffer_reset(&vs->input);
675 buffer_reset(&vs->output);
676 return 0;
677 }
678 return ret;
679 }
681 static void vnc_client_error(VncState *vs)
682 {
683 vnc_client_io_error(vs, -1, EINVAL);
684 }
686 static void vnc_client_write(void *opaque)
687 {
688 long ret;
689 VncState *vs = opaque;
691 ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
692 ret = vnc_client_io_error(vs, ret, socket_error());
693 if (!ret)
694 return;
696 memmove(vs->output.buffer, vs->output.buffer + ret,
697 vs->output.offset - ret);
698 vs->output.offset -= ret;
700 if (vs->output.offset == 0)
701 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
702 }
704 static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
705 {
706 vs->read_handler = func;
707 vs->read_handler_expect = expecting;
708 }
710 static void vnc_client_read(void *opaque)
711 {
712 VncState *vs = opaque;
713 long ret;
715 buffer_reserve(&vs->input, 4096);
717 ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
718 ret = vnc_client_io_error(vs, ret, socket_error());
719 if (!ret)
720 return;
722 vs->input.offset += ret;
724 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
725 size_t len = vs->read_handler_expect;
726 int ret;
728 ret = vs->read_handler(vs, vs->input.buffer, len);
729 if (vs->csock == -1)
730 return;
732 if (!ret) {
733 memmove(vs->input.buffer, vs->input.buffer + len,
734 vs->input.offset - len);
735 vs->input.offset -= len;
736 } else {
737 assert(ret > vs->read_handler_expect);
738 vs->read_handler_expect = ret;
739 }
740 }
741 }
743 static void vnc_write(VncState *vs, const void *data, size_t len)
744 {
745 buffer_reserve(&vs->output, len);
747 if (buffer_empty(&vs->output))
748 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read,
749 vnc_client_write, vs);
751 buffer_append(&vs->output, data, len);
752 }
754 static void vnc_write_s32(VncState *vs, int32_t value)
755 {
756 vnc_write_u32(vs, *(uint32_t *)&value);
757 }
759 static void vnc_write_u32(VncState *vs, uint32_t value)
760 {
761 uint8_t buf[4];
763 buf[0] = (value >> 24) & 0xFF;
764 buf[1] = (value >> 16) & 0xFF;
765 buf[2] = (value >> 8) & 0xFF;
766 buf[3] = value & 0xFF;
768 vnc_write(vs, buf, 4);
769 }
771 static void vnc_write_u16(VncState *vs, uint16_t value)
772 {
773 char buf[2];
775 buf[0] = (value >> 8) & 0xFF;
776 buf[1] = value & 0xFF;
778 vnc_write(vs, buf, 2);
779 }
781 static void vnc_write_u8(VncState *vs, uint8_t value)
782 {
783 vnc_write(vs, (char *)&value, 1);
784 }
786 static void vnc_flush(VncState *vs)
787 {
788 if (vs->output.offset)
789 vnc_client_write(vs);
790 }
792 static uint8_t read_u8(char *data, size_t offset)
793 {
794 return data[offset];
795 }
797 static uint16_t read_u16(char *data, size_t offset)
798 {
799 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
800 }
802 static int32_t read_s32(char *data, size_t offset)
803 {
804 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
805 (data[offset + 2] << 8) | data[offset + 3]);
806 }
808 static uint32_t read_u32(char *data, size_t offset)
809 {
810 return ((data[offset] << 24) | (data[offset + 1] << 16) |
811 (data[offset + 2] << 8) | data[offset + 3]);
812 }
814 static void client_cut_text(VncState *vs, size_t len, char *text)
815 {
816 }
818 static void pointer_event(VncState *vs, int button_mask, int x, int y)
819 {
820 int buttons = 0;
821 int dz = 0;
823 if (button_mask & 0x01)
824 buttons |= MOUSE_EVENT_LBUTTON;
825 if (button_mask & 0x02)
826 buttons |= MOUSE_EVENT_MBUTTON;
827 if (button_mask & 0x04)
828 buttons |= MOUSE_EVENT_RBUTTON;
829 if (button_mask & 0x08)
830 dz = -1;
831 if (button_mask & 0x10)
832 dz = 1;
834 if (kbd_mouse_is_absolute()) {
835 kbd_mouse_event(x * 0x7FFF / vs->ds->width,
836 y * 0x7FFF / vs->ds->height,
837 dz, buttons);
838 } else {
839 static int last_x = -1;
840 static int last_y = -1;
842 if (last_x != -1)
843 kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
845 last_x = x;
846 last_y = y;
847 }
848 }
850 static void do_key_event(VncState *vs, int down, uint32_t sym)
851 {
852 sym &= 0xFFFF;
854 if (is_graphic_console()) {
855 int keycode;
857 keycode = keysym2scancode(vs->kbd_layout, sym);
858 if (keycode & 0x80)
859 kbd_put_keycode(0xe0);
860 if (down)
861 kbd_put_keycode(keycode & 0x7f);
862 else
863 kbd_put_keycode(keycode | 0x80);
864 } else if (down) {
865 int qemu_keysym = 0;
867 if (sym <= 128) /* normal ascii */
868 qemu_keysym = sym;
869 else {
870 switch (sym) {
871 case XK_Up: qemu_keysym = QEMU_KEY_UP; break;
872 case XK_Down: qemu_keysym = QEMU_KEY_DOWN; break;
873 case XK_Left: qemu_keysym = QEMU_KEY_LEFT; break;
874 case XK_Right: qemu_keysym = QEMU_KEY_RIGHT; break;
875 case XK_Home: qemu_keysym = QEMU_KEY_HOME; break;
876 case XK_End: qemu_keysym = QEMU_KEY_END; break;
877 case XK_Page_Up: qemu_keysym = QEMU_KEY_PAGEUP; break;
878 case XK_Page_Down: qemu_keysym = QEMU_KEY_PAGEDOWN; break;
879 case XK_BackSpace: qemu_keysym = QEMU_KEY_BACKSPACE; break;
880 case XK_Delete: qemu_keysym = QEMU_KEY_DELETE; break;
881 case XK_Return:
882 case XK_Linefeed: qemu_keysym = sym; break;
883 default: break;
884 }
885 }
886 if (qemu_keysym != 0)
887 kbd_put_keysym(qemu_keysym);
888 }
890 if (down) {
891 switch (sym) {
892 case XK_Control_L:
893 vs->ctl_keys |= 1;
894 break;
896 case XK_Alt_L:
897 vs->ctl_keys |= 2;
898 break;
900 default:
901 break;
902 }
903 } else {
904 switch (sym) {
905 case XK_Control_L:
906 vs->ctl_keys &= ~1;
907 break;
909 case XK_Alt_L:
910 vs->ctl_keys &= ~2;
911 break;
913 case XK_1 ... XK_9:
914 if ((vs->ctl_keys & 3) != 3)
915 break;
917 console_select(sym - XK_1);
918 if (is_graphic_console()) {
919 /* tell the vga console to redisplay itself */
920 vga_hw_invalidate();
921 vnc_dpy_update(vs->ds, 0, 0, vs->ds->width, vs->ds->height);
922 }
923 break;
924 }
925 }
926 }
928 static void key_event(VncState *vs, int down, uint32_t sym)
929 {
930 if (sym >= 'A' && sym <= 'Z')
931 sym = sym - 'A' + 'a';
932 do_key_event(vs, down, sym);
933 }
935 static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
936 {
938 set_bits_in_row(vs, vs->update_row, x, y, w, h);
940 vs->has_update = 1;
941 }
943 static void framebuffer_update_request(VncState *vs, int incremental,
944 int x_position, int y_position,
945 int w, int h)
946 {
947 if (!incremental)
948 framebuffer_set_updated(vs, x_position, y_position, w, h);
949 vs->visible_x = x_position;
950 vs->visible_y = y_position;
951 vs->visible_w = w;
952 vs->visible_h = h;
954 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
955 }
957 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
958 {
959 int i;
961 vs->has_hextile = 0;
962 vs->has_resize = 0;
963 vs->ds->dpy_copy = NULL;
965 for (i = n_encodings - 1; i >= 0; i--) {
966 switch (encodings[i]) {
967 case 0: /* Raw */
968 vs->has_hextile = 0;
969 break;
970 case 1: /* CopyRect */
971 vs->ds->dpy_copy = vnc_copy;
972 break;
973 case 5: /* Hextile */
974 vs->has_hextile = 1;
975 break;
976 case -223: /* DesktopResize */
977 vs->has_resize = 1;
978 break;
979 default:
980 break;
981 }
982 }
983 }
985 static int compute_nbits(unsigned int val)
986 {
987 int n;
988 n = 0;
989 while (val != 0) {
990 n++;
991 val >>= 1;
992 }
993 return n;
994 }
996 static void set_pixel_format(VncState *vs,
997 int bits_per_pixel, int depth,
998 int big_endian_flag, int true_color_flag,
999 int red_max, int green_max, int blue_max,
1000 int red_shift, int green_shift, int blue_shift)
1002 int host_big_endian_flag;
1004 #ifdef WORDS_BIGENDIAN
1005 host_big_endian_flag = 1;
1006 #else
1007 host_big_endian_flag = 0;
1008 #endif
1009 if (!true_color_flag) {
1010 fail:
1011 vnc_client_error(vs);
1012 return;
1014 if (bits_per_pixel == 32 &&
1015 host_big_endian_flag == big_endian_flag &&
1016 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1017 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1018 vs->depth = 4;
1019 vs->write_pixels = vnc_write_pixels_copy;
1020 vs->send_hextile_tile = send_hextile_tile_32;
1021 } else
1022 if (bits_per_pixel == 16 &&
1023 host_big_endian_flag == big_endian_flag &&
1024 red_max == 31 && green_max == 63 && blue_max == 31 &&
1025 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1026 vs->depth = 2;
1027 vs->write_pixels = vnc_write_pixels_copy;
1028 vs->send_hextile_tile = send_hextile_tile_16;
1029 } else
1030 if (bits_per_pixel == 8 &&
1031 red_max == 7 && green_max == 7 && blue_max == 3 &&
1032 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1033 vs->depth = 1;
1034 vs->write_pixels = vnc_write_pixels_copy;
1035 vs->send_hextile_tile = send_hextile_tile_8;
1036 } else
1038 /* generic and slower case */
1039 if (bits_per_pixel != 8 &&
1040 bits_per_pixel != 16 &&
1041 bits_per_pixel != 32)
1042 goto fail;
1043 vs->depth = 4;
1044 vs->red_shift = red_shift;
1045 vs->red_max = red_max;
1046 vs->red_shift1 = 24 - compute_nbits(red_max);
1047 vs->green_shift = green_shift;
1048 vs->green_max = green_max;
1049 vs->green_shift1 = 16 - compute_nbits(green_max);
1050 vs->blue_shift = blue_shift;
1051 vs->blue_max = blue_max;
1052 vs->blue_shift1 = 8 - compute_nbits(blue_max);
1053 vs->pix_bpp = bits_per_pixel / 8;
1054 vs->pix_big_endian = big_endian_flag;
1055 vs->write_pixels = vnc_write_pixels_generic;
1056 vs->send_hextile_tile = send_hextile_tile_generic;
1059 vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
1061 vga_hw_invalidate();
1062 vga_hw_update();
1065 static int protocol_client_msg(VncState *vs, char *data, size_t len)
1067 int i;
1068 uint16_t limit;
1069 int64_t now;
1071 switch (data[0]) {
1072 case 0:
1073 if (len == 1)
1074 return 20;
1076 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1077 read_u8(data, 6), read_u8(data, 7),
1078 read_u16(data, 8), read_u16(data, 10),
1079 read_u16(data, 12), read_u8(data, 14),
1080 read_u8(data, 15), read_u8(data, 16));
1081 break;
1082 case 2:
1083 if (len == 1)
1084 return 4;
1086 if (len == 4) {
1087 uint16_t v;
1088 v = read_u16(data, 2);
1089 if (v)
1090 return 4 + v * 4;
1093 limit = read_u16(data, 2);
1094 for (i = 0; i < limit; i++) {
1095 int32_t val = read_s32(data, 4 + (i * 4));
1096 memcpy(data + 4 + (i * 4), &val, sizeof(val));
1099 set_encodings(vs, (int32_t *)(data + 4), limit);
1100 break;
1101 case 3:
1102 if (len == 1)
1103 return 10;
1105 framebuffer_update_request(vs,
1106 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1107 read_u16(data, 6), read_u16(data, 8));
1108 break;
1109 case 4:
1110 if (len == 1)
1111 return 8;
1113 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1114 qemu_advance_timer(vs->timer,
1115 qemu_get_clock(rt_clock) + vs->timer_interval);
1116 key_event(vs, read_u8(data, 1), read_u32(data, 4));
1117 break;
1118 case 5:
1119 if (len == 1)
1120 return 6;
1122 vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1123 qemu_advance_timer(vs->timer,
1124 qemu_get_clock(rt_clock) + vs->timer_interval);
1125 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1126 break;
1127 case 6:
1128 if (len == 1)
1129 return 8;
1131 if (len == 8) {
1132 uint32_t v;
1133 v = read_u32(data, 4);
1134 if (v)
1135 return 8 + v;
1138 client_cut_text(vs, read_u32(data, 4), data + 8);
1139 break;
1140 default:
1141 printf("Msg: %d\n", data[0]);
1142 vnc_client_error(vs);
1143 break;
1146 vnc_read_when(vs, protocol_client_msg, 1);
1147 return 0;
1150 static int protocol_client_init(VncState *vs, char *data, size_t len)
1152 size_t l;
1153 char pad[3] = { 0, 0, 0 };
1155 vga_hw_update();
1157 vs->width = vs->ds->width;
1158 vs->height = vs->ds->height;
1159 vnc_write_u16(vs, vs->ds->width);
1160 vnc_write_u16(vs, vs->ds->height);
1162 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1163 vnc_write_u8(vs, vs->depth * 8); /* depth */
1164 #ifdef WORDS_BIGENDIAN
1165 vnc_write_u8(vs, 1); /* big-endian-flag */
1166 #else
1167 vnc_write_u8(vs, 0); /* big-endian-flag */
1168 #endif
1169 vnc_write_u8(vs, 1); /* true-color-flag */
1170 if (vs->depth == 4) {
1171 vnc_write_u16(vs, 0xFF); /* red-max */
1172 vnc_write_u16(vs, 0xFF); /* green-max */
1173 vnc_write_u16(vs, 0xFF); /* blue-max */
1174 vnc_write_u8(vs, 16); /* red-shift */
1175 vnc_write_u8(vs, 8); /* green-shift */
1176 vnc_write_u8(vs, 0); /* blue-shift */
1177 vs->send_hextile_tile = send_hextile_tile_32;
1178 } else if (vs->depth == 2) {
1179 vnc_write_u16(vs, 31); /* red-max */
1180 vnc_write_u16(vs, 63); /* green-max */
1181 vnc_write_u16(vs, 31); /* blue-max */
1182 vnc_write_u8(vs, 11); /* red-shift */
1183 vnc_write_u8(vs, 5); /* green-shift */
1184 vnc_write_u8(vs, 0); /* blue-shift */
1185 vs->send_hextile_tile = send_hextile_tile_16;
1186 } else if (vs->depth == 1) {
1187 /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1188 vnc_write_u16(vs, 7); /* red-max */
1189 vnc_write_u16(vs, 7); /* green-max */
1190 vnc_write_u16(vs, 3); /* blue-max */
1191 vnc_write_u8(vs, 5); /* red-shift */
1192 vnc_write_u8(vs, 2); /* green-shift */
1193 vnc_write_u8(vs, 0); /* blue-shift */
1194 vs->send_hextile_tile = send_hextile_tile_8;
1196 vs->write_pixels = vnc_write_pixels_copy;
1198 vnc_write(vs, pad, 3); /* padding */
1200 l = strlen(domain_name);
1201 vnc_write_u32(vs, l);
1202 vnc_write(vs, domain_name, l);
1204 vnc_flush(vs);
1206 vnc_read_when(vs, protocol_client_msg, 1);
1208 return 0;
1211 static int protocol_version(VncState *vs, char *version, size_t len)
1213 char local[13];
1214 int maj, min;
1216 memcpy(local, version, 12);
1217 local[12] = 0;
1219 if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
1220 vnc_client_error(vs);
1221 return 0;
1224 vnc_write_u32(vs, 1); /* None */
1225 vnc_flush(vs);
1227 vnc_read_when(vs, protocol_client_init, 1);
1229 return 0;
1232 static void vnc_listen_read(void *opaque)
1234 VncState *vs = opaque;
1235 struct sockaddr_in addr;
1236 socklen_t addrlen = sizeof(addr);
1238 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1239 if (vs->csock != -1) {
1240 socket_set_nonblock(vs->csock);
1241 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1242 vnc_write(vs, "RFB 003.003\n", 12);
1243 vnc_flush(vs);
1244 vnc_read_when(vs, protocol_version, 12);
1245 framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
1246 vs->has_resize = 0;
1247 vs->has_hextile = 0;
1248 vs->ds->dpy_copy = NULL;
1249 vnc_timer_init(vs);
1253 int vnc_display_init(DisplayState *ds, int display, int find_unused)
1255 struct sockaddr_in addr;
1256 int reuse_addr, ret;
1257 VncState *vs;
1259 vs = qemu_mallocz(sizeof(VncState));
1260 if (!vs)
1261 exit(1);
1263 ds->opaque = vs;
1265 vs->lsock = -1;
1266 vs->csock = -1;
1267 vs->depth = 4;
1269 vs->ds = ds;
1271 if (!keyboard_layout)
1272 keyboard_layout = "en-us";
1274 vs->kbd_layout = init_keyboard_layout(keyboard_layout);
1275 if (!vs->kbd_layout)
1276 exit(1);
1278 vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
1279 if (vs->lsock == -1) {
1280 fprintf(stderr, "Could not create socket\n");
1281 exit(1);
1284 reuse_addr = 1;
1285 ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
1286 (const char *)&reuse_addr, sizeof(reuse_addr));
1287 if (ret == -1) {
1288 fprintf(stderr, "setsockopt() failed\n");
1289 exit(1);
1292 retry:
1293 addr.sin_family = AF_INET;
1294 addr.sin_port = htons(5900 + display);
1295 memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
1297 if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
1298 if (find_unused && errno == EADDRINUSE) {
1299 display++;
1300 goto retry;
1302 fprintf(stderr, "bind() failed\n");
1303 exit(1);
1306 if (listen(vs->lsock, 1) == -1) {
1307 fprintf(stderr, "listen() failed\n");
1308 exit(1);
1311 ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read,
1312 NULL, vs);
1313 if (ret == -1)
1314 exit(1);
1316 vs->ds->data = NULL;
1317 vs->ds->dpy_update = vnc_dpy_update;
1318 vs->ds->dpy_resize = vnc_dpy_resize;
1319 vs->ds->dpy_refresh = vnc_dpy_refresh;
1321 vnc_dpy_resize(vs->ds, 640, 400);
1323 return display;
1326 int vnc_start_viewer(int port)
1328 int pid;
1329 char s[16];
1331 sprintf(s, ":%d", port);
1333 switch (pid = fork()) {
1334 case -1:
1335 fprintf(stderr, "vncviewer failed fork\n");
1336 exit(1);
1338 case 0: /* child */
1339 execlp("vncviewer", "vncviewer", s, NULL);
1340 fprintf(stderr, "vncviewer execlp failed\n");
1341 exit(1);
1343 default:
1344 return pid;