* Re: Access to raw keycodes in xen domU
2008-08-14 15:21 ` Samuel Thibault
@ 2008-08-25 9:26 ` Maxim Gorbachyov
0 siblings, 0 replies; 7+ messages in thread
From: Maxim Gorbachyov @ 2008-08-25 9:26 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 698 bytes --]
Hello.
On Thu, Aug 14, 2008 at 7:21 PM, Samuel Thibault
<samuel.thibault@eu.citrix.com> wrote:
> Well, the problem is that since the xen console can be accessed e.g.
> through ssh, there is really no way to properly return keycodes. If you
> can not use pvfb, The only half-sane way I see is that you hardcode the
> translation that your dinosaur binary expects according to the keyboard
> layout you are using and use that patched version. I really don't see
> how that could ever fit generically in xen console.
There were doubts if anyone beside me needs it. Well, just
informational, this is the way I did it (see diff attached). Note,
some used esc-sequences are not in the default keymap.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: domU-raw-keycodes.patch --]
[-- Type: text/x-diff; name=domU-raw-keycodes.patch, Size: 15898 bytes --]
Index: linux-2.6.18-xen-3.2.0/drivers/xen/console/console.c
===================================================================
--- linux-2.6.18-xen-3.2.0/drivers/xen/console/console.c (revision 2)
+++ linux-2.6.18-xen-3.2.0/drivers/xen/console/console.c (working copy)
@@ -50,6 +50,10 @@
#include <linux/sysrq.h>
#include <linux/screen_info.h>
#include <linux/vt.h>
+#include <linux/vt_kern.h>
+#include <linux/kd.h>
+#include <linux/kbd_kern.h>
+#include <linux/workqueue.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -344,18 +348,388 @@
static struct tty_struct *xencons_tty;
static int xencons_priv_irq;
static char x_char;
+static unsigned char xencons_mode;
+static void match(void *unused);
+DECLARE_WORK(match_work, match, NULL);
+static DEFINE_SPINLOCK(translate_lock);
+static char raw_in[1024], pending;
+static unsigned current_in;
+
+typedef struct {
+ char *in;
+ char *out;
+ unsigned char in_len;
+ unsigned char out_len;
+} reverse_entry_t;
+
+#define ESC_CODE_IN 0x1b
+
+static reverse_entry_t reverse_escaped[] = {
+ { "\x1b\x5b\x44", "\xe0\x4b\xe0\xcb", 0, 0 }, // arrow left
+ { "\x1b\x5b\x41", "\xe0\x48\xe0\xc8", 0, 0 }, // arrow up
+ { "\x1b\x5b\x43", "\xe0\x4d\xe0\xcd", 0, 0 }, // arrow right
+ { "\x1b\x5b\x42", "\xe0\x50\xe0\xd0", 0, 0 }, // arrow down
+ { "\x1b\x5b\x5b\x41", "\x3b\xbb", 0, 0 }, // f1
+ { "\x1b\x5b\x5b\x42", "\x3c\xbc", 0, 0 }, // f2
+ { "\x1b\x5b\x5b\x43", "\x3d\xbd", 0, 0 }, // f3
+ { "\x1b\x5b\x5b\x44", "\x3e\xbe", 0, 0 }, // f4
+ { "\x1b\x5b\x5b\x45", "\x3f\xbf", 0, 0 }, // f5
+ { "\x1b\x5b\x31\x37\x7e", "\x40\xc0", 0, 0 }, // f6
+ { "\x1b\x5b\x31\x38\x7e", "\x41\xc1", 0, 0 }, // f7
+ { "\x1b\x5b\x31\x39\x7e", "\x42\xc2", 0, 0 }, // f8
+ { "\x1b\x5b\x32\x30\x7e", "\x43\xc3", 0, 0 }, // f9
+ { "\x1b\x5b\x32\x31\x7e", "\x44\xc4", 0, 0 }, // f10
+ { "\x1b\x5b\x32\x33\x7e", "\x57\xd7", 0, 0 }, // f11
+ { "\x1b\x5b\x32\x34\x7e", "\x58\xd8", 0, 0 }, // f12
+ { "\x1b\x5b\x50", "\x77\xf7", 0, 0 }, // pause
+ { "\x1b\x5b\x32\x7e", "\x6e\xee", 0, 0 }, // ins
+ { "\x1b\x5b\x31\x7e", "\x66\xe6", 0, 0 }, // home
+ { "\x1b\x5b\x35\x7e", "\x68\xe8", 0, 0 }, // pg up
+ { "\x1b\x5b\x33\x7e", "\x6f\xef", 0, 0 }, // del
+ { "\x1b\x5b\x34\x7e", "\x6b\xeb", 0, 0 }, // end
+ { "\x1b\x5b\x36\x7e", "\x6d\xed", 0, 0 }, // pg down
+ { "\x1b\x5b\x31\x7e", "\x47\xc7", 0, 0 }, // num - home
+ { "\x1b\x5b\x41", "\x48\xc8", 0, 0 }, // num - up
+ { "\x1b\x5b\x35\x7e", "\x49\xc9", 0, 0 }, // num - pg up
+ { "\x1b\x5b\x44", "\x4b\xcb", 0, 0 }, // num - arrow left
+ { "\x1b\x5b\x47", "\x4c\xcc", 0, 0 }, // num - center
+ { "\x1b\x5b\x43", "\x4d\xcd", 0, 0 }, // num - arrow right
+ { "\x1b\x5b\x34\x7e", "\x4f\xcf", 0, 0 }, // num - end
+ { "\x1b\x5b\x42", "\x50\xd0", 0, 0 }, // num - arrow down
+ { "\x1b\x5b\x36\x7e", "\x51\xd1", 0, 0 }, // num - pg down
+ { "\x1b\x5b\x32\x7e", "\x52\xd2", 0, 0 }, // num - ins
+ { "\x1b\x5b\x33\x7e", "\x53\xd3", 0, 0 }, // num - del
+ /* ctrl + f[1-12] */
+ { "\033[35~", "\x1d\x3b\xbb\x9d", 0, 0 },
+ { "\033[36~", "\x1d\x3c\xbc\x9d", 0, 0 },
+ { "\033[37~", "\x1d\x3d\xbd\x9d", 0, 0 },
+ { "\033[38~", "\x1d\x3e\xbe\x9d", 0, 0 },
+ { "\033[39~", "\x1d\x3f\xbf\x9d", 0, 0 },
+ { "\033[40~", "\x1d\x40\xc0\x9d", 0, 0 },
+ { "\033[41~", "\x1d\x41\xc1\x9d", 0, 0 },
+ { "\033[42~", "\x1d\x42\xc2\x9d", 0, 0 },
+ { "\033[43~", "\x1d\x43\xc3\x9d", 0, 0 },
+ { "\033[44~", "\x1d\x44\xc4\x9d", 0, 0 },
+ { "\033[45~", "\x1d\x57\xd7\x9d", 0, 0 },
+ { "\033[46~", "\x1d\x58\xd8\x9d", 0, 0 },
+ /* alt + f[1-12] */
+ { "\033[55~", "\x38\x3b\xbb\xb8", 0, 0 },
+ { "\033[56~", "\x38\x3c\xbc\xb8", 0, 0 },
+ { "\033[57~", "\x38\x3d\xbd\xb8", 0, 0 },
+ { "\033[58~", "\x38\x3e\xbe\xb8", 0, 0 },
+ { "\033[59~", "\x38\x3f\xbf\xb8", 0, 0 },
+ { "\033[60~", "\x38\x40\xc0\xb8", 0, 0 },
+ { "\033[61~", "\x38\x41\xc1\xb8", 0, 0 },
+ { "\033[62~", "\x38\x42\xc2\xb8", 0, 0 },
+ { "\033[63~", "\x38\x43\xc3\xb8", 0, 0 },
+ { "\033[64~", "\x38\x44\xc4\xb8", 0, 0 },
+ { "\033[65~", "\x38\x57\xd7\xb8", 0, 0 },
+ { "\033[66~", "\x38\x58\xd8\xb8", 0, 0 },
+ /* shift + F[1-12] */
+ { "\033[75~", "\x2a\x3b\xbb\xaa", 0, 0 },
+ { "\033[76~", "\x2a\x3c\xbc\xaa", 0, 0 },
+ { "\033[77~", "\x2a\x3d\xbd\xaa", 0, 0 },
+ { "\033[78~", "\x2a\x3e\xbe\xaa", 0, 0 },
+ { "\033[79~", "\x2a\x3f\xbf\xaa", 0, 0 },
+ { "\033[80~", "\x2a\x40\xc0\xaa", 0, 0 },
+ { "\033[81~", "\x2a\x41\xc1\xaa", 0, 0 },
+ { "\033[82~", "\x2a\x42\xc2\xaa", 0, 0 },
+ { "\033[83~", "\x2a\x43\xc3\xaa", 0, 0 },
+ { "\033[84~", "\x2a\x44\xc4\xaa", 0, 0 },
+ { "\033[85~", "\x2a\x57\xd7\xaa", 0, 0 },
+ { "\033[86~", "\x2a\x58\xd8\xaa", 0, 0 },
+ /* alt + [:alpha:] */
+ { "\033[altq~", "\x38\x10\x90\xb8", 0, 0 },
+ { "\033[altw~", "\x38\x11\x91\xb8", 0, 0 },
+ { "\033[alte~", "\x38\x12\x92\xb8", 0, 0 },
+ { "\033[altr~", "\x38\x13\x93\xb8", 0, 0 },
+ { "\033[altt~", "\x38\x14\x94\xb8", 0, 0 },
+ { "\033[alty~", "\x38\x15\x95\xb8", 0, 0 },
+ { "\033[altu~", "\x38\x16\x96\xb8", 0, 0 },
+ { "\033[alti~", "\x38\x17\x97\xb8", 0, 0 },
+ { "\033[alto~", "\x38\x18\x98\xb8", 0, 0 },
+ { "\033[altp~", "\x38\x19\x99\xb8", 0, 0 },
+ { "\033[alta~", "\x38\x1e\x9e\xb8", 0, 0 },
+ { "\033[alts~", "\x38\x1f\x9f\xb8", 0, 0 },
+ { "\033[altd~", "\x38\x20\xa0\xb8", 0, 0 },
+ { "\033[altf~", "\x38\x21\xa1\xb8", 0, 0 },
+ { "\033[altg~", "\x38\x22\xa2\xb8", 0, 0 },
+ { "\033[alth~", "\x38\x23\xa3\xb8", 0, 0 },
+ { "\033[altj~", "\x38\x24\xa4\xb8", 0, 0 },
+ { "\033[altk~", "\x38\x25\xa5\xb8", 0, 0 },
+ { "\033[altl~", "\x38\x26\xa6\xb8", 0, 0 },
+ { "\033[altz~", "\x38\x2c\xac\xb8", 0, 0 },
+ { "\033[altx~", "\x38\x2d\xad\xb8", 0, 0 },
+ { "\033[altc~", "\x38\x2e\xae\xb8", 0, 0 },
+ { "\033[altv~", "\x38\x2f\xaf\xb8", 0, 0 },
+ { "\033[altb~", "\x38\x30\xb0\xb8", 0, 0 },
+ { "\033[altn~", "\x38\x31\xb1\xb8", 0, 0 },
+ { "\033[altm~", "\x38\x32\xb2\xb8", 0, 0 },
+ /* alt + [:num:] */
+ { "\033[altone~", "\x38\x02\x82\xb8", 0, 0 },
+ { "\033[alttwo~", "\x38\x03\x83\xb8", 0, 0 },
+ { "\033[altthree~", "\x38\x04\x84\xb8", 0, 0 },
+ { "\033[altfour~", "\x38\x05\x85\xb8", 0, 0 },
+ { "\033[altfive~", "\x38\x06\x86\xb8", 0, 0 },
+ { "\033[altsix~", "\x38\x07\x87\xb8", 0, 0 },
+ { "\033[altseven~", "\x38\x08\x88\xb8", 0, 0 },
+ { "\033[alteight~", "\x38\x09\x89\xb8", 0, 0 },
+ { "\033[altnine~", "\x38\x0a\x8a\xb8", 0, 0 },
+ { "\033[altzero~", "\x38\x0b\x8b\xb8", 0, 0 },
+
+ { 0, 0, 0, 0 }
+};
+
+static reverse_entry_t reverse_short[] = {
+ { "\x1b", "\x01\x81", 0, 0 }, // esc
+ { "\x60", "\x29\xa9", 0, 0 }, // `
+ { "\x31", "\x02\x82", 0, 0 }, // 1
+ { "\x32", "\x03\x83", 0, 0 }, // 2
+ { "\x33", "\x04\x84", 0, 0 }, // 3
+ { "\x34", "\x05\x85", 0, 0 }, // 4
+ { "\x35", "\x06\x86", 0, 0 }, // 5
+ { "\x36", "\x07\x87", 0, 0 }, // 6
+ { "\x37", "\x08\x88", 0, 0 }, // 7
+ { "\x38", "\x09\x89", 0, 0 }, // 8
+ { "\x39", "\x0a\x8a", 0, 0 }, // 9
+ { "\x30", "\x0b\x8b", 0, 0 }, // 0
+ { "\x2d", "\x0c\x8c", 0, 0 }, // -
+ { "\x3d", "\x0d\x8d", 0, 0 }, // =
+ { "\x7f", "\x0e\x8e", 0, 0 }, // backspace
+ { "\x09", "\x0f\x8f", 0, 0 }, // tab
+ /* Well, that's true only for dionis inteface.
+ * In the real world [:alpha:] keys below
+ * must produce 0x2a 0xaa with Shift pressed */
+ { "\x71", "\x2a\x10\x90\xaa", 0, 0 }, // q
+ { "\x77", "\x2a\x11\x91\xaa", 0, 0 }, // w
+ { "\x65", "\x2a\x12\x92\xaa", 0, 0 }, // e
+ { "\x72", "\x2a\x13\x93\xaa", 0, 0 }, // r
+ { "\x74", "\x2a\x14\x94\xaa", 0, 0 }, // t
+ { "\x79", "\x2a\x15\x95\xaa", 0, 0 }, // y
+ { "\x75", "\x2a\x16\x96\xaa", 0, 0 }, // u
+ { "\x69", "\x2a\x17\x97\xaa", 0, 0 }, // i
+ { "\x6f", "\x2a\x18\x98\xaa", 0, 0 }, // o
+ { "\x70", "\x2a\x19\x99\xaa", 0, 0 }, // p
+ { "\x5b", "\x1a\x9a", 0, 0 }, // [
+ { "\x5d", "\x1b\x9b", 0, 0 }, // ]
+ { "\x5c", "\x2b\xab", 0, 0 }, /* \ */
+ { "\x61", "\x2a\x1e\x9e\xaa", 0, 0 }, // a
+ { "\x73", "\x2a\x1f\x9f\xaa", 0, 0 }, // s
+ { "\x64", "\x2a\x20\xa0\xaa", 0, 0 }, // d
+ { "\x66", "\x2a\x21\xa1\xaa", 0, 0 }, // f
+ { "\x67", "\x2a\x22\xa2\xaa", 0, 0 }, // g
+ { "\x68", "\x2a\x23\xa3\xaa", 0, 0 }, // h
+ { "\x6a", "\x2a\x24\xa4\xaa", 0, 0 }, // j
+ { "\x6b", "\x2a\x25\xa5\xaa", 0, 0 }, // k
+ { "\x6c", "\x2a\x26\xa6\xaa", 0, 0 }, // l
+ { "\x3b", "\x27\xa7", 0, 0 }, // ;
+ { "\x27", "\x28\xa8", 0, 0 }, // '
+ { "\x0d", "\x1c\x9c", 0, 0 }, // enter
+ { "\x7a", "\x2a\x2c\xac\xaa", 0, 0 }, // z
+ { "\x78", "\x2a\x2d\xad\xaa", 0, 0 }, // x
+ { "\x63", "\x2a\x2e\xae\xaa", 0, 0 }, // c
+ { "\x76", "\x2a\x2f\xaf\xaa", 0, 0 }, // v
+ { "\x62", "\x2a\x30\xb0\xaa", 0, 0 }, // b
+ { "\x6e", "\x2a\x31\xb1\xaa", 0, 0 }, // n
+ { "\x6d", "\x2a\x32\xb2\xaa", 0, 0 }, // m
+ { "\x2c", "\x33\xb3", 0, 0 }, // ,
+ { "\x2e", "\x34\xb4", 0, 0 }, // .
+ { "\x2f", "\x35\xb5", 0, 0 }, // /
+ { "\x20", "\x39\xb9", 0, 0 }, // space
+ { "\x1c", "\x63\xe3", 0, 0 }, // prt scr
+ { "\x2a", "\x37\xb7", 0, 0 }, // num *
+ { "\x2b", "\x4e\xce", 0, 0 }, // num +
+ /* with 'shift' pressed: */
+ { "\x7e", "\x2a\x29\xa9\xaa", 0, 0 }, // ~
+ { "\x21", "\x2a\x02\x82\xaa", 0, 0 }, // !
+ { "\x40", "\x2a\x03\x83\xaa", 0, 0 }, // @
+ { "\x23", "\x2a\x04\x84\xaa", 0, 0 }, // #
+ { "\x24", "\x2a\x05\x85\xaa", 0, 0 }, // $
+ { "\x25", "\x2a\x06\x86\xaa", 0, 0 }, // %
+ { "\x5e", "\x2a\x07\x87\xaa", 0, 0 }, // ^
+ { "\x26", "\x2a\x08\x88\xaa", 0, 0 }, // &
+ { "\x28", "\x2a\x0a\x8a\xaa", 0, 0 }, // (
+ { "\x29", "\x2a\x0b\x8b\xaa", 0, 0 }, // )
+ { "\x5f", "\x2a\x0c\x8c\xaa", 0, 0 }, // _
+ /* Again, use inversed behavior for [:alpha:] with Shift: */
+ { "\x51", "\x10\x90", 0, 0 }, // Q
+ { "\x57", "\x11\x91", 0, 0 }, // W
+ { "\x45", "\x12\x92", 0, 0 }, // E
+ { "\x52", "\x13\x93", 0, 0 }, // R
+ { "\x54", "\x14\x94", 0, 0 }, // T
+ { "\x59", "\x15\x95", 0, 0 }, // Y
+ { "\x55", "\x16\x96", 0, 0 }, // U
+ { "\x49", "\x17\x97", 0, 0 }, // I
+ { "\x4f", "\x18\x98", 0, 0 }, // O
+ { "\x50", "\x19\x99", 0, 0 }, // P
+ { "\x7b", "\x2a\x1a\x9a\xaa", 0, 0 }, // {
+ { "\x7d", "\x2a\x1b\x9b\xaa", 0, 0 }, // }
+ { "\x7c", "\x2a\x2b\xab\xaa", 0, 0 }, // |
+ { "\x41", "\x1e\x9e", 0, 0 }, // A
+ { "\x53", "\x1f\x9f", 0, 0 }, // S
+ { "\x44", "\x20\xa0", 0, 0 }, // D
+ { "\x46", "\x21\xa1", 0, 0 }, // F
+ { "\x47", "\x22\xa2", 0, 0 }, // G
+ { "\x48", "\x23\xa3", 0, 0 }, // H
+ { "\x4a", "\x24\xa4", 0, 0 }, // J
+ { "\x4b", "\x25\xa5", 0, 0 }, // K
+ { "\x4c", "\x26\xa6", 0, 0 }, // L
+ { "\x3a", "\x2a\x27\xa7\xaa", 0, 0 }, // :
+ { "\x22", "\x2a\x28\xa8\xaa", 0, 0 }, // "
+ { "\x5a", "\x2c\xac", 0, 0 }, // Z
+ { "\x58", "\x2d\xad", 0, 0 }, // X
+ { "\x43", "\x2e\xae", 0, 0 }, // C
+ { "\x56", "\x2f\xaf", 0, 0 }, // V
+ { "\x42", "\x30\xb0", 0, 0 }, // B
+ { "\x4e", "\x31\xb1", 0, 0 }, // N
+ { "\x4d", "\x32\xb2", 0, 0 }, // M
+ { "\x3c", "\x2a\x33\xb3\xaa", 0, 0 }, // <
+ { "\x3e", "\x2a\x34\xb4\xaa", 0, 0 }, // >
+ { "\x3f", "\x2a\x35\xb5\xaa", 0, 0 }, // ?
+ { 0, 0, 0, 0 }
+};
+
+static void xencons_tty_in(char *buf, unsigned len)
+{
+ unsigned i;
+
+ for (i = 0; i < len; ++i)
+ tty_insert_flip_char(xencons_tty, buf[i], 0);
+ tty_flip_buffer_push(xencons_tty);
+}
+
+/**
+ * return -1 if match is not possible
+ * return 0 if in_len bytes are equal
+ * return 1 if match is possible with more raw data provided
+ */
+static int trans_cmp(char *raw, unsigned raw_len, char *in, unsigned in_len)
+{
+ unsigned i, limit;
+ int success_means;
+
+ if (raw_len < in_len) {
+ limit = raw_len;
+ success_means = 1;
+ } else {
+ limit = in_len;
+ success_means = 0;
+ }
+
+ for (i = 0; i < limit; ++i)
+ if (raw[i] != in[i])
+ return -1;
+
+ return success_means;
+}
+
+static void match(void *unused)
+{
+ reverse_entry_t *re, *found;
+ int cmp_res;
+
+ spin_lock(&translate_lock);
+
+try_match:
+ if (!current_in)
+ goto out;
+
+ found = NULL;
+ pending = 0;
+
+ re = reverse_escaped;
+ while (re->in) {
+ cmp_res = trans_cmp(raw_in, current_in, re->in, re->in_len);
+ if (0 == cmp_res) {
+ found = re;
+ goto fnd;
+ } else if (1 == cmp_res) {
+ pending = 1;
+ }
+ ++re;
+ }
+
+ re = reverse_short;
+ while (re->in) {
+ cmp_res = trans_cmp(raw_in, current_in, re->in, re->in_len);
+ if (0 == cmp_res) {
+ found = re;
+ goto fnd;
+ }
+ ++re;
+ }
+fnd:
+ if (found) {
+ xencons_tty_in(found->out, found->out_len);
+ current_in -= found->in_len;
+ if (current_in) {
+ memmove(raw_in, raw_in + found->in_len, current_in);
+ goto try_match;
+ }
+ } else if (!pending) {
+ /* there is no match possible with more data provided,
+ * so remove heading garbage and try again
+ */
+ --current_in;
+ if (current_in) {
+ memmove(raw_in, raw_in + 1, current_in);
+ goto try_match;
+ }
+ }
+out:
+ spin_unlock(&translate_lock);
+}
+
+/**
+ * Idea is to wait for more data if ESC code was found.
+ * It prevents from matching start of escaped sequence to bare esc code.
+ */
+static void translate(char *in, unsigned in_len)
+{
+ unsigned i;
+
+ /* TODO: what? clear raw_in? */
+ if (in_len > sizeof(raw_in) - current_in)
+ return;
+
+ spin_lock(&translate_lock);
+ memcpy(raw_in + current_in, in, in_len);
+ current_in += in_len;
+ spin_unlock(&translate_lock);
+
+ for (i = 0; i < in_len; ++i)
+ if (ESC_CODE_IN == in[i]) {
+ schedule_delayed_work(&match_work, HZ/10);
+ return;
+ }
+
+ if (!match_work.pending)
+ match(NULL);
+}
+
+static void reset_trans(void)
+{
+ spin_lock(&translate_lock);
+ cancel_delayed_work(&match_work);
+ pending = 0;
+ current_in = 0;
+ spin_unlock(&translate_lock);
+}
+
void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
{
- int i;
+#ifdef CONFIG_MAGIC_SYSRQ
+ unsigned i;
+#endif
unsigned long flags;
spin_lock_irqsave(&xencons_lock, flags);
if (xencons_tty == NULL)
goto out;
+#ifdef CONFIG_MAGIC_SYSRQ
for (i = 0; i < len; i++) {
-#ifdef CONFIG_MAGIC_SYSRQ
if (sysrq_enabled) {
if (buf[i] == '\x0f') { /* ^O */
if (!sysrq_requested) {
@@ -378,11 +752,12 @@
}
}
}
+ }
#endif
- tty_insert_flip_char(xencons_tty, buf[i], 0);
- }
- tty_flip_buffer_push(xencons_tty);
-
+ if (K_RAW == xencons_mode)
+ translate(buf, len);
+ else
+ xencons_tty_in(buf, len);
out:
spin_unlock_irqrestore(&xencons_lock, flags);
}
@@ -593,8 +968,10 @@
spin_lock_irqsave(&xencons_lock, flags);
tty->driver_data = NULL;
- if (xencons_tty == NULL)
+ if (xencons_tty == NULL) {
xencons_tty = tty;
+ xencons_mode = K_XLATE;
+ }
__xencons_tx_flush();
spin_unlock_irqrestore(&xencons_lock, flags);
@@ -628,9 +1005,46 @@
tty->closing = 0;
spin_lock_irqsave(&xencons_lock, flags);
xencons_tty = NULL;
+ xencons_mode = K_XLATE;
spin_unlock_irqrestore(&xencons_lock, flags);
+ reset_trans();
}
+static int xencons_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned char ucval, perm;
+ long val;
+
+ perm = 0;
+ if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
+ perm = 1;
+
+ switch (cmd) {
+ case KDGKBTYPE:
+ ucval = KB_101;
+ return put_user(ucval, (char __user *)arg);
+
+ case KDGKBMODE:
+ val = xencons_mode;
+ return put_user(val, (long __user *)arg);
+
+ case KDSKBMODE:
+ if (!perm)
+ return -EPERM;
+ if (K_RAW != arg
+ && K_XLATE != arg
+ && K_MEDIUMRAW != arg
+ && K_UNICODE != arg)
+ return -EINVAL;
+ xencons_mode = arg;
+ reset_trans();
+ tty_ldisc_flush(tty);
+ return 0;
+ }
+ return -ENOIOCTLCMD;
+}
+
static struct tty_operations xencons_ops = {
.open = xencons_open,
.close = xencons_close,
@@ -644,12 +1058,29 @@
.throttle = xencons_throttle,
.unthrottle = xencons_unthrottle,
.wait_until_sent = xencons_wait_until_sent,
+ .ioctl = xencons_ioctl,
};
static int __init xencons_init(void)
{
int rc;
+ reverse_entry_t *re;
+ /* initialize reverse tables */
+ re = reverse_escaped;
+ while (re->in) {
+ re->in_len = strlen(re->in);
+ re->out_len = strlen(re->out);
+ ++re;
+ }
+
+ re = reverse_short;
+ while (re->in) {
+ re->in_len = strlen(re->in);
+ re->out_len = strlen(re->out);
+ ++re;
+ }
+
if (!is_running_on_xen())
return -ENODEV;
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 7+ messages in thread