All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 1/1] Add shared memory interface to QEMU
Date: Sun, 16 Jul 2006 13:13:09 -0500	[thread overview]
Message-ID: <44BA81B5.3090002@codemonkey.ws> (raw)

[-- Attachment #1: Type: text/plain, Size: 86 bytes --]

This is actually adds the shared memory interface to QEMU.

Regards,

Anthony Liguori

[-- Attachment #2: shmem.diff --]
[-- Type: text/x-patch, Size: 21977 bytes --]

# HG changeset patch
# User anthony@localhost.localdomain
# 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 <anthony@codemonkey.ws>
+  - 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 <anthony@codemonkey.ws>
+ * 
+ * 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},			      
+};

                 reply	other threads:[~2006-07-16 18:17 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44BA81B5.3090002@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.