summaryrefslogtreecommitdiff
path: root/debian/patches/console_switch3.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/console_switch3.patch')
-rw-r--r--debian/patches/console_switch3.patch839
1 files changed, 839 insertions, 0 deletions
diff --git a/debian/patches/console_switch3.patch b/debian/patches/console_switch3.patch
new file mode 100644
index 00000000..13c090d3
--- /dev/null
+++ b/debian/patches/console_switch3.patch
@@ -0,0 +1,839 @@
+2004-04-01 Marco Gerards <metgerards@student.han.nl>
+
+ * Makefile (LCLHDRS): Add inputdev.h.
+ (pc_kbd.so.$(hurd-version)): Add kdioctlServer.o kbd-repeat.c.
+ (pc_kbd-LDLIBS): New variable.
+ * console.c (saved_id): New variable.
+ (saved_cons): Likewise.
+ (console_switch_away): New function.
+ (console_switch_back): Likewise.
+ * input.h (console_switch_away): New prototype.
+ (console_switch_back): Likewise.
+ * pc-kbd.c: Include "inputdev.h" and <argp.h>.
+ (repeater_node): New variable.
+ (doc): Likewise.
+ (options): Likewise.
+ (argp): Likewise.
+ (parse_opt): New function.
+ (pc_kbd_init): Parse the arguments.
+ (gnumach_v1_input_next): Pass the keyboard event to the repeater
+ if the repeater is active.
+ (pc_kbd_init): Parse the `--repeat' argument.
+ (pc_kbd_start): If a repeater node was specified, start it as a
+ translator on the given node.
+ (kev_type, mouse_motion, mouse_motion, Scancode, m_deltaX)
+ (m_deltaY, MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, MOUSE_MOTION)
+ (MOUSE_EVENT, IOCPARM_MASK, IOC_OUT, IOC_IN, _IOC, _IOR, _IOW)
+ (KDSKBDMODE, KB_EVENT, KB_ASCII, KDFKBDTYPE, KB_VANILLAKB)
+ (KB_EVENT, KBSETLEDS): Move from here...
+ * inputdev.h: ... to here. New file.
+ * kbd-repeat.c: New file.
+
+
+
+diff -upN ../../console-client/Makefile ./Makefile
+--- ../../console-client/Makefile 2002-09-17 14:26:10.000000000 +0200
++++ console-client/Makefile 2004-03-28 10:53:06.000000000 +0200
+@@ -21,7 +21,7 @@ makemode := utility
+ target = console
+ SRCS = console.c timer.c driver.c
+ LCLHDRS = timer.h driver.h display.h input.h bell.h \
+- unicode.h bdf.h \
++ unicode.h bdf.h inputdev.h \
+ vga-dynafont.h vga-dynacolor.h vga-hw.h vga.h
+
+ OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
+@@ -45,7 +45,9 @@ modules = vga pc_kbd generic_speaker
+
+ vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,bdf.c vga-dynafont.c \
+ vga-dynacolor.c vga-support.c vga.c)
+-pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c)
++pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c kdioctlServer.o kbd-repeat.c)
++pc_kbd-LDLIBS = -ltrivfs
++
+ generic_speaker.so.$(hurd-version): $(patsubst %.c,%_pic.o,generic-speaker.c)
+
+ ifneq ($(LIBNCURSESW),)
+diff -upN ../../console-client/console.c ./console.c
+--- ../../console-client/console.c 2004-03-24 23:53:17.000000000 +0100
++++ console-client/console.c 2004-03-28 11:10:42.000000000 +0200
+@@ -47,6 +47,12 @@ static struct mutex global_lock;
+ displayed. */
+ static vcons_t active_vcons = NULL;
+
++/* Contains the VT id when switched away. */
++static int saved_id = 0;
++
++/* The console, used to switch back. */
++static cons_t saved_cons;
++
+
+ /* Callbacks for input source drivers. */
+
+@@ -94,6 +100,53 @@ console_switch (int id, int delta)
+ }
+
+
++/* Switch away from the console an external use of the console like
++ XFree. */
++void
++console_switch_away (void)
++{
++ mutex_lock (&global_lock);
++ saved_id = active_vcons->id;
++ saved_cons = active_vcons->cons;
++ cons_vcons_close (active_vcons);
++ active_vcons = NULL;
++ mutex_unlock (&global_lock);
++}
++
++/* Switch back to the console client from an external user of the
++ console like XFree. */
++void
++console_switch_back (void)
++{
++ vcons_list_t conslist;
++ mutex_lock (&global_lock);
++ if (saved_cons)
++ {
++ error_t err;
++
++ err = cons_lookup (saved_cons, saved_id, 1, &conslist);
++ if (err)
++ {
++ mutex_unlock (&global_lock);
++ return;
++ }
++
++ err = cons_vcons_open (saved_cons, conslist, &active_vcons);
++ if (err)
++ {
++ mutex_unlock (&global_lock);
++ return;
++ }
++
++ conslist->vcons = active_vcons;
++ saved_cons = NULL;
++ mutex_unlock (&active_vcons->lock);
++ }
++ mutex_unlock (&global_lock);
++}
++
++
++
+ /* Enter SIZE bytes from the buffer BUF into the currently active
+ console. This can be called by the input driver at any time. */
+ error_t
+diff -upN ../../console-client/input.h ./input.h
+--- ../../console-client/input.h 2002-09-17 14:26:10.000000000 +0200
++++ console-client/input.h 2004-03-28 10:53:13.000000000 +0200
+@@ -1,5 +1,5 @@
+ /* input.h - The interface to and for an input driver.
+- Copyright (C) 2002 Free Software Foundation, Inc.
++ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Written by Marcus Brinkmann.
+
+ This file is part of the GNU Hurd.
+@@ -65,6 +65,15 @@ void console_error (const wchar_t *const
+ /* Exit the console client. Does not return. */
+ void console_exit (void);
+
++/* Switch away from the console an external use of the console like
++ XFree. */
++void console_switch_away (void);
++
++/* Switch back to the console client from an external user of the
++ console like XFree. */
++void console_switch_back (void);
++
++
+ #if QUAERENDO_INVENIETIS
+ /* Do not use, do not remove. */
+ void console_deprecated (int key);
+diff -upN ../../console-client/inputdev.h ./inputdev.h
+--- ../../console-client/inputdev.h 1970-01-01 01:00:00.000000000 +0100
++++ console-client/inputdev.h 2004-03-28 10:53:13.000000000 +0200
+@@ -0,0 +1,122 @@
++/* inputdev.h - Interfaces for the PC pc-kbd and mouse input drivers.
++ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
++ Written by Marco Gerards.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2, or (at
++ your option) any later version.
++
++ The GNU Hurd is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
++
++/* This gross stuff is cut & pasted from Mach sources, as Mach doesn't
++ export the interface we are using here. */
++
++/*
++ * Mach Operating System
++ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
++ * All Rights Reserved.
++ *
++ * Permission to use, copy, modify and distribute this software and its
++ * documentation is hereby granted, provided that both the copyright
++ * notice and this permission notice appear in all copies of the
++ * software, derivative works or modified versions, and any portions
++ * thereof, and that both notices appear in supporting documentation.
++ *
++ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
++ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
++ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
++ *
++ * Carnegie Mellon requests users of this software to return to
++ *
++ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
++ * School of Computer Science
++ * Carnegie Mellon University
++ * Pittsburgh PA 15213-3890
++ *
++ * any improvements or extensions that they make and grant Carnegie Mellon
++ * the rights to redistribute these changes.
++ */
++
++#ifndef _INPUTDEV_H_
++#define _INPUTDEV_H_ 1
++
++typedef u_short kev_type; /* kd event type */
++
++/* (used for event records) */
++struct mouse_motion {
++ short mm_deltaX; /* units? */
++ short mm_deltaY;
++};
++typedef u_char Scancode;
++
++typedef struct {
++ kev_type type; /* see below */
++ struct timeval time; /* timestamp */
++ union { /* value associated with event */
++ boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */
++ Scancode sc; /* KEYBD_EVENT */
++ struct mouse_motion mmotion; /* MOUSE_MOTION */
++ } value;
++} kd_event;
++#define m_deltaX mmotion.mm_deltaX
++#define m_deltaY mmotion.mm_deltaY
++
++/*
++ * kd_event ID's.
++ */
++#define MOUSE_LEFT 1 /* mouse left button up/down */
++#define MOUSE_MIDDLE 2
++#define MOUSE_RIGHT 3
++#define MOUSE_MOTION 4 /* mouse motion */
++#define KEYBD_EVENT 5 /* key up/down */
++
++
++#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */
++#define IOC_OUT 0x40000000 /* copy out parameters */
++#define IOC_IN 0x80000000U /* copy in parameters */
++
++#ifndef _IOC
++#define _IOC(inout,group,num,len) \
++ (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
++#endif
++#ifndef _IOR
++#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
++#endif
++#ifndef _IOW
++#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
++#endif
++
++#define KDSKBDMODE _IOW('K', 1, int) /* set keyboard mode */
++#define KB_EVENT 1
++#define KB_ASCII 2
++
++#define KDGKBDTYPE _IOR('K', 2, int) /* get keyboard type */
++#define KB_VANILLAKB 0
++
++#define KDSETLEDS _IOW('K', 5, int) /* set keyboard leds */
++
++
++/* End of Mach code. */
++
++
++/* Amount of times the device was opened. Normally this translator
++ should be only opened once. */
++extern int kbd_repeater_opened;
++
++/* Place the keyboard event KEY in the keyboard buffer. */
++void repeat_key (kd_event *key);
++
++/* Set the repeater translator on the node PATH. */
++error_t setrepeater (const char *path);
++
++#endif /* _INPUTDEV_H_ */
+diff -upN ../../console-client/kbd-repeat.c ./kbd-repeat.c
+--- ../../console-client/kbd-repeat.c 1970-01-01 01:00:00.000000000 +0100
++++ console-client/kbd-repeat.c 2004-04-01 03:22:46.000000000 +0200
+@@ -0,0 +1,357 @@
++/* kbd-repeat.c - Keyboard repeater.
++ Copyright (C) 2004 Free Software Foundation, Inc.
++ Written by Marco Gerards.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2, or (at
++ your option) any later version.
++
++ The GNU Hurd is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
++
++
++#include <hurd/trivfs.h>
++#include <stdlib.h>
++#include <error.h>
++#include <string.h>
++#include <fcntl.h>
++#include <sys/mman.h>
++
++#include "kdioctl_S.h"
++#include "inputdev.h"
++#include "input.h"
++
++/* The amount of keyboard events that can be stored in the keyboard buffer. */
++#define KBDEVTBUFSZ 20
++
++/* The size of the keyboard buffer in bytes. */
++#define KBDBUFSZ (KBDEVTBUFSZ * sizeof (kd_event))
++
++/* Return the position of X in the buffer. */
++#define KBDBUF_POS(x) ((x) % KBDBUFSZ)
++
++/* The keyboard buffer. */
++struct kbdbuf
++{
++ char keybuffer[KBDBUFSZ];
++ int pos;
++ size_t size;
++ struct condition readcond;
++ struct condition writecond;
++} kbdbuf;
++
++/* Wakeup for select */
++static struct condition select_alert;
++
++/* The global lock */
++static struct mutex global_lock;
++
++/* Bucket to handle the keyboard RPCs. */
++static struct port_bucket *kbdbucket;
++
++/* Amount of times the device was opened. Normally this translator
++ should be only opened once. */
++int kbd_repeater_opened;
++
++
++static int
++kdioctl_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
++{
++ extern int kdioctl_server (mach_msg_header_t *inp, mach_msg_header_t *outp);
++ return kdioctl_server (inp, outp) || trivfs_demuxer (inp, outp);
++}
++
++
++/* Place the keyboard event KEY in the keyboard buffer. */
++void
++repeat_key (kd_event *key)
++{
++ kd_event *ev;
++
++ mutex_lock (&global_lock);
++ while (kbdbuf.size + sizeof (kd_event) > KBDBUFSZ)
++ {
++ /* The input buffer is full, wait until there is some space. */
++ if (hurd_condition_wait (&kbdbuf.writecond, &global_lock))
++ {
++ mutex_unlock (&global_lock);
++ /* Interrupt, silently continue. */
++ }
++ }
++ ev = (kd_event *) &kbdbuf.keybuffer[KBDBUF_POS (kbdbuf.pos
++ + kbdbuf.size)];
++ kbdbuf.size += sizeof (kd_event);
++ memcpy (ev, key, sizeof (kd_event));
++ condition_broadcast (&kbdbuf.readcond);
++ mutex_unlock (&global_lock);
++}
++
++
++/* Thread to handle operations on the kbdbucket. */
++static any_t
++repeater_translator_function (void *arg)
++{
++ ports_manage_port_operations_one_thread (kbdbucket, kdioctl_demuxer, 0);
++ return 0;
++}
++
++
++/* Set the repeater translator on the node PATH. */
++error_t
++setrepeater (const char *path)
++{
++ error_t err;
++ struct trivfs_control *control;
++ file_t node;
++
++ kbdbucket = ports_create_bucket ();
++
++ node = file_name_lookup (path, O_CREAT|O_NOTRANS, 0664);
++ if (node == MACH_PORT_NULL)
++ return errno;
++
++ err = trivfs_create_control (node, 0, kbdbucket, 0, kbdbucket, &control);
++ if (! err)
++ {
++ mach_port_t right = ports_get_send_right (control);
++ err = file_set_translator (node, 0, FS_TRANS_EXCL | FS_TRANS_SET, 0, 0, 0,
++ right, MACH_MSG_TYPE_COPY_SEND);
++ mach_port_deallocate (mach_task_self (), right);
++ }
++ else
++ return err;
++
++ mutex_init (&global_lock);
++
++ condition_init (&kbdbuf.readcond);
++ condition_init (&kbdbuf.writecond);
++
++ condition_init (&select_alert);
++ condition_implies (&kbdbuf.readcond, &select_alert);
++
++ cthread_detach (cthread_fork (repeater_translator_function, 0));
++
++ return 0;
++}
++
++
++/* Just act like the Mach kbd device. */
++int trivfs_fstype = FSTYPE_DEV;
++int trivfs_fsid = 0;
++
++int trivfs_allow_open = O_READ;
++
++int trivfs_support_read = 1;
++int trivfs_support_write = 0;
++int trivfs_support_exec = 0;
++
++error_t
++trivfs_S_io_select (struct trivfs_protid *cred, mach_port_t reply,
++ mach_msg_type_name_t reply_type, int *type)
++{
++ int available = 0;
++
++ if (!cred)
++ return EOPNOTSUPP;
++
++ if (*type & ~SELECT_READ)
++ return EINVAL;
++
++ if (*type == 0)
++ return 0;
++
++ available = 0;
++
++ mutex_lock (&global_lock);
++ while (1)
++ {
++ if (available && kbdbuf.size > 0)
++ {
++ *type = SELECT_READ;
++ mutex_unlock (&global_lock);
++
++ return 0;
++ }
++
++ if (cred->po->openmodes & O_NONBLOCK)
++ {
++ mutex_unlock (&global_lock);
++
++ return EWOULDBLOCK;
++ }
++
++ ports_interrupt_self_on_port_death (cred, reply);
++ if (hurd_condition_wait (&select_alert, &global_lock))
++ {
++ *type = 0;
++ mutex_unlock (&global_lock);
++
++ return EINTR;
++ }
++ }
++}
++
++
++void
++trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *st)
++{
++ /* Mark the node as a read-only plain file. */
++ st->st_mode &= ~(S_IFMT);
++ st->st_mode |= (S_IRUSR | S_IFCHR);
++
++ st->st_size = 0;
++ st->st_blocks = 0;
++
++}
++
++
++/* No one wants this. Use the console client to terminate the console
++ client or send a signal. */
++error_t
++trivfs_goaway (struct trivfs_control *cntl, int flags)
++{
++ return EOPNOTSUPP;
++}
++
++
++static error_t
++open_hook (struct trivfs_peropen *peropen)
++{
++ /* Make sure the console does not access the hardware anymore. */
++ if (! kbd_repeater_opened)
++ console_switch_away ();
++ kbd_repeater_opened++;
++
++ return 0;
++}
++
++
++static void
++close_hook (struct trivfs_peropen *peropen)
++{
++ kbd_repeater_opened--;
++
++ /* Allow the console to access the hardware again. */
++ if (! kbd_repeater_opened)
++ {
++ console_switch_back ();
++ kbdbuf.pos = 0;
++ kbdbuf.size = 0;
++
++ }
++}
++
++
++/* Read data from an IO object. If offset is -1, read from the object
++ maintained file pointer. If the object is not seekable, offset is
++ ignored. The amount desired to be read is in AMOUNT. */
++error_t
++trivfs_S_io_read (struct trivfs_protid *cred,
++ mach_port_t reply, mach_msg_type_name_t reply_type,
++ char **data, mach_msg_type_number_t *data_len,
++ loff_t offs, mach_msg_type_number_t amount)
++{
++ /* Deny access if they have bad credentials. */
++ if (! cred)
++ return EOPNOTSUPP;
++ else if (! (cred->po->openmodes & O_READ))
++ return EBADF;
++
++
++ mutex_lock (&global_lock);
++ while (amount > kbdbuf.size)
++ {
++ if (cred->po->openmodes & O_NONBLOCK && amount > kbdbuf.size)
++ {
++ mutex_unlock (&global_lock);
++ return EWOULDBLOCK;
++ }
++
++ if (hurd_condition_wait (&kbdbuf.readcond, &global_lock))
++ {
++ mutex_unlock (&global_lock);
++ return EINTR;
++ }
++ }
++
++ if (amount > 0)
++ {
++ char *keydata;
++ unsigned int i = 0;
++
++ /* Allocate a buffer when this is required. */
++ if (*data_len < amount)
++ {
++ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
++ if (*data == MAP_FAILED)
++ {
++ mutex_unlock (&global_lock);
++ return ENOMEM;
++ }
++ }
++
++ /* Copy the bytes to the user's buffer and remove them from the
++ keyboard buffer. */
++ keydata = *data;
++ while (i != amount)
++ {
++ keydata[i++] = kbdbuf.keybuffer[kbdbuf.pos++];
++ kbdbuf.pos = KBDBUF_POS (kbdbuf.pos);
++ }
++ kbdbuf.size -= amount;
++ condition_broadcast (&kbdbuf.writecond);
++ }
++
++ *data_len = amount;
++ mutex_unlock (&global_lock);
++
++ return 0;
++}
++
++
++/* Change current read/write offset */
++error_t
++trivfs_S_io_seek (struct trivfs_protid *cred,
++ mach_port_t reply, mach_msg_type_name_t reply_type,
++ off_t offs, int whence, off_t *new_offs)
++{
++ if (!cred)
++ return EOPNOTSUPP;
++ else
++ return ESPIPE;
++}
++
++
++/* If this variable is set, it is called every time a new peropen
++ structure is created and initialized. */
++error_t (*trivfs_peropen_create_hook)(struct trivfs_peropen *) = open_hook;
++
++/* If this variable is set, it is called every time a peropen structure
++ is about to be destroyed. */
++void (*trivfs_peropen_destroy_hook) (struct trivfs_peropen *) = close_hook;
++
++
++/* Some RPC calls for controlling the keyboard. These calls are just
++ ignored and just exist to make XFree happy. */
++
++kern_return_t
++S_kdioctl_kdskbdmode (io_t port, int mode)
++{
++ return 0;
++}
++
++
++kern_return_t
++S_kdioctl_kdgkbdmode (io_t port, int *mode)
++{
++ return 0;
++}
+diff -upN ../../console-client/pc-kbd.c ./pc-kbd.c
+--- ../../console-client/pc-kbd.c 2004-02-02 22:25:10.000000000 +0100
++++ console-client/pc-kbd.c 2004-03-28 11:35:46.000000000 +0200
+@@ -23,6 +23,7 @@
+ #include <string.h>
+ #include <iconv.h>
+ #include <sys/mman.h>
++#include <argp.h>
+
+ #include <device/device.h>
+ #include <cthreads.h>
+@@ -31,6 +32,7 @@
+ #include <hurd/cons.h>
+
+ #include "driver.h"
++#include "inputdev.h"
+
+
+ /* The keyboard device in the kernel. */
+@@ -52,6 +54,10 @@ int gnumach_v1_compat;
+ /* Forward declaration. */
+ static struct input_ops pc_kbd_ops;
+
++
++/* The node on which the repeater translator is set. */
++static char *repeater_node;
++
+
+ /* A list of scan codes generated by the keyboard, in the set 2 encoding. */
+ enum scancode
+@@ -558,87 +564,6 @@ enum scancode sc_set1_to_set2_x1[] =
+ SC_X1_DEL
+ };
+
+-
+-/* This gross stuff is cut & pasted from Mach sources, as Mach doesn't
+- export the interface we are using here. */
+-
+-/*
+- * Mach Operating System
+- * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+- * All Rights Reserved.
+- *
+- * Permission to use, copy, modify and distribute this software and its
+- * documentation is hereby granted, provided that both the copyright
+- * notice and this permission notice appear in all copies of the
+- * software, derivative works or modified versions, and any portions
+- * thereof, and that both notices appear in supporting documentation.
+- *
+- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+- *
+- * Carnegie Mellon requests users of this software to return to
+- *
+- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+- * School of Computer Science
+- * Carnegie Mellon University
+- * Pittsburgh PA 15213-3890
+- *
+- * any improvements or extensions that they make and grant Carnegie Mellon
+- * the rights to redistribute these changes.
+- */
+-
+-typedef u_short kev_type; /* kd event type */
+-
+-/* (used for event records) */
+-struct mouse_motion {
+- short mm_deltaX; /* units? */
+- short mm_deltaY;
+-};
+-typedef u_char Scancode;
+-
+-typedef struct {
+- kev_type type; /* see below */
+- struct timeval time; /* timestamp */
+- union { /* value associated with event */
+- boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */
+- Scancode sc; /* KEYBD_EVENT */
+- struct mouse_motion mmotion; /* MOUSE_MOTION */
+- } value;
+-} kd_event;
+-#define m_deltaX mmotion.mm_deltaX
+-#define m_deltaY mmotion.mm_deltaY
+-
+-/*
+- * kd_event ID's.
+- */
+-#define MOUSE_LEFT 1 /* mouse left button up/down */
+-#define MOUSE_MIDDLE 2
+-#define MOUSE_RIGHT 3
+-#define MOUSE_MOTION 4 /* mouse motion */
+-#define KEYBD_EVENT 5 /* key up/down */
+-
+-
+-#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */
+-#define IOC_OUT 0x40000000 /* copy out parameters */
+-#define IOC_IN 0x80000000U /* copy in parameters */
+-#define _IOC(inout,group,num,len) \
+- (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
+-#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
+-#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
+-
+-#define KDSKBDMODE _IOW('K', 1, int) /* set keyboard mode */
+-#define KB_EVENT 1
+-#define KB_ASCII 2
+-
+-#define KDGKBDTYPE _IOR('K', 2, int) /* get keyboard type */
+-#define KB_VANILLAKB 0
+-
+-#define KDSETLEDS _IOW('K', 5, int) /* set keyboard leds */
+-
+-
+-/* End of Mach code. */
+-
+ static enum scancode
+ gnumach_v1_input_next ()
+ {
+@@ -658,6 +583,13 @@ gnumach_v1_input_next ()
+ terminate. */
+ if (err)
+ return 0;
++
++ if (kbd_repeater_opened && data_buf.type == KEYBD_EVENT)
++ {
++ repeat_key (&data_buf);
++ data_buf.type = 0;
++ continue;
++ }
+ }
+ while (data_buf.type != KEYBD_EVENT);
+
+@@ -1088,10 +1020,56 @@ input_loop (any_t unused)
+
+
+
++
++
++static const char doc[] = "PC Keyboard Driver";
++
++static const struct argp_option options[] =
++ {
++ {"repeat", 'r', "NODE", 0, "Set a repeater translator on NODE"},
++ { 0 }
++ };
++
++static error_t
++parse_opt (int key, char *arg, struct argp_state *state)
++{
++ int *pos = (int *) state->input;
++
++ switch (key)
++ {
++ case 'r':
++ repeater_node = arg;
++ break;
++
++ case ARGP_KEY_END:
++ break;
++
++ default:
++ return ARGP_ERR_UNKNOWN;
++ }
++
++ *pos = state->next;
++ return 0;
++}
++
++static struct argp argp = {options, parse_opt, 0, doc};
++
+ /* Initialize the PC keyboard driver. */
+ static error_t
+ pc_kbd_init (void **handle, int no_exit, int argc, char *argv[], int *next)
+ {
++ error_t err;
++ int pos = 1;
++
++ /* Parse the arguments. */
++ err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER | ARGP_NO_EXIT
++ | ARGP_SILENT, 0 , &pos);
++ *next += pos - 1;
++
++ if (err && err != EINVAL)
++ return err;
++
++
+ return 0;
+ }
+
+@@ -1156,6 +1134,10 @@ pc_kbd_start (void *handle)
+ iconv_close (cd);
+ return err;
+ }
++
++ if (repeater_node)
++ setrepeater (repeater_node);
++
+ cthread_detach (cthread_fork (input_loop, NULL));
+
+ return 0;