[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/1] Add shared memory interface to QEMU
From: |
Anthony Liguori |
Subject: |
[Qemu-devel] [PATCH 1/1] Add shared memory interface to QEMU |
Date: |
Sun, 16 Jul 2006 13:13:09 -0500 |
User-agent: |
Thunderbird 1.5.0.4 (X11/20060615) |
This is actually adds the shared memory interface to QEMU.
Regards,
Anthony Liguori
# HG changeset patch
# User address@hidden
# Node ID 0b4c6f94ee520884063f11f4631185368998cf9c
# Parent b9f2ce1d04dc160035f2a8c44fa400912b8a01fd
Add shared memory interface for external GUIs. The protocol is documented
in README.shmem.
diff -r b9f2ce1d04dc -r 0b4c6f94ee52 Makefile.target
--- a/Makefile.target Sat Jul 15 03:03:35 2006
+++ b/Makefile.target Sun Jul 16 16:25:28 2006
@@ -375,6 +375,7 @@
VL_OBJS+=sdl.o
endif
VL_OBJS+=vnc.o
+VL_OBJS+=shmem.o
ifdef CONFIG_COCOA
VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
diff -r b9f2ce1d04dc -r 0b4c6f94ee52 vl.c
--- a/vl.c Sat Jul 15 03:03:35 2006
+++ b/vl.c Sun Jul 16 16:25:28 2006
@@ -5221,6 +5221,7 @@
#endif
"-loadvm file start right away with a saved state (loadvm in
monitor)\n"
"-vnc display start a VNC server on display\n"
+ "-shmem dev start the shared memory interface on char device
'dev'\n"
"\n"
"During emulation, the following keys are useful:\n"
"ctrl-alt-f toggle full screen\n"
@@ -5299,6 +5300,7 @@
QEMU_OPTION_smp,
QEMU_OPTION_vnc,
QEMU_OPTION_no_acpi,
+ QEMU_OPTION_shmem,
};
typedef struct QEMUOption {
@@ -5370,6 +5372,7 @@
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
{ "smp", HAS_ARG, QEMU_OPTION_smp },
{ "vnc", HAS_ARG, QEMU_OPTION_vnc },
+ { "shmem", HAS_ARG, QEMU_OPTION_shmem },
/* temporary options */
{ "usb", 0, QEMU_OPTION_usb },
@@ -5604,6 +5607,7 @@
QEMUMachine *machine;
char usb_devices[MAX_USB_CMDLINE][128];
int usb_devices_index;
+ const char *shmem_path = 0;
LIST_INIT (&vm_change_state_head);
#ifndef _WIN32
@@ -6020,6 +6024,9 @@
case QEMU_OPTION_no_acpi:
acpi_enabled = 0;
break;
+ case QEMU_OPTION_shmem:
+ shmem_path = optarg;
+ break;
}
}
}
@@ -6133,6 +6140,19 @@
dumb_display_init(ds);
} else if (vnc_display != -1) {
vnc_display_init(ds, vnc_display);
+ } else if (shmem_path) {
+ CharDriverState *s;
+
+ s = qemu_chr_open(shmem_path);
+ if (!s) {
+ fprintf(stderr, "qemu: could not open shmem device '%s'\n",
+ shmem_path);
+ exit(1);
+ }
+ if (!strcmp(shmem_path, "vc"))
+ qemu_chr_printf(s, "shmem console\n");
+
+ shmem_display_init(ds, s);
} else {
#if defined(CONFIG_SDL)
sdl_display_init(ds, full_screen);
diff -r b9f2ce1d04dc -r 0b4c6f94ee52 vl.h
--- a/vl.h Sat Jul 15 03:03:35 2006
+++ b/vl.h Sun Jul 16 16:25:28 2006
@@ -767,6 +767,9 @@
/* vnc.c */
void vnc_display_init(DisplayState *ds, int display);
+/* shmem.c */
+void shmem_display_init(DisplayState *ds, CharDriverState *s);
+
/* ide.c */
#define MAX_DISKS 4
diff -r b9f2ce1d04dc -r 0b4c6f94ee52 README.shmem
--- /dev/null Sat Jul 15 03:03:35 2006
+++ b/README.shmem Sun Jul 16 16:25:28 2006
@@ -0,0 +1,96 @@
+QEMU Shared Memory Interface
+
+Changelog
+
+07-15-2006 Anthony Liguori <address@hidden>
+ - initial draft
+
+The shared memory interface in qemu provides a way to write external GUIs that
+perform almost as well as an integrated GUI. This document attempts to
+described the protocol used to interact with this interface.
+
+Overview
+
+The transport for the shared memory interface is a QEMU character device.
+Currently, QEMU supports a wide variety of devices (TCP/UDP sockets,
+ptys, etc). The shared memory interface is enabled with the -shmem option.
+The format of the argument for this option is similar to the -serial or
+-monitor options.
+
+The protocol used is asynchronous and line based. Line's are terminated with
+a \n (or possibly a \r\n). For the rest of this document, I will refer to
+commands sent by QEMU as server commands and commands sent by the other end
+of the character device as client commands.
+
+Server Commands
+
+ERROR [string]
+
+This command is sent when an error has occurred (usually from a bad command).
+String is a human-readable description of the problem. These errors are
+usually not fatal.
+
+MOUSE-ABSOLUTE
+
+This command signals to the client that the mouse is now in absolute mode.
+This is a hint to the client so that it can handle mouse grab appropriately.
+
+MOUSE-RELATIVE
+
+This command signals to the client that the mouse is now in relative mode.
+This is a hint to the client so that it can handle mouse grab appropriately.
+
+RESIZE width, height
+
+This command signals to the client that the guest has resized the VGA screen.
+After a client receives this command, it should allocate an appropriately
+sized shared memory segment and notify the server about this with the SHMID
+command.
+
+UPDATE x, y, width, height
+
+This command signals to the client that the guest has updated a portion of the
+VGA screen described by the rectangle (x, y, width, height).
+
+ATTACHED shmid
+
+This command signals to the client that the server has attached to the shared
+memory segment specified by shmid. The purpose of this command is to allow
+the client to know when to mark the shared memory segment as deleted. This
+cannot be relied upon in cases where an exit may occur so the client should
+take precautions and remove any shared memory segment whenever it is no longer
+needed (for instance, after a RESIZE and before the client exits).
+
+Client Commands
+
+SHMID shmid, size, width, height, depth, linesize
+
+This command reports a shared memory segment that the server should use to
+render the display too. shmid is a shared memory id (returned from shmget()).
+size is the size of the memory (in bytes). width and height represent the
+size of the image in pixels. depth is the number of bits per pixel. Finally,
+linesize is the number of bytes per line in the image.
+
+A client should wait for an ATTACHED server command before removing the shared
+memory segment.
+
+MOUSE x, y, buttons
+
+This command reports a change in mouse state to the server. x and y are the
+absolute position of the mouse (relative to the upper left corner of the guests
+screen). Both of these values may be negative when in relative mode. buttons
+is a bitmask representing which mouse buttons are active. The first bit in the
+mask represents the right mouse button, the second represents the left button,
+and the third represents the middle mouse button.
+
+KEY-DOWN key
+
+This command reports a key press event to the server. key is the name of the
+key that has been depressed. The format of key is identical to that used to
+represent keys in the keyboard layout files.
+
+KEY-UP key
+
+This command reports that a key has been released to the server. key is the
+name of the key that has been released. The format of key is identical to that
+used to represent keys in the keyboard layout files.
diff -r b9f2ce1d04dc -r 0b4c6f94ee52 shmem.c
--- /dev/null Sat Jul 15 03:03:35 2006
+++ b/shmem.c Sun Jul 16 16:25:28 2006
@@ -0,0 +1,249 @@
+/*
+ * QEMU Shared Memory display driver
+ *
+ * Copyright (C) 2006 Anthony Liguori <address@hidden>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#include "shmem_keysym.h"
+#include "keymaps.c"
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+typedef struct _ShmemState
+{
+ CharDriverState *chr;
+ DisplayState *ds;
+ char buffer[1024];
+ int n_buffer;
+ uint8_t *dummy;
+ int old_x, old_y;
+ int mouse_mode; /* 0 is relative; 1 is absolute */
+ kbd_layout_t *kbd_layout;
+} ShmemState;
+
+static int shmem_can_read(void *opaque)
+{
+ return 1024;
+}
+
+static void shmem_cmd_shmid(ShmemState *s, int shmid, int size,
+ int width, int height, int depth, int linesize)
+{
+ uint8_t *addr;
+
+ addr = shmat(shmid, NULL, 0);
+ if (addr == (void *)-1) {
+ qemu_chr_printf(s->chr, "ERROR could not attach to shm:%d\n", shmid);
+ return;
+ }
+
+ qemu_chr_printf(s->chr, "ATTACHED %d\n", shmid);
+
+ if (s->ds->data && s->ds->data != s->dummy)
+ shmdt(s->ds->data);
+
+ s->ds->data = addr;
+ s->ds->linesize = linesize;
+ s->ds->depth = depth;
+ s->ds->width = width;
+ s->ds->height = height;
+
+ vga_hw_invalidate();
+ vga_hw_update();
+}
+
+static void shmem_update_mouse_type(ShmemState *s)
+{
+ if (kbd_mouse_is_absolute()) {
+ if (s->mouse_mode != 1) {
+ s->mouse_mode = 1;
+ qemu_chr_printf(s->chr, "MOUSE-ABSOLUTE\n");
+ }
+ } else if (s->mouse_mode != 0) {
+ s->mouse_mode = 0;
+ qemu_chr_printf(s->chr, "MOUSE-RELATIVE\n");
+ }
+}
+
+static void shmem_cmd_mouse(ShmemState *s, int x, int y, int z, int buttons)
+{
+ if (s->old_x != -1) {
+ int dx, dy;
+
+ if (kbd_mouse_is_absolute()) {
+ dx = x * 0x7FFF / s->ds->width;
+ dy = y * 0x7FFF / s->ds->height;
+ } else {
+ dx = x - s->old_x;
+ dy = y - s->old_y;
+ }
+
+ shmem_update_mouse_type(s);
+
+ kbd_mouse_event(dx, dy, z, buttons);
+ }
+
+ s->old_x = x;
+ s->old_y = y;
+}
+
+static int keyname2keysym(const char *key)
+{
+ int i;
+
+ for (i = 0; name2keysym[i].name; i++) {
+ if (strcmp(name2keysym[i].name, key) == 0)
+ return name2keysym[i].keysym;
+ }
+
+ return 0;
+}
+
+static void shmem_cmd_key(ShmemState *s, const char *key, int down)
+{
+ int keycode;
+ int keysym;
+
+ keysym = keyname2keysym(key);
+ if (keysym == 0) {
+ qemu_chr_printf(s->chr, "ERROR unknown key `%s'\n", key);
+ return;
+ }
+ keycode = keysym2scancode(s->kbd_layout, keysym & 0xFFFF);
+
+ if (keycode & 0x80)
+ kbd_put_keycode(0xe0);
+ if (down)
+ kbd_put_keycode(keycode & 0x7F);
+ else
+ kbd_put_keycode(keycode | 0x80);
+}
+
+static void shmem_handle_command(ShmemState *s, const char *cmd)
+{
+ int shmid, size, depth, linesize, width, height;
+ int x, y, z, buttons;
+ char key[1024];
+
+ if (sscanf(cmd, "SHMID %d, %d, %d, %d, %d, %d\n",
+ &shmid, &size, &width, &height, &depth, &linesize) == 6) {
+ shmem_cmd_shmid(s, shmid, size, width, height, depth, linesize);
+ } else if (sscanf(cmd, "MOUSE %d, %d, %d, %d\n",
+ &x, &y, &z, &buttons) == 4) {
+ shmem_cmd_mouse(s, x, y, z, buttons);
+ } else if (sscanf(cmd, "KEY-DOWN %1023s\n", key) == 1) {
+ shmem_cmd_key(s, key, 1);
+ } else if (sscanf(cmd, "KEY-UP %1023s\n", key) == 1) {
+ shmem_cmd_key(s, key, 0);
+ } else {
+ qemu_chr_printf(s->chr, "ERROR unknown command: `%s'\n", cmd);
+ }
+}
+
+static void shmem_read(void *opaque, const uint8_t *buf, int size)
+{
+ ShmemState *s = opaque;
+ int offset = 0;
+
+ while (offset < size) {
+ char *nl;
+ int len;
+
+ len = MIN(sizeof(s->buffer) - s->n_buffer - 1, size - offset);
+ memcpy(s->buffer + s->n_buffer, buf + offset, len);
+ s->n_buffer += len;
+ s->buffer[s->n_buffer] = 0;
+ offset += len;
+
+ while ((nl = strchr(s->buffer, '\n'))) {
+ int remainder = s->n_buffer - (nl - s->buffer) - 1;
+ *nl = 0;
+ shmem_handle_command(s, s->buffer);
+ memmove(s->buffer, nl + 1, remainder);
+ s->n_buffer = remainder;
+ }
+ }
+}
+
+static void shmem_dpy_resize(DisplayState *ds, int w, int h)
+{
+ ShmemState *s = ds->opaque;
+
+ if (w == ds->width && h == ds->height)
+ return;
+
+ qemu_chr_printf(s->chr, "RESIZE %d, %d\n", w, h);
+
+ s->dummy = realloc(s->dummy, w * h);
+ if (s->dummy == NULL)
+ exit(1);
+
+ ds->depth = 8;
+ ds->width = w;
+ ds->height = h;
+ ds->linesize = w;
+ ds->data = s->dummy;
+}
+
+static void shmem_dpy_update(DisplayState *ds, int x, int y, int w, int h)
+{
+ ShmemState *s = ds->opaque;
+ qemu_chr_printf(s->chr, "UPDATE %d, %d, %d, %d\n", x, y, w, h);
+}
+
+static void shmem_dpy_refresh(DisplayState *ds)
+{
+ vga_hw_update();
+}
+
+void shmem_display_init(DisplayState *ds, CharDriverState *chr)
+{
+ ShmemState *s;
+
+ s = qemu_mallocz(sizeof(ShmemState));
+ if (!s)
+ exit(1);
+
+ s->chr = chr;
+ s->ds = ds;
+ s->old_x = -1;
+ s->old_y = -1;
+ s->mouse_mode = 0;
+
+ if (!keyboard_layout)
+ keyboard_layout = "en-us";
+
+ s->kbd_layout = init_keyboard_layout(keyboard_layout);
+ if (!s->kbd_layout)
+ exit(1);
+
+ ds->dpy_update = shmem_dpy_update;
+ ds->dpy_resize = shmem_dpy_resize;
+ ds->dpy_refresh = shmem_dpy_refresh;
+ ds->opaque = s;
+
+ shmem_dpy_resize(ds, 640, 480);
+
+ qemu_chr_add_read_handler(chr, shmem_can_read, shmem_read, s);
+}
diff -r b9f2ce1d04dc -r 0b4c6f94ee52 shmem_keysym.h
--- /dev/null Sat Jul 15 03:03:35 2006
+++ b/shmem_keysym.h Sun Jul 16 16:25:28 2006
@@ -0,0 +1,277 @@
+typedef struct {
+ const char* name;
+ int keysym;
+} name2keysym_t;
+static name2keysym_t name2keysym[]={
+/* ascii */
+ { "space", 1},
+ { "exclam", 2},
+ { "quotedbl", 3},
+ { "numbersign", 4},
+ { "dollar", 5},
+ { "percent", 6},
+ { "ampersand", 7},
+ { "apostrophe", 8},
+ { "parenleft", 9},
+ { "parenright", 10},
+ { "asterisk", 11},
+ { "plus", 12},
+ { "comma", 13},
+ { "minus", 14},
+ { "period", 15},
+ { "slash", 16},
+ { "0", 17},
+ { "1", 18},
+ { "2", 19},
+ { "3", 20},
+ { "4", 21},
+ { "5", 22},
+ { "6", 23},
+ { "7", 24},
+ { "8", 25},
+ { "9", 26},
+ { "colon", 27},
+ { "semicolon", 28},
+ { "less", 29},
+ { "equal", 30},
+ { "greater", 31},
+ { "question", 32},
+ { "at", 33},
+ { "A", 34},
+ { "B", 35},
+ { "C", 36},
+ { "D", 37},
+ { "E", 38},
+ { "F", 39},
+ { "G", 40},
+ { "H", 41},
+ { "I", 42},
+ { "J", 43},
+ { "K", 44},
+ { "L", 45},
+ { "M", 46},
+ { "N", 47},
+ { "O", 48},
+ { "P", 49},
+ { "Q", 40},
+ { "R", 41},
+ { "S", 42},
+ { "T", 43},
+ { "U", 44},
+ { "V", 45},
+ { "W", 46},
+ { "X", 47},
+ { "Y", 48},
+ { "Z", 49},
+ { "bracketleft", 50},
+ { "backslash", 51},
+ { "bracketright", 52},
+ { "asciicircum", 53},
+ { "underscore", 54},
+ { "grave", 55},
+ { "a", 56},
+ { "b", 57},
+ { "c", 58},
+ { "d", 59},
+ { "e", 60},
+ { "f", 61},
+ { "g", 62},
+ { "h", 63},
+ { "i", 64},
+ { "j", 65},
+ { "k", 66},
+ { "l", 67},
+ { "m", 68},
+ { "n", 69},
+ { "o", 70},
+ { "p", 71},
+ { "q", 72},
+ { "r", 73},
+ { "s", 74},
+ { "t", 75},
+ { "u", 76},
+ { "v", 77},
+ { "w", 78},
+ { "x", 79},
+ { "y", 80},
+ { "z", 81},
+ { "braceleft", 82},
+ { "bar", 83},
+ { "braceright", 84},
+ { "asciitilde", 85},
+
+/* latin 1 extensions */
+{ "nobreakspace", 86},
+{ "exclamdown", 87},
+{ "cent", 88},
+{ "sterling", 89},
+{ "currency", 90},
+{ "yen", 91},
+{ "brokenbar", 92},
+{ "section", 93},
+{ "diaeresis", 94},
+{ "copyright", 95},
+{ "ordfeminine", 96},
+{ "guillemotleft", 97},
+{ "notsign", 98},
+{ "hyphen", 99},
+{ "registered", 100},
+{ "macron", 101},
+{ "degree", 102},
+{ "plusminus", 103},
+{ "twosuperior", 104},
+{ "threesuperior", 105},
+{ "acute", 106},
+{ "mu", 107},
+{ "paragraph", 108},
+{ "periodcentered", 109},
+{ "cedilla", 110},
+{ "onesuperior", 111},
+{ "masculine", 112},
+{ "guillemotright", 113},
+{ "onequarter", 114},
+{ "onehalf", 115},
+{ "threequarters", 116},
+{ "questiondown", 117},
+{ "Agrave", 118},
+{ "Aacute", 119},
+{ "Acircumflex", 120},
+{ "Atilde", 121},
+{ "Adiaeresis", 122},
+{ "Aring", 123},
+{ "AE", 124},
+{ "Ccedilla", 125},
+{ "Egrave", 126},
+{ "Eacute", 127},
+{ "Ecircumflex", 128},
+{ "Ediaeresis", 129},
+{ "Igrave", 130},
+{ "Iacute", 131},
+{ "Icircumflex", 132},
+{ "Idiaeresis", 133},
+{ "ETH", 134},
+{ "Eth", 135},
+{ "Ntilde", 136},
+{ "Ograve", 137},
+{ "Oacute", 138},
+{ "Ocircumflex", 139},
+{ "Otilde", 140},
+{ "Odiaeresis", 141},
+{ "multiply", 142},
+{ "Ooblique", 143},
+{ "Oslash", 144},
+{ "Ugrave", 145},
+{ "Uacute", 146},
+{ "Ucircumflex", 147},
+{ "Udiaeresis", 148},
+{ "Yacute", 149},
+{ "THORN", 140},
+{ "Thorn", 141},
+{ "ssharp", 142},
+{ "agrave", 143},
+{ "aacute", 144},
+{ "acircumflex", 145},
+{ "atilde", 146},
+{ "adiaeresis", 147},
+{ "aring", 148},
+{ "ae", 149},
+{ "ccedilla", 150},
+{ "egrave", 151},
+{ "eacute", 152},
+{ "ecircumflex", 153},
+{ "ediaeresis", 154},
+{ "igrave", 155},
+{ "iacute", 156},
+{ "icircumflex", 157},
+{ "idiaeresis", 158},
+{ "eth", 159},
+{ "ntilde", 160},
+{ "ograve", 161},
+{ "oacute", 162},
+{ "ocircumflex", 163},
+{ "otilde", 164},
+{ "odiaeresis", 165},
+{ "division", 166},
+{ "oslash", 167},
+{ "ooblique", 168},
+{ "ugrave", 169},
+{ "uacute", 170},
+{ "ucircumflex", 171},
+{ "udiaeresis", 172},
+{ "yacute", 173},
+{ "thorn", 174},
+{ "ydiaeresis", 175},
+{ "EuroSign", 176},
+
+ /* modifiers */
+{"Control_L", 177},
+{"Control_R", 178},
+{"Alt_L", 179},
+{"Alt_R", 180},
+{"Caps_Lock", 181},
+{"Meta_L", 182},
+{"Meta_R", 183},
+{"Shift_L", 184},
+{"Shift_R", 185},
+{"Super_L", 186},
+{"Super_R", 187},
+
+ /* special keys */
+{"BackSpace", 188},
+{"Tab", 189},
+{"Return", 190},
+{"Right", 191},
+{"Left", 192},
+{"Up", 193},
+{"Down", 194},
+{"Page_Down", 195},
+{"Page_Up", 196},
+{"Insert", 197},
+{"Delete", 198},
+{"Home", 199},
+{"End", 200},
+{"Scroll_Lock", 201},
+{"F1", 202},
+{"F2", 203},
+{"F3", 204},
+{"F4", 205},
+{"F5", 206},
+{"F6", 207},
+{"F7", 208},
+{"F8", 209},
+{"F9", 210},
+{"F10", 211},
+{"F11", 212},
+{"F12", 213},
+{"F13", 214},
+{"F14", 215},
+{"F15", 216},
+{"Sys_Req", 217},
+{"KP_0", 218},
+{"KP_1", 219},
+{"KP_2", 220},
+{"KP_3", 221},
+{"KP_4", 222},
+{"KP_5", 223},
+{"KP_6", 224},
+{"KP_7", 225},
+{"KP_8", 226},
+{"KP_9", 227},
+{"KP_Add", 228},
+{"KP_Decimal", 229},
+{"KP_Divide", 230},
+{"KP_Enter", 231},
+{"KP_Equal", 232},
+{"KP_Multiply", 233},
+{"KP_Subtract", 234},
+{"help", 235},
+{"Menu", 236},
+{"Power", 237},
+{"Print", 238},
+{"Mode_switch", 239},
+{"Multi_Key", 240},
+{"Num_Lock", 241},
+{"Pause", 242},
+{"Escape", 243},
+{0},
+};
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH 1/1] Add shared memory interface to QEMU,
Anthony Liguori <=