Annotation of qemu/vnc.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * QEMU VNC display driver
                      3:  * 
                      4:  * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
                      5:  * Copyright (C) 2006 Fabrice Bellard
                      6:  * 
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include "vl.h"
                     27: #include "qemu_socket.h"
                     28: 
                     29: #define VNC_REFRESH_INTERVAL (1000 / 30)
                     30: 
                     31: #include "vnc_keysym.h"
                     32: #include "keymaps.c"
                     33: 
                     34: typedef struct Buffer
                     35: {
                     36:     size_t capacity;
                     37:     size_t offset;
                     38:     char *buffer;
                     39: } Buffer;
                     40: 
                     41: typedef struct VncState VncState;
                     42: 
                     43: typedef int VncReadEvent(VncState *vs, char *data, size_t len);
                     44: 
1.1.1.2 ! root       45: typedef void VncWritePixels(VncState *vs, void *data, int size);
        !            46: 
        !            47: typedef void VncSendHextileTile(VncState *vs,
        !            48:                                 int x, int y, int w, int h,
        !            49:                                 uint32_t *last_bg, 
        !            50:                                 uint32_t *last_fg,
        !            51:                                 int *has_bg, int *has_fg);
        !            52: 
        !            53: #define VNC_MAX_WIDTH 2048
        !            54: #define VNC_MAX_HEIGHT 2048
        !            55: #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
        !            56: 
1.1       root       57: struct VncState
                     58: {
                     59:     QEMUTimer *timer;
                     60:     int lsock;
                     61:     int csock;
                     62:     DisplayState *ds;
                     63:     int need_update;
                     64:     int width;
                     65:     int height;
1.1.1.2 ! root       66:     uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
1.1       root       67:     char *old_data;
1.1.1.2 ! root       68:     int depth; /* internal VNC frame buffer byte per pixel */
1.1       root       69:     int has_resize;
                     70:     int has_hextile;
                     71:     Buffer output;
                     72:     Buffer input;
                     73:     kbd_layout_t *kbd_layout;
1.1.1.2 ! root       74:     /* current output mode information */
        !            75:     VncWritePixels *write_pixels;
        !            76:     VncSendHextileTile *send_hextile_tile;
        !            77:     int pix_bpp, pix_big_endian;
        !            78:     int red_shift, red_max, red_shift1;
        !            79:     int green_shift, green_max, green_shift1;
        !            80:     int blue_shift, blue_max, blue_shift1;
1.1       root       81: 
                     82:     VncReadEvent *read_handler;
                     83:     size_t read_handler_expect;
                     84: };
                     85: 
                     86: /* TODO
                     87:    1) Get the queue working for IO.
                     88:    2) there is some weirdness when using the -S option (the screen is grey
                     89:       and not totally invalidated
                     90:    3) resolutions > 1024
                     91: */
                     92: 
                     93: static void vnc_write(VncState *vs, const void *data, size_t len);
                     94: static void vnc_write_u32(VncState *vs, uint32_t value);
                     95: static void vnc_write_s32(VncState *vs, int32_t value);
                     96: static void vnc_write_u16(VncState *vs, uint16_t value);
                     97: static void vnc_write_u8(VncState *vs, uint8_t value);
                     98: static void vnc_flush(VncState *vs);
                     99: static void vnc_update_client(void *opaque);
                    100: static void vnc_client_read(void *opaque);
                    101: 
1.1.1.2 ! root      102: static inline void vnc_set_bit(uint32_t *d, int k)
        !           103: {
        !           104:     d[k >> 5] |= 1 << (k & 0x1f);
        !           105: }
        !           106: 
        !           107: static inline void vnc_clear_bit(uint32_t *d, int k)
        !           108: {
        !           109:     d[k >> 5] &= ~(1 << (k & 0x1f));
        !           110: }
        !           111: 
        !           112: static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
        !           113: {
        !           114:     int j;
        !           115: 
        !           116:     j = 0;
        !           117:     while (n >= 32) {
        !           118:         d[j++] = -1;
        !           119:         n -= 32;
        !           120:     }
        !           121:     if (n > 0) 
        !           122:         d[j++] = (1 << n) - 1;
        !           123:     while (j < nb_words)
        !           124:         d[j++] = 0;
        !           125: }
        !           126: 
        !           127: static inline int vnc_get_bit(const uint32_t *d, int k)
        !           128: {
        !           129:     return (d[k >> 5] >> (k & 0x1f)) & 1;
        !           130: }
        !           131: 
        !           132: static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2, 
        !           133:                                int nb_words)
        !           134: {
        !           135:     int i;
        !           136:     for(i = 0; i < nb_words; i++) {
        !           137:         if ((d1[i] & d2[i]) != 0)
        !           138:             return 1;
        !           139:     }
        !           140:     return 0;
        !           141: }
        !           142: 
1.1       root      143: static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
                    144: {
                    145:     VncState *vs = ds->opaque;
                    146:     int i;
                    147: 
                    148:     h += y;
                    149: 
                    150:     for (; y < h; y++)
                    151:        for (i = 0; i < w; i += 16)
1.1.1.2 ! root      152:            vnc_set_bit(vs->dirty_row[y], (x + i) / 16);
1.1       root      153: }
                    154: 
                    155: static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
                    156:                                   int32_t encoding)
                    157: {
                    158:     vnc_write_u16(vs, x);
                    159:     vnc_write_u16(vs, y);
                    160:     vnc_write_u16(vs, w);
                    161:     vnc_write_u16(vs, h);
                    162: 
                    163:     vnc_write_s32(vs, encoding);
                    164: }
                    165: 
                    166: static void vnc_dpy_resize(DisplayState *ds, int w, int h)
                    167: {
                    168:     VncState *vs = ds->opaque;
                    169: 
                    170:     ds->data = realloc(ds->data, w * h * vs->depth);
                    171:     vs->old_data = realloc(vs->old_data, w * h * vs->depth);
                    172: 
                    173:     if (ds->data == NULL || vs->old_data == NULL) {
                    174:        fprintf(stderr, "vnc: memory allocation failed\n");
                    175:        exit(1);
                    176:     }
                    177: 
                    178:     ds->depth = vs->depth * 8;
                    179:     ds->width = w;
                    180:     ds->height = h;
                    181:     ds->linesize = w * vs->depth;
                    182:     if (vs->csock != -1 && vs->has_resize) {
                    183:        vnc_write_u8(vs, 0);  /* msg id */
                    184:        vnc_write_u8(vs, 0);
                    185:        vnc_write_u16(vs, 1); /* number of rects */
                    186:        vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
                    187:        vnc_flush(vs);
                    188:        vs->width = ds->width;
                    189:        vs->height = ds->height;
                    190:     }
                    191: }
                    192: 
1.1.1.2 ! root      193: /* fastest code */
        !           194: static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
        !           195: {
        !           196:     vnc_write(vs, pixels, size);
        !           197: }
        !           198: 
        !           199: /* slowest but generic code. */
        !           200: static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
        !           201: {
        !           202:     unsigned int r, g, b;
        !           203: 
        !           204:     r = (v >> vs->red_shift1) & vs->red_max;
        !           205:     g = (v >> vs->green_shift1) & vs->green_max;
        !           206:     b = (v >> vs->blue_shift1) & vs->blue_max;
        !           207:     v = (r << vs->red_shift) | 
        !           208:         (g << vs->green_shift) | 
        !           209:         (b << vs->blue_shift);
        !           210:     switch(vs->pix_bpp) {
        !           211:     case 1:
        !           212:         buf[0] = v;
        !           213:         break;
        !           214:     case 2:
        !           215:         if (vs->pix_big_endian) {
        !           216:             buf[0] = v >> 8;
        !           217:             buf[1] = v;
        !           218:         } else {
        !           219:             buf[1] = v >> 8;
        !           220:             buf[0] = v;
        !           221:         }
        !           222:         break;
        !           223:     default:
        !           224:     case 4:
        !           225:         if (vs->pix_big_endian) {
        !           226:             buf[0] = v >> 24;
        !           227:             buf[1] = v >> 16;
        !           228:             buf[2] = v >> 8;
        !           229:             buf[3] = v;
        !           230:         } else {
        !           231:             buf[3] = v >> 24;
        !           232:             buf[2] = v >> 16;
        !           233:             buf[1] = v >> 8;
        !           234:             buf[0] = v;
        !           235:         }
        !           236:         break;
        !           237:     }
        !           238: }
        !           239: 
        !           240: static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
        !           241: {
        !           242:     uint32_t *pixels = pixels1;
        !           243:     uint8_t buf[4];
        !           244:     int n, i;
        !           245: 
        !           246:     n = size >> 2;
        !           247:     for(i = 0; i < n; i++) {
        !           248:         vnc_convert_pixel(vs, buf, pixels[i]);
        !           249:         vnc_write(vs, buf, vs->pix_bpp);
        !           250:     }
        !           251: }
        !           252: 
1.1       root      253: static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
                    254: {
                    255:     int i;
                    256:     char *row;
                    257: 
                    258:     vnc_framebuffer_update(vs, x, y, w, h, 0);
                    259: 
                    260:     row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
                    261:     for (i = 0; i < h; i++) {
1.1.1.2 ! root      262:        vs->write_pixels(vs, row, w * vs->depth);
1.1       root      263:        row += vs->ds->linesize;
                    264:     }
                    265: }
                    266: 
                    267: static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
                    268: {
                    269:     ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
                    270:     ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
                    271: }
                    272: 
                    273: #define BPP 8
                    274: #include "vnchextile.h"
                    275: #undef BPP
                    276: 
                    277: #define BPP 16
                    278: #include "vnchextile.h"
                    279: #undef BPP
                    280: 
                    281: #define BPP 32
                    282: #include "vnchextile.h"
                    283: #undef BPP
                    284: 
1.1.1.2 ! root      285: #define GENERIC
        !           286: #define BPP 32
        !           287: #include "vnchextile.h"
        !           288: #undef BPP
        !           289: #undef GENERIC
        !           290: 
1.1       root      291: static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
                    292: {
                    293:     int i, j;
                    294:     int has_fg, has_bg;
                    295:     uint32_t last_fg32, last_bg32;
                    296: 
                    297:     vnc_framebuffer_update(vs, x, y, w, h, 5);
                    298: 
                    299:     has_fg = has_bg = 0;
                    300:     for (j = y; j < (y + h); j += 16) {
                    301:        for (i = x; i < (x + w); i += 16) {
1.1.1.2 ! root      302:             vs->send_hextile_tile(vs, i, j, 
        !           303:                                   MIN(16, x + w - i), MIN(16, y + h - j),
        !           304:                                   &last_bg32, &last_fg32, &has_bg, &has_fg);
1.1       root      305:        }
                    306:     }
                    307: }
                    308: 
                    309: static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
                    310: {
                    311:        if (vs->has_hextile)
                    312:            send_framebuffer_update_hextile(vs, x, y, w, h);
                    313:        else
                    314:            send_framebuffer_update_raw(vs, x, y, w, h);
                    315: }
                    316: 
                    317: static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
                    318: {
                    319:     int src, dst;
                    320:     char *src_row;
                    321:     char *dst_row;
                    322:     char *old_row;
                    323:     int y = 0;
                    324:     int pitch = ds->linesize;
                    325:     VncState *vs = ds->opaque;
                    326: 
                    327:     vnc_update_client(vs);
                    328: 
                    329:     if (dst_y > src_y) {
                    330:        y = h - 1;
                    331:        pitch = -pitch;
                    332:     }
                    333: 
                    334:     src = (ds->linesize * (src_y + y) + vs->depth * src_x);
                    335:     dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
                    336: 
                    337:     src_row = ds->data + src;
                    338:     dst_row = ds->data + dst;
                    339:     old_row = vs->old_data + dst;
                    340: 
                    341:     for (y = 0; y < h; y++) {
                    342:        memmove(old_row, src_row, w * vs->depth);
                    343:        memmove(dst_row, src_row, w * vs->depth);
                    344:        src_row += pitch;
                    345:        dst_row += pitch;
                    346:        old_row += pitch;
                    347:     }
                    348: 
                    349:     vnc_write_u8(vs, 0);  /* msg id */
                    350:     vnc_write_u8(vs, 0);
                    351:     vnc_write_u16(vs, 1); /* number of rects */
                    352:     vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
                    353:     vnc_write_u16(vs, src_x);
                    354:     vnc_write_u16(vs, src_y);
                    355:     vnc_flush(vs);
                    356: }
                    357: 
                    358: static int find_dirty_height(VncState *vs, int y, int last_x, int x)
                    359: {
                    360:     int h;
                    361: 
                    362:     for (h = 1; h < (vs->height - y); h++) {
                    363:        int tmp_x;
1.1.1.2 ! root      364:        if (!vnc_get_bit(vs->dirty_row[y + h], last_x))
1.1       root      365:            break;
                    366:        for (tmp_x = last_x; tmp_x < x; tmp_x++)
1.1.1.2 ! root      367:            vnc_clear_bit(vs->dirty_row[y + h], tmp_x);
1.1       root      368:     }
                    369: 
                    370:     return h;
                    371: }
                    372: 
                    373: static void vnc_update_client(void *opaque)
                    374: {
                    375:     VncState *vs = opaque;
                    376: 
                    377:     if (vs->need_update && vs->csock != -1) {
                    378:        int y;
                    379:        char *row;
                    380:        char *old_row;
1.1.1.2 ! root      381:        uint32_t width_mask[VNC_DIRTY_WORDS];
1.1       root      382:        int n_rectangles;
                    383:        int saved_offset;
                    384:        int has_dirty = 0;
                    385: 
1.1.1.2 ! root      386:         vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
1.1       root      387: 
                    388:        /* Walk through the dirty map and eliminate tiles that
                    389:           really aren't dirty */
                    390:        row = vs->ds->data;
                    391:        old_row = vs->old_data;
                    392: 
                    393:        for (y = 0; y < vs->height; y++) {
1.1.1.2 ! root      394:            if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
1.1       root      395:                int x;
                    396:                char *ptr, *old_ptr;
                    397: 
                    398:                ptr = row;
                    399:                old_ptr = old_row;
                    400: 
                    401:                for (x = 0; x < vs->ds->width; x += 16) {
                    402:                    if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
1.1.1.2 ! root      403:                        vnc_clear_bit(vs->dirty_row[y], (x / 16));
1.1       root      404:                    } else {
                    405:                        has_dirty = 1;
                    406:                        memcpy(old_ptr, ptr, 16 * vs->depth);
                    407:                    }
                    408: 
                    409:                    ptr += 16 * vs->depth;
                    410:                    old_ptr += 16 * vs->depth;
                    411:                }
                    412:            }
                    413: 
                    414:            row += vs->ds->linesize;
                    415:            old_row += vs->ds->linesize;
                    416:        }
                    417: 
                    418:        if (!has_dirty) {
                    419:            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
                    420:            return;
                    421:        }
                    422: 
                    423:        /* Count rectangles */
                    424:        n_rectangles = 0;
                    425:        vnc_write_u8(vs, 0);  /* msg id */
                    426:        vnc_write_u8(vs, 0);
                    427:        saved_offset = vs->output.offset;
                    428:        vnc_write_u16(vs, 0);
                    429: 
                    430:        for (y = 0; y < vs->height; y++) {
                    431:            int x;
                    432:            int last_x = -1;
                    433:            for (x = 0; x < vs->width / 16; x++) {
1.1.1.2 ! root      434:                if (vnc_get_bit(vs->dirty_row[y], x)) {
1.1       root      435:                    if (last_x == -1) {
                    436:                        last_x = x;
                    437:                    }
1.1.1.2 ! root      438:                    vnc_clear_bit(vs->dirty_row[y], x);
1.1       root      439:                } else {
                    440:                    if (last_x != -1) {
                    441:                        int h = find_dirty_height(vs, y, last_x, x);
                    442:                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
                    443:                        n_rectangles++;
                    444:                    }
                    445:                    last_x = -1;
                    446:                }
                    447:            }
                    448:            if (last_x != -1) {
                    449:                int h = find_dirty_height(vs, y, last_x, x);
                    450:                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
                    451:                n_rectangles++;
                    452:            }
                    453:        }
                    454:        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
                    455:        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
                    456:        vnc_flush(vs);
                    457: 
                    458:     }
                    459:     qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
                    460: }
                    461: 
                    462: static void vnc_timer_init(VncState *vs)
                    463: {
                    464:     if (vs->timer == NULL) {
                    465:        vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
                    466:        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
                    467:     }
                    468: }
                    469: 
                    470: static void vnc_dpy_refresh(DisplayState *ds)
                    471: {
                    472:     VncState *vs = ds->opaque;
                    473:     vnc_timer_init(vs);
                    474:     vga_hw_update();
                    475: }
                    476: 
                    477: static int vnc_listen_poll(void *opaque)
                    478: {
                    479:     VncState *vs = opaque;
                    480:     if (vs->csock == -1)
                    481:        return 1;
                    482:     return 0;
                    483: }
                    484: 
                    485: static void buffer_reserve(Buffer *buffer, size_t len)
                    486: {
                    487:     if ((buffer->capacity - buffer->offset) < len) {
                    488:        buffer->capacity += (len + 1024);
                    489:        buffer->buffer = realloc(buffer->buffer, buffer->capacity);
                    490:        if (buffer->buffer == NULL) {
                    491:            fprintf(stderr, "vnc: out of memory\n");
                    492:            exit(1);
                    493:        }
                    494:     }
                    495: }
                    496: 
                    497: static int buffer_empty(Buffer *buffer)
                    498: {
                    499:     return buffer->offset == 0;
                    500: }
                    501: 
                    502: static char *buffer_end(Buffer *buffer)
                    503: {
                    504:     return buffer->buffer + buffer->offset;
                    505: }
                    506: 
                    507: static void buffer_reset(Buffer *buffer)
                    508: {
                    509:        buffer->offset = 0;
                    510: }
                    511: 
                    512: static void buffer_append(Buffer *buffer, const void *data, size_t len)
                    513: {
                    514:     memcpy(buffer->buffer + buffer->offset, data, len);
                    515:     buffer->offset += len;
                    516: }
                    517: 
                    518: static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
                    519: {
                    520:     if (ret == 0 || ret == -1) {
                    521:        if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
                    522:            return 0;
                    523: 
                    524:        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
                    525:        closesocket(vs->csock);
                    526:        vs->csock = -1;
                    527:        buffer_reset(&vs->input);
                    528:        buffer_reset(&vs->output);
                    529:        vs->need_update = 0;
                    530:        return 0;
                    531:     }
                    532:     return ret;
                    533: }
                    534: 
                    535: static void vnc_client_error(VncState *vs)
                    536: {
                    537:     vnc_client_io_error(vs, -1, EINVAL);
                    538: }
                    539: 
                    540: static void vnc_client_write(void *opaque)
                    541: {
1.1.1.2 ! root      542:     long ret;
1.1       root      543:     VncState *vs = opaque;
                    544: 
                    545:     ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
                    546:     ret = vnc_client_io_error(vs, ret, socket_error());
                    547:     if (!ret)
                    548:        return;
                    549: 
                    550:     memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
                    551:     vs->output.offset -= ret;
                    552: 
                    553:     if (vs->output.offset == 0) {
                    554:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
                    555:     }
                    556: }
                    557: 
                    558: static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
                    559: {
                    560:     vs->read_handler = func;
                    561:     vs->read_handler_expect = expecting;
                    562: }
                    563: 
                    564: static void vnc_client_read(void *opaque)
                    565: {
                    566:     VncState *vs = opaque;
1.1.1.2 ! root      567:     long ret;
1.1       root      568: 
                    569:     buffer_reserve(&vs->input, 4096);
                    570: 
                    571:     ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
                    572:     ret = vnc_client_io_error(vs, ret, socket_error());
                    573:     if (!ret)
                    574:        return;
                    575: 
                    576:     vs->input.offset += ret;
                    577: 
                    578:     while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
                    579:        size_t len = vs->read_handler_expect;
                    580:        int ret;
                    581: 
                    582:        ret = vs->read_handler(vs, vs->input.buffer, len);
                    583:        if (vs->csock == -1)
                    584:            return;
                    585: 
                    586:        if (!ret) {
                    587:            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
                    588:            vs->input.offset -= len;
                    589:        } else {
                    590:            vs->read_handler_expect = ret;
                    591:        }
                    592:     }
                    593: }
                    594: 
                    595: static void vnc_write(VncState *vs, const void *data, size_t len)
                    596: {
                    597:     buffer_reserve(&vs->output, len);
                    598: 
                    599:     if (buffer_empty(&vs->output)) {
                    600:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
                    601:     }
                    602: 
                    603:     buffer_append(&vs->output, data, len);
                    604: }
                    605: 
                    606: static void vnc_write_s32(VncState *vs, int32_t value)
                    607: {
                    608:     vnc_write_u32(vs, *(uint32_t *)&value);
                    609: }
                    610: 
                    611: static void vnc_write_u32(VncState *vs, uint32_t value)
                    612: {
                    613:     uint8_t buf[4];
                    614: 
                    615:     buf[0] = (value >> 24) & 0xFF;
                    616:     buf[1] = (value >> 16) & 0xFF;
                    617:     buf[2] = (value >>  8) & 0xFF;
                    618:     buf[3] = value & 0xFF;
                    619: 
                    620:     vnc_write(vs, buf, 4);
                    621: }
                    622: 
                    623: static void vnc_write_u16(VncState *vs, uint16_t value)
                    624: {
                    625:     char buf[2];
                    626: 
                    627:     buf[0] = (value >> 8) & 0xFF;
                    628:     buf[1] = value & 0xFF;
                    629: 
                    630:     vnc_write(vs, buf, 2);
                    631: }
                    632: 
                    633: static void vnc_write_u8(VncState *vs, uint8_t value)
                    634: {
                    635:     vnc_write(vs, (char *)&value, 1);
                    636: }
                    637: 
                    638: static void vnc_flush(VncState *vs)
                    639: {
                    640:     if (vs->output.offset)
                    641:        vnc_client_write(vs);
                    642: }
                    643: 
                    644: static uint8_t read_u8(char *data, size_t offset)
                    645: {
                    646:     return data[offset];
                    647: }
                    648: 
                    649: static uint16_t read_u16(char *data, size_t offset)
                    650: {
                    651:     return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
                    652: }
                    653: 
                    654: static int32_t read_s32(char *data, size_t offset)
                    655: {
                    656:     return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
                    657:                     (data[offset + 2] << 8) | data[offset + 3]);
                    658: }
                    659: 
                    660: static uint32_t read_u32(char *data, size_t offset)
                    661: {
                    662:     return ((data[offset] << 24) | (data[offset + 1] << 16) |
                    663:            (data[offset + 2] << 8) | data[offset + 3]);
                    664: }
                    665: 
                    666: static void client_cut_text(VncState *vs, size_t len, char *text)
                    667: {
                    668: }
                    669: 
                    670: static void pointer_event(VncState *vs, int button_mask, int x, int y)
                    671: {
                    672:     int buttons = 0;
                    673:     int dz = 0;
                    674: 
                    675:     if (button_mask & 0x01)
                    676:        buttons |= MOUSE_EVENT_LBUTTON;
                    677:     if (button_mask & 0x02)
                    678:        buttons |= MOUSE_EVENT_MBUTTON;
                    679:     if (button_mask & 0x04)
                    680:        buttons |= MOUSE_EVENT_RBUTTON;
                    681:     if (button_mask & 0x08)
                    682:        dz = -1;
                    683:     if (button_mask & 0x10)
                    684:        dz = 1;
                    685:            
                    686:     if (kbd_mouse_is_absolute()) {
                    687:        kbd_mouse_event(x * 0x7FFF / vs->ds->width,
                    688:                        y * 0x7FFF / vs->ds->height,
                    689:                        dz, buttons);
                    690:     } else {
                    691:        static int last_x = -1;
                    692:        static int last_y = -1;
                    693: 
                    694:        if (last_x != -1)
                    695:            kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
                    696: 
                    697:        last_x = x;
                    698:        last_y = y;
                    699:     }
                    700: }
                    701: 
                    702: static void do_key_event(VncState *vs, int down, uint32_t sym)
                    703: {
                    704:     int keycode;
                    705: 
                    706:     keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
                    707: 
                    708:     if (keycode & 0x80)
                    709:        kbd_put_keycode(0xe0);
                    710:     if (down)
                    711:        kbd_put_keycode(keycode & 0x7f);
                    712:     else
                    713:        kbd_put_keycode(keycode | 0x80);
                    714: }
                    715: 
                    716: static void key_event(VncState *vs, int down, uint32_t sym)
                    717: {
                    718:     if (sym >= 'A' && sym <= 'Z')
                    719:        sym = sym - 'A' + 'a';
                    720:     do_key_event(vs, down, sym);
                    721: }
                    722: 
                    723: static void framebuffer_update_request(VncState *vs, int incremental,
                    724:                                       int x_position, int y_position,
                    725:                                       int w, int h)
                    726: {
                    727:     int i;
                    728:     vs->need_update = 1;
                    729:     if (!incremental) {
                    730:        char *old_row = vs->old_data + y_position * vs->ds->linesize;
                    731: 
                    732:        for (i = 0; i < h; i++) {
1.1.1.2 ! root      733:             vnc_set_bits(vs->dirty_row[y_position + i], 
        !           734:                          (vs->ds->width / 16), VNC_DIRTY_WORDS);
1.1       root      735:            memset(old_row, 42, vs->ds->width * vs->depth);
                    736:            old_row += vs->ds->linesize;
                    737:        }
                    738:     }
                    739: }
                    740: 
                    741: static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
                    742: {
                    743:     int i;
                    744: 
                    745:     vs->has_hextile = 0;
                    746:     vs->has_resize = 0;
                    747:     vs->ds->dpy_copy = NULL;
                    748: 
                    749:     for (i = n_encodings - 1; i >= 0; i--) {
                    750:        switch (encodings[i]) {
                    751:        case 0: /* Raw */
                    752:            vs->has_hextile = 0;
                    753:            break;
                    754:        case 1: /* CopyRect */
                    755:            vs->ds->dpy_copy = vnc_copy;
                    756:            break;
                    757:        case 5: /* Hextile */
                    758:            vs->has_hextile = 1;
                    759:            break;
                    760:        case -223: /* DesktopResize */
                    761:            vs->has_resize = 1;
                    762:            break;
                    763:        default:
                    764:            break;
                    765:        }
                    766:     }
                    767: }
                    768: 
1.1.1.2 ! root      769: static int compute_nbits(unsigned int val)
        !           770: {
        !           771:     int n;
        !           772:     n = 0;
        !           773:     while (val != 0) {
        !           774:         n++;
        !           775:         val >>= 1;
        !           776:     }
        !           777:     return n;
        !           778: }
        !           779: 
1.1       root      780: static void set_pixel_format(VncState *vs,
                    781:                             int bits_per_pixel, int depth,
                    782:                             int big_endian_flag, int true_color_flag,
                    783:                             int red_max, int green_max, int blue_max,
                    784:                             int red_shift, int green_shift, int blue_shift)
                    785: {
1.1.1.2 ! root      786:     int host_big_endian_flag;
1.1       root      787: 
1.1.1.2 ! root      788: #ifdef WORDS_BIGENDIAN
        !           789:     host_big_endian_flag = 1;
        !           790: #else
        !           791:     host_big_endian_flag = 0;
        !           792: #endif
        !           793:     if (!true_color_flag) {
        !           794:     fail:
1.1       root      795:        vnc_client_error(vs);
1.1.1.2 ! root      796:         return;
        !           797:     }
        !           798:     if (bits_per_pixel == 32 && 
        !           799:         host_big_endian_flag == big_endian_flag &&
        !           800:         red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
        !           801:         red_shift == 16 && green_shift == 8 && blue_shift == 0) {
        !           802:         vs->depth = 4;
        !           803:         vs->write_pixels = vnc_write_pixels_copy;
        !           804:         vs->send_hextile_tile = send_hextile_tile_32;
        !           805:     } else 
        !           806:     if (bits_per_pixel == 16 && 
        !           807:         host_big_endian_flag == big_endian_flag &&
        !           808:         red_max == 31 && green_max == 63 && blue_max == 31 &&
        !           809:         red_shift == 11 && green_shift == 5 && blue_shift == 0) {
        !           810:         vs->depth = 2;
        !           811:         vs->write_pixels = vnc_write_pixels_copy;
        !           812:         vs->send_hextile_tile = send_hextile_tile_16;
        !           813:     } else 
        !           814:     if (bits_per_pixel == 8 && 
        !           815:         red_max == 7 && green_max == 7 && blue_max == 3 &&
        !           816:         red_shift == 5 && green_shift == 2 && blue_shift == 0) {
        !           817:         vs->depth = 1;
        !           818:         vs->write_pixels = vnc_write_pixels_copy;
        !           819:         vs->send_hextile_tile = send_hextile_tile_8;
        !           820:     } else 
        !           821:     {
        !           822:         /* generic and slower case */
        !           823:         if (bits_per_pixel != 8 &&
        !           824:             bits_per_pixel != 16 &&
        !           825:             bits_per_pixel != 32)
        !           826:             goto fail;
        !           827:         vs->depth = 4;
        !           828:         vs->red_shift = red_shift;
        !           829:         vs->red_max = red_max;
        !           830:         vs->red_shift1 = 24 - compute_nbits(red_max);
        !           831:         vs->green_shift = green_shift;
        !           832:         vs->green_max = green_max;
        !           833:         vs->green_shift1 = 16 - compute_nbits(green_max);
        !           834:         vs->blue_shift = blue_shift;
        !           835:         vs->blue_max = blue_max;
        !           836:         vs->blue_shift1 = 8 - compute_nbits(blue_max);
        !           837:         vs->pix_bpp = bits_per_pixel / 8;
        !           838:         vs->pix_big_endian = big_endian_flag;
        !           839:         vs->write_pixels = vnc_write_pixels_generic;
        !           840:         vs->send_hextile_tile = send_hextile_tile_generic;
        !           841:     }
1.1       root      842: 
                    843:     vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
                    844:     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                    845:     memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
                    846: 
                    847:     vga_hw_invalidate();
                    848:     vga_hw_update();
                    849: }
                    850: 
                    851: static int protocol_client_msg(VncState *vs, char *data, size_t len)
                    852: {
                    853:     int i;
                    854:     uint16_t limit;
                    855: 
                    856:     switch (data[0]) {
                    857:     case 0:
                    858:        if (len == 1)
                    859:            return 20;
                    860: 
                    861:        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
                    862:                         read_u8(data, 6), read_u8(data, 7),
                    863:                         read_u16(data, 8), read_u16(data, 10),
                    864:                         read_u16(data, 12), read_u8(data, 14),
                    865:                         read_u8(data, 15), read_u8(data, 16));
                    866:        break;
                    867:     case 2:
                    868:        if (len == 1)
                    869:            return 4;
                    870: 
                    871:        if (len == 4)
                    872:            return 4 + (read_u16(data, 2) * 4);
                    873: 
                    874:        limit = read_u16(data, 2);
                    875:        for (i = 0; i < limit; i++) {
                    876:            int32_t val = read_s32(data, 4 + (i * 4));
                    877:            memcpy(data + 4 + (i * 4), &val, sizeof(val));
                    878:        }
                    879: 
                    880:        set_encodings(vs, (int32_t *)(data + 4), limit);
                    881:        break;
                    882:     case 3:
                    883:        if (len == 1)
                    884:            return 10;
                    885: 
                    886:        framebuffer_update_request(vs,
                    887:                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
                    888:                                   read_u16(data, 6), read_u16(data, 8));
                    889:        break;
                    890:     case 4:
                    891:        if (len == 1)
                    892:            return 8;
                    893: 
                    894:        key_event(vs, read_u8(data, 1), read_u32(data, 4));
                    895:        break;
                    896:     case 5:
                    897:        if (len == 1)
                    898:            return 6;
                    899: 
                    900:        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
                    901:        break;
                    902:     case 6:
                    903:        if (len == 1)
                    904:            return 8;
                    905: 
                    906:        if (len == 8)
                    907:            return 8 + read_u32(data, 4);
                    908: 
                    909:        client_cut_text(vs, read_u32(data, 4), data + 8);
                    910:        break;
                    911:     default:
                    912:        printf("Msg: %d\n", data[0]);
                    913:        vnc_client_error(vs);
                    914:        break;
                    915:     }
                    916:        
                    917:     vnc_read_when(vs, protocol_client_msg, 1);
                    918:     return 0;
                    919: }
                    920: 
                    921: static int protocol_client_init(VncState *vs, char *data, size_t len)
                    922: {
                    923:     char pad[3] = { 0, 0, 0 };
                    924: 
                    925:     vs->width = vs->ds->width;
                    926:     vs->height = vs->ds->height;
                    927:     vnc_write_u16(vs, vs->ds->width);
                    928:     vnc_write_u16(vs, vs->ds->height);
                    929: 
                    930:     vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
                    931:     vnc_write_u8(vs, vs->depth * 8); /* depth */
1.1.1.2 ! root      932: #ifdef WORDS_BIGENDIAN
        !           933:     vnc_write_u8(vs, 1);             /* big-endian-flag */
        !           934: #else
1.1       root      935:     vnc_write_u8(vs, 0);             /* big-endian-flag */
1.1.1.2 ! root      936: #endif
1.1       root      937:     vnc_write_u8(vs, 1);             /* true-color-flag */
                    938:     if (vs->depth == 4) {
                    939:        vnc_write_u16(vs, 0xFF);     /* red-max */
                    940:        vnc_write_u16(vs, 0xFF);     /* green-max */
                    941:        vnc_write_u16(vs, 0xFF);     /* blue-max */
                    942:        vnc_write_u8(vs, 16);        /* red-shift */
                    943:        vnc_write_u8(vs, 8);         /* green-shift */
                    944:        vnc_write_u8(vs, 0);         /* blue-shift */
1.1.1.2 ! root      945:         vs->send_hextile_tile = send_hextile_tile_32;
1.1       root      946:     } else if (vs->depth == 2) {
                    947:        vnc_write_u16(vs, 31);       /* red-max */
                    948:        vnc_write_u16(vs, 63);       /* green-max */
                    949:        vnc_write_u16(vs, 31);       /* blue-max */
                    950:        vnc_write_u8(vs, 11);        /* red-shift */
                    951:        vnc_write_u8(vs, 5);         /* green-shift */
                    952:        vnc_write_u8(vs, 0);         /* blue-shift */
1.1.1.2 ! root      953:         vs->send_hextile_tile = send_hextile_tile_16;
1.1       root      954:     } else if (vs->depth == 1) {
1.1.1.2 ! root      955:         /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
        !           956:        vnc_write_u16(vs, 7);        /* red-max */
1.1       root      957:        vnc_write_u16(vs, 7);        /* green-max */
                    958:        vnc_write_u16(vs, 3);        /* blue-max */
                    959:        vnc_write_u8(vs, 5);         /* red-shift */
                    960:        vnc_write_u8(vs, 2);         /* green-shift */
                    961:        vnc_write_u8(vs, 0);         /* blue-shift */
1.1.1.2 ! root      962:         vs->send_hextile_tile = send_hextile_tile_8;
1.1       root      963:     }
1.1.1.2 ! root      964:     vs->write_pixels = vnc_write_pixels_copy;
1.1       root      965:        
                    966:     vnc_write(vs, pad, 3);           /* padding */
                    967: 
                    968:     vnc_write_u32(vs, 4);        
                    969:     vnc_write(vs, "QEMU", 4);
                    970:     vnc_flush(vs);
                    971: 
                    972:     vnc_read_when(vs, protocol_client_msg, 1);
                    973: 
                    974:     return 0;
                    975: }
                    976: 
                    977: static int protocol_version(VncState *vs, char *version, size_t len)
                    978: {
                    979:     char local[13];
                    980:     int maj, min;
                    981: 
                    982:     memcpy(local, version, 12);
                    983:     local[12] = 0;
                    984: 
                    985:     if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
                    986:        vnc_client_error(vs);
                    987:        return 0;
                    988:     }
                    989: 
                    990:     vnc_write_u32(vs, 1); /* None */
                    991:     vnc_flush(vs);
                    992: 
                    993:     vnc_read_when(vs, protocol_client_init, 1);
                    994: 
                    995:     return 0;
                    996: }
                    997: 
                    998: static void vnc_listen_read(void *opaque)
                    999: {
                   1000:     VncState *vs = opaque;
                   1001:     struct sockaddr_in addr;
                   1002:     socklen_t addrlen = sizeof(addr);
                   1003: 
                   1004:     vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
                   1005:     if (vs->csock != -1) {
                   1006:         socket_set_nonblock(vs->csock);
                   1007:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
                   1008:        vnc_write(vs, "RFB 003.003\n", 12);
                   1009:        vnc_flush(vs);
                   1010:        vnc_read_when(vs, protocol_version, 12);
                   1011:        memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
                   1012:        memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                   1013:        vs->has_resize = 0;
                   1014:        vs->has_hextile = 0;
                   1015:        vs->ds->dpy_copy = NULL;
                   1016:     }
                   1017: }
                   1018: 
                   1019: void vnc_display_init(DisplayState *ds, int display)
                   1020: {
                   1021:     struct sockaddr_in addr;
                   1022:     int reuse_addr, ret;
                   1023:     VncState *vs;
                   1024: 
                   1025:     vs = qemu_mallocz(sizeof(VncState));
                   1026:     if (!vs)
                   1027:        exit(1);
                   1028: 
                   1029:     ds->opaque = vs;
                   1030: 
                   1031:     vs->lsock = -1;
                   1032:     vs->csock = -1;
                   1033:     vs->depth = 4;
                   1034: 
                   1035:     vs->ds = ds;
                   1036: 
                   1037:     if (!keyboard_layout)
                   1038:        keyboard_layout = "en-us";
                   1039: 
                   1040:     vs->kbd_layout = init_keyboard_layout(keyboard_layout);
                   1041:     if (!vs->kbd_layout)
                   1042:        exit(1);
                   1043: 
                   1044:     vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
                   1045:     if (vs->lsock == -1) {
                   1046:        fprintf(stderr, "Could not create socket\n");
                   1047:        exit(1);
                   1048:     }
                   1049: 
                   1050:     addr.sin_family = AF_INET;
                   1051:     addr.sin_port = htons(5900 + display);
                   1052:     memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
                   1053: 
                   1054:     reuse_addr = 1;
                   1055:     ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
                   1056:                     (const char *)&reuse_addr, sizeof(reuse_addr));
                   1057:     if (ret == -1) {
                   1058:        fprintf(stderr, "setsockopt() failed\n");
                   1059:        exit(1);
                   1060:     }
                   1061: 
                   1062:     if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
                   1063:        fprintf(stderr, "bind() failed\n");
                   1064:        exit(1);
                   1065:     }
                   1066: 
                   1067:     if (listen(vs->lsock, 1) == -1) {
                   1068:        fprintf(stderr, "listen() failed\n");
                   1069:        exit(1);
                   1070:     }
                   1071: 
                   1072:     ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
                   1073:     if (ret == -1) {
                   1074:        exit(1);
                   1075:     }
                   1076: 
                   1077:     vs->ds->data = NULL;
                   1078:     vs->ds->dpy_update = vnc_dpy_update;
                   1079:     vs->ds->dpy_resize = vnc_dpy_resize;
                   1080:     vs->ds->dpy_refresh = vnc_dpy_refresh;
                   1081: 
                   1082:     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                   1083: 
                   1084:     vnc_dpy_resize(vs->ds, 640, 400);
                   1085: }

unix.superglobalmegacorp.com