Annotation of qemu/vnc.c, revision 1.1.1.1

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: 
                     45: struct VncState
                     46: {
                     47:     QEMUTimer *timer;
                     48:     int lsock;
                     49:     int csock;
                     50:     DisplayState *ds;
                     51:     int need_update;
                     52:     int width;
                     53:     int height;
                     54:     uint64_t dirty_row[768];
                     55:     char *old_data;
                     56:     int depth;
                     57:     int has_resize;
                     58:     int has_hextile;
                     59:     Buffer output;
                     60:     Buffer input;
                     61:     kbd_layout_t *kbd_layout;
                     62: 
                     63:     VncReadEvent *read_handler;
                     64:     size_t read_handler_expect;
                     65: };
                     66: 
                     67: /* TODO
                     68:    1) Get the queue working for IO.
                     69:    2) there is some weirdness when using the -S option (the screen is grey
                     70:       and not totally invalidated
                     71:    3) resolutions > 1024
                     72: */
                     73: 
                     74: static void vnc_write(VncState *vs, const void *data, size_t len);
                     75: static void vnc_write_u32(VncState *vs, uint32_t value);
                     76: static void vnc_write_s32(VncState *vs, int32_t value);
                     77: static void vnc_write_u16(VncState *vs, uint16_t value);
                     78: static void vnc_write_u8(VncState *vs, uint8_t value);
                     79: static void vnc_flush(VncState *vs);
                     80: static void vnc_update_client(void *opaque);
                     81: static void vnc_client_read(void *opaque);
                     82: 
                     83: static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
                     84: {
                     85:     VncState *vs = ds->opaque;
                     86:     int i;
                     87: 
                     88:     h += y;
                     89: 
                     90:     for (; y < h; y++)
                     91:        for (i = 0; i < w; i += 16)
                     92:            vs->dirty_row[y] |= (1ULL << ((x + i) / 16));
                     93: }
                     94: 
                     95: static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
                     96:                                   int32_t encoding)
                     97: {
                     98:     vnc_write_u16(vs, x);
                     99:     vnc_write_u16(vs, y);
                    100:     vnc_write_u16(vs, w);
                    101:     vnc_write_u16(vs, h);
                    102: 
                    103:     vnc_write_s32(vs, encoding);
                    104: }
                    105: 
                    106: static void vnc_dpy_resize(DisplayState *ds, int w, int h)
                    107: {
                    108:     VncState *vs = ds->opaque;
                    109: 
                    110:     ds->data = realloc(ds->data, w * h * vs->depth);
                    111:     vs->old_data = realloc(vs->old_data, w * h * vs->depth);
                    112: 
                    113:     if (ds->data == NULL || vs->old_data == NULL) {
                    114:        fprintf(stderr, "vnc: memory allocation failed\n");
                    115:        exit(1);
                    116:     }
                    117: 
                    118:     ds->depth = vs->depth * 8;
                    119:     ds->width = w;
                    120:     ds->height = h;
                    121:     ds->linesize = w * vs->depth;
                    122:     if (vs->csock != -1 && vs->has_resize) {
                    123:        vnc_write_u8(vs, 0);  /* msg id */
                    124:        vnc_write_u8(vs, 0);
                    125:        vnc_write_u16(vs, 1); /* number of rects */
                    126:        vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
                    127:        vnc_flush(vs);
                    128:        vs->width = ds->width;
                    129:        vs->height = ds->height;
                    130:     }
                    131: }
                    132: 
                    133: static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
                    134: {
                    135:     int i;
                    136:     char *row;
                    137: 
                    138:     vnc_framebuffer_update(vs, x, y, w, h, 0);
                    139: 
                    140:     row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
                    141:     for (i = 0; i < h; i++) {
                    142:        vnc_write(vs, row, w * vs->depth);
                    143:        row += vs->ds->linesize;
                    144:     }
                    145: }
                    146: 
                    147: static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
                    148: {
                    149:     ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
                    150:     ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
                    151: }
                    152: 
                    153: #define BPP 8
                    154: #include "vnchextile.h"
                    155: #undef BPP
                    156: 
                    157: #define BPP 16
                    158: #include "vnchextile.h"
                    159: #undef BPP
                    160: 
                    161: #define BPP 32
                    162: #include "vnchextile.h"
                    163: #undef BPP
                    164: 
                    165: static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
                    166: {
                    167:     int i, j;
                    168:     int has_fg, has_bg;
                    169:     uint32_t last_fg32, last_bg32;
                    170:     uint16_t last_fg16, last_bg16;
                    171:     uint8_t last_fg8, last_bg8;
                    172: 
                    173:     vnc_framebuffer_update(vs, x, y, w, h, 5);
                    174: 
                    175:     has_fg = has_bg = 0;
                    176:     for (j = y; j < (y + h); j += 16) {
                    177:        for (i = x; i < (x + w); i += 16) {
                    178:            switch (vs->depth) {
                    179:            case 1:
                    180:                send_hextile_tile_8(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
                    181:                                    &last_bg8, &last_fg8, &has_bg, &has_fg);
                    182:                break;
                    183:            case 2:
                    184:                send_hextile_tile_16(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
                    185:                                     &last_bg16, &last_fg16, &has_bg, &has_fg);
                    186:                break;
                    187:            case 4:
                    188:                send_hextile_tile_32(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
                    189:                                     &last_bg32, &last_fg32, &has_bg, &has_fg);
                    190:                break;
                    191:            default:
                    192:                break;
                    193:            }
                    194:        }
                    195:     }
                    196: }
                    197: 
                    198: static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
                    199: {
                    200:        if (vs->has_hextile)
                    201:            send_framebuffer_update_hextile(vs, x, y, w, h);
                    202:        else
                    203:            send_framebuffer_update_raw(vs, x, y, w, h);
                    204: }
                    205: 
                    206: static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
                    207: {
                    208:     int src, dst;
                    209:     char *src_row;
                    210:     char *dst_row;
                    211:     char *old_row;
                    212:     int y = 0;
                    213:     int pitch = ds->linesize;
                    214:     VncState *vs = ds->opaque;
                    215: 
                    216:     vnc_update_client(vs);
                    217: 
                    218:     if (dst_y > src_y) {
                    219:        y = h - 1;
                    220:        pitch = -pitch;
                    221:     }
                    222: 
                    223:     src = (ds->linesize * (src_y + y) + vs->depth * src_x);
                    224:     dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
                    225: 
                    226:     src_row = ds->data + src;
                    227:     dst_row = ds->data + dst;
                    228:     old_row = vs->old_data + dst;
                    229: 
                    230:     for (y = 0; y < h; y++) {
                    231:        memmove(old_row, src_row, w * vs->depth);
                    232:        memmove(dst_row, src_row, w * vs->depth);
                    233:        src_row += pitch;
                    234:        dst_row += pitch;
                    235:        old_row += pitch;
                    236:     }
                    237: 
                    238:     vnc_write_u8(vs, 0);  /* msg id */
                    239:     vnc_write_u8(vs, 0);
                    240:     vnc_write_u16(vs, 1); /* number of rects */
                    241:     vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
                    242:     vnc_write_u16(vs, src_x);
                    243:     vnc_write_u16(vs, src_y);
                    244:     vnc_flush(vs);
                    245: }
                    246: 
                    247: static int find_dirty_height(VncState *vs, int y, int last_x, int x)
                    248: {
                    249:     int h;
                    250: 
                    251:     for (h = 1; h < (vs->height - y); h++) {
                    252:        int tmp_x;
                    253:        if (!(vs->dirty_row[y + h] & (1ULL << last_x)))
                    254:            break;
                    255:        for (tmp_x = last_x; tmp_x < x; tmp_x++)
                    256:            vs->dirty_row[y + h] &= ~(1ULL << tmp_x);
                    257:     }
                    258: 
                    259:     return h;
                    260: }
                    261: 
                    262: static void vnc_update_client(void *opaque)
                    263: {
                    264:     VncState *vs = opaque;
                    265: 
                    266:     if (vs->need_update && vs->csock != -1) {
                    267:        int y;
                    268:        char *row;
                    269:        char *old_row;
                    270:        uint64_t width_mask;
                    271:        int n_rectangles;
                    272:        int saved_offset;
                    273:        int has_dirty = 0;
                    274: 
                    275:        width_mask = (1ULL << (vs->width / 16)) - 1;
                    276: 
                    277:        if (vs->width == 1024)
                    278:            width_mask = ~(0ULL);
                    279: 
                    280:        /* Walk through the dirty map and eliminate tiles that
                    281:           really aren't dirty */
                    282:        row = vs->ds->data;
                    283:        old_row = vs->old_data;
                    284: 
                    285:        for (y = 0; y < vs->height; y++) {
                    286:            if (vs->dirty_row[y] & width_mask) {
                    287:                int x;
                    288:                char *ptr, *old_ptr;
                    289: 
                    290:                ptr = row;
                    291:                old_ptr = old_row;
                    292: 
                    293:                for (x = 0; x < vs->ds->width; x += 16) {
                    294:                    if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
                    295:                        vs->dirty_row[y] &= ~(1ULL << (x / 16));
                    296:                    } else {
                    297:                        has_dirty = 1;
                    298:                        memcpy(old_ptr, ptr, 16 * vs->depth);
                    299:                    }
                    300: 
                    301:                    ptr += 16 * vs->depth;
                    302:                    old_ptr += 16 * vs->depth;
                    303:                }
                    304:            }
                    305: 
                    306:            row += vs->ds->linesize;
                    307:            old_row += vs->ds->linesize;
                    308:        }
                    309: 
                    310:        if (!has_dirty) {
                    311:            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
                    312:            return;
                    313:        }
                    314: 
                    315:        /* Count rectangles */
                    316:        n_rectangles = 0;
                    317:        vnc_write_u8(vs, 0);  /* msg id */
                    318:        vnc_write_u8(vs, 0);
                    319:        saved_offset = vs->output.offset;
                    320:        vnc_write_u16(vs, 0);
                    321: 
                    322:        for (y = 0; y < vs->height; y++) {
                    323:            int x;
                    324:            int last_x = -1;
                    325:            for (x = 0; x < vs->width / 16; x++) {
                    326:                if (vs->dirty_row[y] & (1ULL << x)) {
                    327:                    if (last_x == -1) {
                    328:                        last_x = x;
                    329:                    }
                    330:                    vs->dirty_row[y] &= ~(1ULL << x);
                    331:                } else {
                    332:                    if (last_x != -1) {
                    333:                        int h = find_dirty_height(vs, y, last_x, x);
                    334:                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
                    335:                        n_rectangles++;
                    336:                    }
                    337:                    last_x = -1;
                    338:                }
                    339:            }
                    340:            if (last_x != -1) {
                    341:                int h = find_dirty_height(vs, y, last_x, x);
                    342:                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
                    343:                n_rectangles++;
                    344:            }
                    345:        }
                    346:        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
                    347:        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
                    348:        vnc_flush(vs);
                    349: 
                    350:     }
                    351:     qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
                    352: }
                    353: 
                    354: static void vnc_timer_init(VncState *vs)
                    355: {
                    356:     if (vs->timer == NULL) {
                    357:        vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
                    358:        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
                    359:     }
                    360: }
                    361: 
                    362: static void vnc_dpy_refresh(DisplayState *ds)
                    363: {
                    364:     VncState *vs = ds->opaque;
                    365:     vnc_timer_init(vs);
                    366:     vga_hw_update();
                    367: }
                    368: 
                    369: static int vnc_listen_poll(void *opaque)
                    370: {
                    371:     VncState *vs = opaque;
                    372:     if (vs->csock == -1)
                    373:        return 1;
                    374:     return 0;
                    375: }
                    376: 
                    377: static void buffer_reserve(Buffer *buffer, size_t len)
                    378: {
                    379:     if ((buffer->capacity - buffer->offset) < len) {
                    380:        buffer->capacity += (len + 1024);
                    381:        buffer->buffer = realloc(buffer->buffer, buffer->capacity);
                    382:        if (buffer->buffer == NULL) {
                    383:            fprintf(stderr, "vnc: out of memory\n");
                    384:            exit(1);
                    385:        }
                    386:     }
                    387: }
                    388: 
                    389: static int buffer_empty(Buffer *buffer)
                    390: {
                    391:     return buffer->offset == 0;
                    392: }
                    393: 
                    394: static char *buffer_end(Buffer *buffer)
                    395: {
                    396:     return buffer->buffer + buffer->offset;
                    397: }
                    398: 
                    399: static void buffer_reset(Buffer *buffer)
                    400: {
                    401:        buffer->offset = 0;
                    402: }
                    403: 
                    404: static void buffer_append(Buffer *buffer, const void *data, size_t len)
                    405: {
                    406:     memcpy(buffer->buffer + buffer->offset, data, len);
                    407:     buffer->offset += len;
                    408: }
                    409: 
                    410: static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
                    411: {
                    412:     if (ret == 0 || ret == -1) {
                    413:        if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
                    414:            return 0;
                    415: 
                    416:        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
                    417:        closesocket(vs->csock);
                    418:        vs->csock = -1;
                    419:        buffer_reset(&vs->input);
                    420:        buffer_reset(&vs->output);
                    421:        vs->need_update = 0;
                    422:        return 0;
                    423:     }
                    424:     return ret;
                    425: }
                    426: 
                    427: static void vnc_client_error(VncState *vs)
                    428: {
                    429:     vnc_client_io_error(vs, -1, EINVAL);
                    430: }
                    431: 
                    432: static void vnc_client_write(void *opaque)
                    433: {
                    434:     ssize_t ret;
                    435:     VncState *vs = opaque;
                    436: 
                    437:     ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
                    438:     ret = vnc_client_io_error(vs, ret, socket_error());
                    439:     if (!ret)
                    440:        return;
                    441: 
                    442:     memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
                    443:     vs->output.offset -= ret;
                    444: 
                    445:     if (vs->output.offset == 0) {
                    446:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
                    447:     }
                    448: }
                    449: 
                    450: static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
                    451: {
                    452:     vs->read_handler = func;
                    453:     vs->read_handler_expect = expecting;
                    454: }
                    455: 
                    456: static void vnc_client_read(void *opaque)
                    457: {
                    458:     VncState *vs = opaque;
                    459:     ssize_t ret;
                    460: 
                    461:     buffer_reserve(&vs->input, 4096);
                    462: 
                    463:     ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
                    464:     ret = vnc_client_io_error(vs, ret, socket_error());
                    465:     if (!ret)
                    466:        return;
                    467: 
                    468:     vs->input.offset += ret;
                    469: 
                    470:     while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
                    471:        size_t len = vs->read_handler_expect;
                    472:        int ret;
                    473: 
                    474:        ret = vs->read_handler(vs, vs->input.buffer, len);
                    475:        if (vs->csock == -1)
                    476:            return;
                    477: 
                    478:        if (!ret) {
                    479:            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
                    480:            vs->input.offset -= len;
                    481:        } else {
                    482:            vs->read_handler_expect = ret;
                    483:        }
                    484:     }
                    485: }
                    486: 
                    487: static void vnc_write(VncState *vs, const void *data, size_t len)
                    488: {
                    489:     buffer_reserve(&vs->output, len);
                    490: 
                    491:     if (buffer_empty(&vs->output)) {
                    492:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
                    493:     }
                    494: 
                    495:     buffer_append(&vs->output, data, len);
                    496: }
                    497: 
                    498: static void vnc_write_s32(VncState *vs, int32_t value)
                    499: {
                    500:     vnc_write_u32(vs, *(uint32_t *)&value);
                    501: }
                    502: 
                    503: static void vnc_write_u32(VncState *vs, uint32_t value)
                    504: {
                    505:     uint8_t buf[4];
                    506: 
                    507:     buf[0] = (value >> 24) & 0xFF;
                    508:     buf[1] = (value >> 16) & 0xFF;
                    509:     buf[2] = (value >>  8) & 0xFF;
                    510:     buf[3] = value & 0xFF;
                    511: 
                    512:     vnc_write(vs, buf, 4);
                    513: }
                    514: 
                    515: static void vnc_write_u16(VncState *vs, uint16_t value)
                    516: {
                    517:     char buf[2];
                    518: 
                    519:     buf[0] = (value >> 8) & 0xFF;
                    520:     buf[1] = value & 0xFF;
                    521: 
                    522:     vnc_write(vs, buf, 2);
                    523: }
                    524: 
                    525: static void vnc_write_u8(VncState *vs, uint8_t value)
                    526: {
                    527:     vnc_write(vs, (char *)&value, 1);
                    528: }
                    529: 
                    530: static void vnc_flush(VncState *vs)
                    531: {
                    532:     if (vs->output.offset)
                    533:        vnc_client_write(vs);
                    534: }
                    535: 
                    536: static uint8_t read_u8(char *data, size_t offset)
                    537: {
                    538:     return data[offset];
                    539: }
                    540: 
                    541: static uint16_t read_u16(char *data, size_t offset)
                    542: {
                    543:     return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
                    544: }
                    545: 
                    546: static int32_t read_s32(char *data, size_t offset)
                    547: {
                    548:     return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
                    549:                     (data[offset + 2] << 8) | data[offset + 3]);
                    550: }
                    551: 
                    552: static uint32_t read_u32(char *data, size_t offset)
                    553: {
                    554:     return ((data[offset] << 24) | (data[offset + 1] << 16) |
                    555:            (data[offset + 2] << 8) | data[offset + 3]);
                    556: }
                    557: 
                    558: static void client_cut_text(VncState *vs, size_t len, char *text)
                    559: {
                    560: }
                    561: 
                    562: static void pointer_event(VncState *vs, int button_mask, int x, int y)
                    563: {
                    564:     int buttons = 0;
                    565:     int dz = 0;
                    566: 
                    567:     if (button_mask & 0x01)
                    568:        buttons |= MOUSE_EVENT_LBUTTON;
                    569:     if (button_mask & 0x02)
                    570:        buttons |= MOUSE_EVENT_MBUTTON;
                    571:     if (button_mask & 0x04)
                    572:        buttons |= MOUSE_EVENT_RBUTTON;
                    573:     if (button_mask & 0x08)
                    574:        dz = -1;
                    575:     if (button_mask & 0x10)
                    576:        dz = 1;
                    577:            
                    578:     if (kbd_mouse_is_absolute()) {
                    579:        kbd_mouse_event(x * 0x7FFF / vs->ds->width,
                    580:                        y * 0x7FFF / vs->ds->height,
                    581:                        dz, buttons);
                    582:     } else {
                    583:        static int last_x = -1;
                    584:        static int last_y = -1;
                    585: 
                    586:        if (last_x != -1)
                    587:            kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
                    588: 
                    589:        last_x = x;
                    590:        last_y = y;
                    591:     }
                    592: }
                    593: 
                    594: static void do_key_event(VncState *vs, int down, uint32_t sym)
                    595: {
                    596:     int keycode;
                    597: 
                    598:     keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
                    599: 
                    600:     if (keycode & 0x80)
                    601:        kbd_put_keycode(0xe0);
                    602:     if (down)
                    603:        kbd_put_keycode(keycode & 0x7f);
                    604:     else
                    605:        kbd_put_keycode(keycode | 0x80);
                    606: }
                    607: 
                    608: static void key_event(VncState *vs, int down, uint32_t sym)
                    609: {
                    610:     if (sym >= 'A' && sym <= 'Z')
                    611:        sym = sym - 'A' + 'a';
                    612:     do_key_event(vs, down, sym);
                    613: }
                    614: 
                    615: static void framebuffer_update_request(VncState *vs, int incremental,
                    616:                                       int x_position, int y_position,
                    617:                                       int w, int h)
                    618: {
                    619:     int i;
                    620:     vs->need_update = 1;
                    621:     if (!incremental) {
                    622:        char *old_row = vs->old_data + y_position * vs->ds->linesize;
                    623: 
                    624:        for (i = 0; i < h; i++) {
                    625:            vs->dirty_row[y_position + i] = (1ULL << (vs->ds->width / 16)) - 1;
                    626:            if (vs->ds->width == 1024) {
                    627:              vs->dirty_row[y_position + i] = ~(0ULL);
                    628:            }
                    629:            memset(old_row, 42, vs->ds->width * vs->depth);
                    630:            old_row += vs->ds->linesize;
                    631:        }
                    632:     }
                    633: }
                    634: 
                    635: static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
                    636: {
                    637:     int i;
                    638: 
                    639:     vs->has_hextile = 0;
                    640:     vs->has_resize = 0;
                    641:     vs->ds->dpy_copy = NULL;
                    642: 
                    643:     for (i = n_encodings - 1; i >= 0; i--) {
                    644:        switch (encodings[i]) {
                    645:        case 0: /* Raw */
                    646:            vs->has_hextile = 0;
                    647:            break;
                    648:        case 1: /* CopyRect */
                    649:            vs->ds->dpy_copy = vnc_copy;
                    650:            break;
                    651:        case 5: /* Hextile */
                    652:            vs->has_hextile = 1;
                    653:            break;
                    654:        case -223: /* DesktopResize */
                    655:            vs->has_resize = 1;
                    656:            break;
                    657:        default:
                    658:            break;
                    659:        }
                    660:     }
                    661: }
                    662: 
                    663: static void set_pixel_format(VncState *vs,
                    664:                             int bits_per_pixel, int depth,
                    665:                             int big_endian_flag, int true_color_flag,
                    666:                             int red_max, int green_max, int blue_max,
                    667:                             int red_shift, int green_shift, int blue_shift)
                    668: {
                    669:     switch (bits_per_pixel) {
                    670:     case 32:
                    671:     case 24:
                    672:        vs->depth = 4;
                    673:        break;
                    674:     case 16:
                    675:        vs->depth = 2;
                    676:        break;
                    677:     case 8:
                    678:        vs->depth = 1;
                    679:        break;
                    680:     default:
                    681:        vnc_client_error(vs);
                    682:        break;
                    683:     }
                    684: 
                    685:     if (!true_color_flag)
                    686:        vnc_client_error(vs);
                    687: 
                    688:     vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
                    689:     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                    690:     memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
                    691: 
                    692:     vga_hw_invalidate();
                    693:     vga_hw_update();
                    694: }
                    695: 
                    696: static int protocol_client_msg(VncState *vs, char *data, size_t len)
                    697: {
                    698:     int i;
                    699:     uint16_t limit;
                    700: 
                    701:     switch (data[0]) {
                    702:     case 0:
                    703:        if (len == 1)
                    704:            return 20;
                    705: 
                    706:        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
                    707:                         read_u8(data, 6), read_u8(data, 7),
                    708:                         read_u16(data, 8), read_u16(data, 10),
                    709:                         read_u16(data, 12), read_u8(data, 14),
                    710:                         read_u8(data, 15), read_u8(data, 16));
                    711:        break;
                    712:     case 2:
                    713:        if (len == 1)
                    714:            return 4;
                    715: 
                    716:        if (len == 4)
                    717:            return 4 + (read_u16(data, 2) * 4);
                    718: 
                    719:        limit = read_u16(data, 2);
                    720:        for (i = 0; i < limit; i++) {
                    721:            int32_t val = read_s32(data, 4 + (i * 4));
                    722:            memcpy(data + 4 + (i * 4), &val, sizeof(val));
                    723:        }
                    724: 
                    725:        set_encodings(vs, (int32_t *)(data + 4), limit);
                    726:        break;
                    727:     case 3:
                    728:        if (len == 1)
                    729:            return 10;
                    730: 
                    731:        framebuffer_update_request(vs,
                    732:                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
                    733:                                   read_u16(data, 6), read_u16(data, 8));
                    734:        break;
                    735:     case 4:
                    736:        if (len == 1)
                    737:            return 8;
                    738: 
                    739:        key_event(vs, read_u8(data, 1), read_u32(data, 4));
                    740:        break;
                    741:     case 5:
                    742:        if (len == 1)
                    743:            return 6;
                    744: 
                    745:        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
                    746:        break;
                    747:     case 6:
                    748:        if (len == 1)
                    749:            return 8;
                    750: 
                    751:        if (len == 8)
                    752:            return 8 + read_u32(data, 4);
                    753: 
                    754:        client_cut_text(vs, read_u32(data, 4), data + 8);
                    755:        break;
                    756:     default:
                    757:        printf("Msg: %d\n", data[0]);
                    758:        vnc_client_error(vs);
                    759:        break;
                    760:     }
                    761:        
                    762:     vnc_read_when(vs, protocol_client_msg, 1);
                    763:     return 0;
                    764: }
                    765: 
                    766: static int protocol_client_init(VncState *vs, char *data, size_t len)
                    767: {
                    768:     char pad[3] = { 0, 0, 0 };
                    769: 
                    770:     vs->width = vs->ds->width;
                    771:     vs->height = vs->ds->height;
                    772:     vnc_write_u16(vs, vs->ds->width);
                    773:     vnc_write_u16(vs, vs->ds->height);
                    774: 
                    775:     vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
                    776:     vnc_write_u8(vs, vs->depth * 8); /* depth */
                    777:     vnc_write_u8(vs, 0);             /* big-endian-flag */
                    778:     vnc_write_u8(vs, 1);             /* true-color-flag */
                    779:     if (vs->depth == 4) {
                    780:        vnc_write_u16(vs, 0xFF);     /* red-max */
                    781:        vnc_write_u16(vs, 0xFF);     /* green-max */
                    782:        vnc_write_u16(vs, 0xFF);     /* blue-max */
                    783:        vnc_write_u8(vs, 16);        /* red-shift */
                    784:        vnc_write_u8(vs, 8);         /* green-shift */
                    785:        vnc_write_u8(vs, 0);         /* blue-shift */
                    786:     } else if (vs->depth == 2) {
                    787:        vnc_write_u16(vs, 31);       /* red-max */
                    788:        vnc_write_u16(vs, 63);       /* green-max */
                    789:        vnc_write_u16(vs, 31);       /* blue-max */
                    790:        vnc_write_u8(vs, 11);        /* red-shift */
                    791:        vnc_write_u8(vs, 5);         /* green-shift */
                    792:        vnc_write_u8(vs, 0);         /* blue-shift */
                    793:     } else if (vs->depth == 1) {
                    794:        vnc_write_u16(vs, 3);        /* red-max */
                    795:        vnc_write_u16(vs, 7);        /* green-max */
                    796:        vnc_write_u16(vs, 3);        /* blue-max */
                    797:        vnc_write_u8(vs, 5);         /* red-shift */
                    798:        vnc_write_u8(vs, 2);         /* green-shift */
                    799:        vnc_write_u8(vs, 0);         /* blue-shift */
                    800:     }
                    801:        
                    802:     vnc_write(vs, pad, 3);           /* padding */
                    803: 
                    804:     vnc_write_u32(vs, 4);        
                    805:     vnc_write(vs, "QEMU", 4);
                    806:     vnc_flush(vs);
                    807: 
                    808:     vnc_read_when(vs, protocol_client_msg, 1);
                    809: 
                    810:     return 0;
                    811: }
                    812: 
                    813: static int protocol_version(VncState *vs, char *version, size_t len)
                    814: {
                    815:     char local[13];
                    816:     int maj, min;
                    817: 
                    818:     memcpy(local, version, 12);
                    819:     local[12] = 0;
                    820: 
                    821:     if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
                    822:        vnc_client_error(vs);
                    823:        return 0;
                    824:     }
                    825: 
                    826:     vnc_write_u32(vs, 1); /* None */
                    827:     vnc_flush(vs);
                    828: 
                    829:     vnc_read_when(vs, protocol_client_init, 1);
                    830: 
                    831:     return 0;
                    832: }
                    833: 
                    834: static void vnc_listen_read(void *opaque)
                    835: {
                    836:     VncState *vs = opaque;
                    837:     struct sockaddr_in addr;
                    838:     socklen_t addrlen = sizeof(addr);
                    839: 
                    840:     vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
                    841:     if (vs->csock != -1) {
                    842:         socket_set_nonblock(vs->csock);
                    843:        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
                    844:        vnc_write(vs, "RFB 003.003\n", 12);
                    845:        vnc_flush(vs);
                    846:        vnc_read_when(vs, protocol_version, 12);
                    847:        memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
                    848:        memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                    849:        vs->has_resize = 0;
                    850:        vs->has_hextile = 0;
                    851:        vs->ds->dpy_copy = NULL;
                    852:     }
                    853: }
                    854: 
                    855: void vnc_display_init(DisplayState *ds, int display)
                    856: {
                    857:     struct sockaddr_in addr;
                    858:     int reuse_addr, ret;
                    859:     VncState *vs;
                    860: 
                    861:     vs = qemu_mallocz(sizeof(VncState));
                    862:     if (!vs)
                    863:        exit(1);
                    864: 
                    865:     ds->opaque = vs;
                    866: 
                    867:     vs->lsock = -1;
                    868:     vs->csock = -1;
                    869:     vs->depth = 4;
                    870: 
                    871:     vs->ds = ds;
                    872: 
                    873:     if (!keyboard_layout)
                    874:        keyboard_layout = "en-us";
                    875: 
                    876:     vs->kbd_layout = init_keyboard_layout(keyboard_layout);
                    877:     if (!vs->kbd_layout)
                    878:        exit(1);
                    879: 
                    880:     vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
                    881:     if (vs->lsock == -1) {
                    882:        fprintf(stderr, "Could not create socket\n");
                    883:        exit(1);
                    884:     }
                    885: 
                    886:     addr.sin_family = AF_INET;
                    887:     addr.sin_port = htons(5900 + display);
                    888:     memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
                    889: 
                    890:     reuse_addr = 1;
                    891:     ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
                    892:                     (const char *)&reuse_addr, sizeof(reuse_addr));
                    893:     if (ret == -1) {
                    894:        fprintf(stderr, "setsockopt() failed\n");
                    895:        exit(1);
                    896:     }
                    897: 
                    898:     if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
                    899:        fprintf(stderr, "bind() failed\n");
                    900:        exit(1);
                    901:     }
                    902: 
                    903:     if (listen(vs->lsock, 1) == -1) {
                    904:        fprintf(stderr, "listen() failed\n");
                    905:        exit(1);
                    906:     }
                    907: 
                    908:     ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
                    909:     if (ret == -1) {
                    910:        exit(1);
                    911:     }
                    912: 
                    913:     vs->ds->data = NULL;
                    914:     vs->ds->dpy_update = vnc_dpy_update;
                    915:     vs->ds->dpy_resize = vnc_dpy_resize;
                    916:     vs->ds->dpy_refresh = vnc_dpy_refresh;
                    917: 
                    918:     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
                    919: 
                    920:     vnc_dpy_resize(vs->ds, 640, 400);
                    921: }

unix.superglobalmegacorp.com