summaryrefslogtreecommitdiff
path: root/debian/patches-contrib/kbd.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-contrib/kbd.patch')
-rw-r--r--debian/patches-contrib/kbd.patch815
1 files changed, 815 insertions, 0 deletions
diff --git a/debian/patches-contrib/kbd.patch b/debian/patches-contrib/kbd.patch
new file mode 100644
index 00000000..f32d9a4d
--- /dev/null
+++ b/debian/patches-contrib/kbd.patch
@@ -0,0 +1,815 @@
+--- hurd-20040301.orig/hurd/subsystems
++++ hurd-20040301/hurd/subsystems
+@@ -37,6 +37,7 @@
+ pfinet 37000 Internet configuration calls
+ password 38000 Password checker
+ <ioctl space> 100000- First subsystem of ioctl class 'f' (lowest class)
++kdioctl 120000 Ioctl class 'k' (kd)
+ tioctl 156000 Ioctl class 't' (terminals)
+ tioctl 156200 (continued)
+ <ioctl space> 164200 Last subsystem of ioctl class 'v' (highest class)
+--- hurd-20040301.orig/hurd/kdioctl.defs
++++ hurd-20040301/hurd/kdioctl.defs
+@@ -0,0 +1,39 @@
++/* Definitions for kd ioctls
++ Copyright (C) 1991, 1993, 1994, 1995, 1996, 1998 Free Software Foundation, Inc.
++
++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 the GNU Hurd; see the file COPYING. If not, write to
++the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
++
++#include <hurd/hurd_types.defs>
++
++/* Ioctl class `k'; the subsystem is derived from calculations in
++ <ioctls.h>. */
++subsystem kdioctl 120000;
++
++import <hurd/ioctl_types.h>;
++
++skip; /* 0 unused */
++
++/* 1 KDSKBDMODE */
++routine kdioctl_kdskbdmode (
++ port: io_t;
++ in mode: int);
++/* 2 KDGKBDMODE */
++routine kdioctl_kdgkbdmode (
++ port: io_t;
++ out mode: int);
++
++/* 3 - 256 unused */
+--- hurd-20040301.orig/sutils/MAKEDEV.sh
++++ hurd-20040301/sutils/MAKEDEV.sh
+@@ -86,7 +86,7 @@
+ ;;
+
+ std)
+- mkdev console tty null zero full fd time mem klog shm
++ mkdev console tty null zero full fd time mem klog shm kbd
+ ;;
+ console|com[0-9])
+ st $I root 600 /hurd/term ${DEVDIR}/$I device $I;;
+@@ -115,6 +115,9 @@
+ st $I root 660 /hurd/storeio --no-cache mem ;;
+ klog)
+ st $I root 660 /hurd/streamio kmsg;;
++ kbd)
++ st $I root 666 /hurd/kbd;;
++
+ # ptys
+ [pt]ty[pqrstuvwxyzPQRS]?)
+ # Make one pty, both the master and slave halves.
+--- hurd-20040301.orig/trans/kd.h
++++ hurd-20040301/trans/kd.h
+@@ -0,0 +1,72 @@
++
++/*
++ * Format definitions for 'ioctl' commands in device definitions.
++ *
++ * From BSD4.4.
++ */
++/*
++ * Ioctl's have the command encoded in the lower word, and the size of
++ * any in or out parameters in the upper word. The high 3 bits of the
++ * upper word are used to encode the in/out status of the parameter.
++ */
++#define MACH_IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */
++#define MACH_IOC_VOID 0x20000000 /* no parameters */
++#define MACH_IOC_OUT 0x40000000 /* copy out parameters */
++#define MACH_IOC_IN 0x80000000U /* copy in parameters */
++#define MACH_IOC_INOUT (MACH_IOC_IN|MACH_IOC_OUT)
++
++#define _MACH_IOC(inout,group,num,len) \
++ (inout | ((len & MACH_IOCPARM_MASK) << 16) | ((group) << 8) | (num))
++#define _MACH_IO(g,n) _MACH_IOC(MACH_IOC_VOID, (g), (n), 0)
++#define _MACH_IOR(g,n,t) _MACH_IOC(MACH_IOC_OUT, (g), (n), sizeof(t))
++#define _MACH_IOW(g,n,t) _MACH_IOC(MACH_IOC_IN, (g), (n), sizeof(t))
++#define _MACH_IOWR(g,n,t) _MACH_IOC(MACH_IOC_INOUT, (g), (n), sizeof(t))
++
++/* taken from gnumach-1.1.3/i386/i386at/kd.h */
++
++#define KDSKBDMODE _MACH_IOW('K', 1, int) /* set keyboard mode */
++#define KB_EVENT 1
++#define KB_ASCII 2
++
++#define KDGKBDTYPE _MACH_IOR('K', 2, int) /* get keyboard type */
++
++typedef unsigned short kev_type; /* kd event type */
++typedef unsigned char Scancode;
++/* (used for event records) */
++struct mouse_motion {
++ short mm_deltaX; /* units? */
++ short mm_deltaY;
++};
++
++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;
++
++
++/*
++ * 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 */
++
++/*
++ * Low 3 bits of minor are the com port #.
++ * The high 5 bits of minor are the mouse type
++ */
++#define MOUSE_SYSTEM_MOUSE 0
++#define MICROSOFT_MOUSE 1
++#define IBM_MOUSE 2
++#define NO_MOUSE 3
++#define LOGITECH_TRACKMAN 4
++#define MICROSOFT_MOUSE7 5
++
++
+--- hurd-20040301.orig/trans/Makefile
++++ hurd-20040301/trans/Makefile
+@@ -19,13 +19,15 @@
+ makemode := servers
+
+ targets = symlink firmlink ifsock magic null fifo new-fifo fwd crash \
+- password hello hello-mt streamio fakeroot proxy-defpager
++ password hello hello-mt streamio fakeroot proxy-defpager \
++ kbd mouse
+ SRCS = ifsock.c symlink.c magic.c null.c fifo.c new-fifo.c fwd.c \
+ crash.c firmlink.c password.c hello.c hello-mt.c streamio.c \
+- fakeroot.c proxy-defpager.c
++ fakeroot.c proxy-defpager.c kbd.c mouse.c
+ OBJS = $(SRCS:.c=.o) fsysServer.o ifsockServer.o passwordServer.o \
+ crashServer.o crash_replyUser.o msgServer.o \
+ default_pagerServer.o default_pagerUser.o \
++ kdioctlServer.o \
+ device_replyServer.o elfcore.o
+ HURDLIBS = threads ports trivfs fshelp pipe ihash shouldbeinlibc
+ password-LDLIBS = $(LIBCRYPT)
+@@ -40,6 +42,7 @@
+
+ symlink: fsysServer.o
+ ifsock: ifsockServer.o
++kbd: kdioctlServer.o
+ crash: crashServer.o crash_replyUser.o msgServer.o elfcore.o
+ password: passwordServer.o
+ streamio: device_replyServer.o
+@@ -48,7 +51,7 @@
+ proxy-defpager crash password streamio: ../libthreads/libthreads.a ../libports/libports.a ../libtrivfs/libtrivfs.a ../libthreads/libthreads.a ../libfshelp/libfshelp.a
+ fifo new-fifo: ../libpipe/libpipe.a
+ fwd: ../libfshelp/libfshelp.a ../libports/libports.a
+-hello-mt magic null ifsock fifo new-fifo firmlink: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libthreads/libthreads.a ../libports/libports.a ../libihash/libihash.a
++kbd mouse hello-mt magic null ifsock fifo new-fifo firmlink: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libthreads/libthreads.a ../libports/libports.a ../libihash/libihash.a
+ hello: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libports/libports.a ../libihash/libihash.a
+ fakeroot: ../libnetfs/libnetfs.a ../libfshelp/libfshelp.a ../libiohelp/libiohelp.a ../libthreads/libthreads.a ../libports/libports.a ../libihash/libihash.a
+ $(targets): ../libshouldbeinlibc/libshouldbeinlibc.a
+--- hurd-20040301.orig/trans/kbd.c
++++ hurd-20040301/trans/kbd.c
+@@ -0,0 +1,306 @@
++/* A translator for kbd
++
++ Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
++
++ Written by UCHIYAMA Yasushi <uch@nop.or.jp>
++
++ This program 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.
++
++ This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
++
++#include <hurd.h>
++#include <hurd/ports.h>
++#include <hurd/trivfs.h>
++#include <hurd/fsys.h>
++#include <version.h>
++
++#include <stdio.h>
++#include <unistd.h>
++#include <error.h>
++#include <string.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <argp.h>
++
++
++#include <device/device.h>
++#include "kdioctl_S.h"
++#include "kd.h"
++
++#define KBD_BUF_SIZE 1
++static struct kbd_buffer
++{
++ mach_port_t port;
++ struct mutex lock;
++ struct condition fill;
++ struct condition notfull;
++ kd_event buf[KBD_BUF_SIZE];
++ int cnt;
++ int in;
++ int out;
++} kbd;
++
++static int
++demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
++{
++ extern int kdioctl_server (mach_msg_header_t *, mach_msg_header_t *);
++
++ return (trivfs_demuxer (inp, outp)
++ || kdioctl_server (inp, outp));
++}
++
++static any_t
++kbd_thread (any_t arg)
++{
++ for(;;)
++ {
++ kd_event *event;
++ vm_offset_t buf;
++ mach_msg_type_number_t buf_size;
++ int ncopy;
++ kern_return_t err;
++
++ err = device_read (kbd.port, 0, 0, sizeof (kd_event), (char **)&buf, &buf_size);
++ if (err)
++ return err;
++
++ mutex_lock (&kbd.lock);
++ while (kbd.cnt == KBD_BUF_SIZE)
++ condition_wait (&kbd.notfull, &kbd.lock);
++ ncopy = buf_size / sizeof (kd_event);
++ if (KBD_BUF_SIZE - kbd.cnt < ncopy)
++ ncopy = KBD_BUF_SIZE - kbd.cnt;
++ event = (kd_event*)buf;
++ while (ncopy)
++ {
++ kbd.buf[kbd.in] = *event++;
++ kbd.in = (kbd.in + 1) % KBD_BUF_SIZE;
++ kbd.cnt++;
++ ncopy--;
++ }
++ vm_deallocate (mach_task_self(), buf, buf_size);
++ condition_broadcast (&kbd.fill);
++ mutex_unlock (&kbd.lock);
++ }
++}
++
++/**********************************************************************
++ *open(2), close(2)
++ **********************************************************************/
++static error_t
++open_hook (struct trivfs_peropen *po)
++{
++ kern_return_t err = 0;
++ mach_port_t master;
++
++ mutex_lock (&kbd.lock);
++
++ if (po->openmodes & O_READ)
++ {
++ if( kbd.port != MACH_PORT_NULL)
++ return EBUSY;
++ err = get_privileged_ports (NULL, &master);
++ if (err)
++ return err;
++ err = device_open (master, D_READ, "kbd" , &kbd.port);
++ mach_port_deallocate (mach_task_self(), master);
++ }
++ kbd.cnt = 0;
++ cthread_detach (cthread_fork (kbd_thread, 0));
++ mutex_unlock (&kbd.lock);
++ return err;
++}
++
++static void
++close_hook (struct trivfs_peropen *po)
++{
++ int cnt = 1;
++ int mode = KB_ASCII;
++
++ device_set_status (kbd.port, KDSKBDMODE, (dev_status_t)&mode, cnt);
++ device_close (kbd.port);
++ kbd.port = MACH_PORT_NULL;
++}
++
++/* Trivfs hooks */
++
++error_t (*trivfs_peropen_create_hook) (struct trivfs_peropen *) = open_hook;
++void (*trivfs_peropen_destroy_hook) (struct trivfs_peropen *) = close_hook;
++
++int
++main (int argc, char **argv)
++{
++ error_t err;
++ mach_port_t bootstrap;
++ struct trivfs_control *fsys;
++
++ task_get_bootstrap_port (mach_task_self (), &bootstrap);
++ if (bootstrap == MACH_PORT_NULL)
++ error(1, 0, "Must be started as a translator");
++
++ /* Reply to our parent */
++ err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys);
++ if (err)
++ error(3, err, "Contacting parent");
++ /* Launch. */
++ mutex_init( &kbd.lock );
++ ports_manage_port_operations_multithread (fsys->pi.bucket,demuxer,2 * 60 * 1000, 0, 0);
++
++ exit(0);
++}
++
++/* Trivfs hooks */
++
++int trivfs_fstype = FSTYPE_DEV;
++int trivfs_fsid = 0;
++
++int trivfs_support_read = 1;
++int trivfs_support_write = 0;
++int trivfs_support_exec = 0;
++
++int trivfs_allow_open = O_READ;
++
++void
++trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st)
++{
++ st->st_blksize = vm_page_size * 256; /* Make transfers LARRRRRGE */
++
++ st->st_size = 0;
++ st->st_blocks = 0;
++
++ st->st_mode &= ~S_IFMT;
++ st->st_mode |= S_IFCHR;
++}
++
++error_t
++trivfs_goaway (struct trivfs_control *fsys, int flags)
++{
++ exit (0);
++}
++/***********************************************************************
++ * read(2), select(2)
++ ***********************************************************************/
++/* Read data from an IO object. If offset if -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 AMT. */
++kern_return_t
++trivfs_S_io_read(struct trivfs_protid *cred,
++ mach_port_t reply, mach_msg_type_name_t replytype,
++ data_t *data,
++ mach_msg_type_number_t *datalen,
++ loff_t offs,
++ vm_size_t amt)
++{
++ int i,n;
++ if (!cred)
++ return EOPNOTSUPP;
++ else if (!(cred->po->openmodes & O_READ))
++ return EBADF;
++
++ mutex_lock (&kbd.lock);
++ while (!kbd.cnt)
++ {
++ if (cred->po->openmodes & O_NONBLOCK)
++ {
++ mutex_unlock (&kbd.lock);
++ return EWOULDBLOCK;
++ }
++ if (hurd_condition_wait (&kbd.fill, &kbd.lock))
++ {
++ mutex_unlock (&kbd.lock);
++ return EINTR;
++ }
++ }
++ if ((n = amt / sizeof (kd_event)) > kbd.cnt)
++ n = kbd.cnt;
++ for (i = 0; i < n ; i++)
++ {
++ (*(kd_event **)data)[i] = kbd.buf[kbd.out];
++ kbd.out = (kbd.out + 1) % KBD_BUF_SIZE;
++ kbd.cnt--;
++ }
++ *datalen = n * sizeof (kd_event);
++ if (n)
++ condition_signal (&kbd.notfull);
++ mutex_unlock (&kbd.lock);
++ return 0;
++}
++
++/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG.
++ Block until one of the indicated types of i/o can be done "quickly", and
++ return the types that are then available. ID_TAG is returned as passed; it
++ is just for the convenience of the user in matching up reply messages with
++ specific requests sent. */
++
++kern_return_t
++trivfs_S_io_select (struct trivfs_protid *cred,
++ mach_port_t reply, mach_msg_type_name_t replytype,
++ int *type)
++{
++ if (!cred)
++ return EOPNOTSUPP;
++ if(*type & ~SELECT_READ )
++ return EINVAL;
++
++ mutex_lock (&kbd.lock);
++ while (1)
++ {
++ if (kbd.cnt)
++ {
++ *type = SELECT_READ;
++ mutex_unlock (&kbd.lock);
++ return 0;
++ }
++ ports_interrupt_self_on_port_death (cred, reply);
++ if (hurd_condition_wait (&kbd.fill, &kbd.lock))
++ {
++ *type = 0;
++ mutex_unlock (&kbd.lock);
++ return EINTR;
++ }
++ }
++}
++/***********************************************************************
++ * ioctl(2)
++***********************************************************************/
++kern_return_t
++S_kdioctl_kdskbdmode( io_t port,int mode )
++{
++ kern_return_t err;
++ int cnt = 1;
++ err = device_set_status (kbd.port, KDSKBDMODE, (dev_status_t)&mode, cnt);
++ return err;
++}
++
++kern_return_t
++S_kdioctl_kdgkbdmode( io_t port,int *mode )
++{
++ kern_return_t err;
++ int cnt;
++
++ err = device_get_status (kbd.port, KDGKBDTYPE, (dev_status_t)mode, &cnt);
++ return err;
++}
++
++kern_return_t
++S_kdioctl_kdkdsetled( io_t port,int mode )
++{
++ return EOPNOTSUPP; /* XXX */
++}
++
++kern_return_t
++S_kdioctl_kdkdgetled( io_t port,int *mode )
++{
++ return EOPNOTSUPP; /* XXX */
++}
++
+--- hurd-20040301.orig/trans/mouse.c
++++ hurd-20040301/trans/mouse.c
+@@ -0,0 +1,318 @@
++/* A translator for mouse.
++
++ Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
++
++ Written by UCHIYAMA Yasushi <uch@nop.or.jp>
++
++ This program 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.
++
++ This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
++
++#include <hurd.h>
++#include <hurd/ports.h>
++#include <hurd/trivfs.h>
++#include <hurd/fsys.h>
++#include <version.h>
++
++#include <stdio.h>
++#include <unistd.h>
++#include <error.h>
++#include <string.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <argp.h>
++
++const char *argp_program_version = STANDARD_HURD_VERSION (mouse);
++
++#include <device/device.h>
++#include "kd.h"
++
++static char *arg_mouse_protocol,*arg_mouse_device;
++static char mouse_device_name[16];
++
++#define MOUSE_BUF_SIZE 64
++static struct mouse_buffer
++{
++ mach_port_t port;
++ struct mutex lock;
++ struct condition fill;
++ struct condition notfull;
++ kd_event buf[MOUSE_BUF_SIZE];
++ int cnt;
++ int in;
++ int out;
++} mouse;
++
++/* mouse options. Used for startup */
++static const struct argp_option options[] =
++{
++ {"protocol", 'p' ,"PROTOCOL", 0, "mouse PROTOCOL(ps/2,microsoft etc..."},
++ {"device", 'd' ,"DEVICE" , 0, "mouse DEVICE (com0,com1,none)"},
++ {0,0}
++};
++
++static error_t
++parse_opt (int key, char *arg, struct argp_state *state)
++{
++ switch (key)
++ {
++ case 'p': arg_mouse_protocol = arg ; break;
++ case 'd': arg_mouse_device = arg ; break;
++ default:
++ return ARGP_ERR_UNKNOWN;
++ }
++ return 0;
++}
++
++static int
++set_mouse_device_name()
++{
++ /* See gnumach/i386/i386at/kd_mouse.c */
++ struct {
++ int type;
++ char *name;
++ } mouse_tab[] = {
++ { MOUSE_SYSTEM_MOUSE, "mousesystem"},
++ { MICROSOFT_MOUSE, "microsoft" },
++ { IBM_MOUSE, "ps/2" },
++ { NO_MOUSE, "nomouse" },
++ { LOGITECH_TRACKMAN, "logitech" },
++ { MICROSOFT_MOUSE7, "mouse7" },
++ };
++ int i,n = sizeof mouse_tab / sizeof (mouse_tab[0]);
++ for (i = 0; i < n; i++)
++ if (!strcmp (mouse_tab[i].name, arg_mouse_protocol))
++ {
++ int type, unit, device_minor;
++ type = mouse_tab[i].type;
++ if (arg_mouse_device && !strcmp (arg_mouse_device, "com1"))
++ unit = 1;
++ else
++ unit = 0;
++ device_minor = 0;
++ device_minor |= (type<<3);
++ device_minor |= unit;
++ device_minor = device_minor % 100;
++
++ sprintf (mouse_device_name, "mouse%d", device_minor);
++ return 1;
++ }
++ return 0;
++}
++
++int
++main (int argc, char **argv)
++{
++ error_t err;
++ mach_port_t bootstrap;
++ struct trivfs_control *fsys;
++
++ const struct argp argp = { options , parse_opt };
++
++ if(argp_parse (&argp, argc, argv, 0, 0, 0) )
++ error(1, 0, "argp_parse failed.");
++
++ set_mouse_device_name();
++
++ task_get_bootstrap_port (mach_task_self (), &bootstrap);
++ if (bootstrap == MACH_PORT_NULL)
++ error(1, 0, "Must be started as a translator");
++
++ /* Reply to our parent */
++ err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys);
++ if (err)
++ error(3, err, "Contacting parent");
++ /* Launch. */
++ mutex_init (&mouse.lock);
++ ports_manage_port_operations_multithread (fsys->pi.bucket,trivfs_demuxer, 2 * 60 * 1000, 0, 0);
++
++ exit(0);
++}
++
++static any_t
++mouse_thread (any_t arg)
++{
++ for(;;)
++ {
++ kd_event *event;
++ vm_offset_t buf;
++ mach_msg_type_number_t buf_size;
++ int ncopy;
++ kern_return_t err;
++
++ err = device_read (mouse.port, 0, 0, sizeof (kd_event), (char **)&buf, &buf_size);
++ if (err)
++ return err;
++
++ mutex_lock (&mouse.lock);
++ while (mouse.cnt == MOUSE_BUF_SIZE)
++ condition_wait (&mouse.notfull, &mouse.lock);
++ ncopy = buf_size / sizeof (kd_event);
++ if (MOUSE_BUF_SIZE - mouse.cnt < ncopy )
++ ncopy = MOUSE_BUF_SIZE - mouse.cnt;
++ event = (kd_event*)buf;
++ while (ncopy--)
++ {
++ mouse.buf[mouse.in] = *event++;
++ mouse.in = (mouse.in + 1) % MOUSE_BUF_SIZE;
++ mouse.cnt++;
++ }
++ vm_deallocate (mach_task_self(), buf, buf_size);
++ condition_broadcast (&mouse.fill);
++ mutex_unlock (&mouse.lock);
++ }
++}
++
++static error_t
++open_hook (struct trivfs_peropen *po)
++{
++ kern_return_t err = 0;
++ mach_port_t master;
++ mutex_lock (&mouse.lock);
++ if (po->openmodes & O_READ)
++ {
++ if( mouse.port )
++ return EBUSY;
++ err = get_privileged_ports( NULL, &master );
++ if( err )
++ return err;
++ err = device_open (master, D_READ, mouse_device_name, &mouse.port);
++ mach_port_deallocate (mach_task_self(), master);
++ }
++ mouse.cnt = 0;
++ cthread_detach (cthread_fork (mouse_thread, 0));
++ mutex_unlock (&mouse.lock);
++ return err;
++}
++
++static void
++close_hook (struct trivfs_peropen *po)
++{
++ device_close (mouse.port);
++ mouse.port = (mach_port_t)NULL;
++}
++
++/* Trivfs hooks */
++
++error_t (*trivfs_peropen_create_hook) (struct trivfs_peropen *) = open_hook;
++void (*trivfs_peropen_destroy_hook) (struct trivfs_peropen *) = close_hook;
++
++int trivfs_fstype = FSTYPE_DEV;
++int trivfs_fsid = 0;
++
++int trivfs_support_read = 1;
++int trivfs_support_write = 0;
++int trivfs_support_exec = 0;
++
++int trivfs_allow_open = O_READ | O_WRITE;
++
++void
++trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st)
++{
++ st->st_blksize = vm_page_size * 256; /* Make transfers LARRRRRGE */
++
++ st->st_size = 0;
++ st->st_blocks = 0;
++
++ st->st_mode &= ~S_IFMT;
++ st->st_mode |= S_IFCHR;
++}
++
++error_t
++trivfs_goaway (struct trivfs_control *fsys, int flags)
++{
++ exit (0);
++}
++
++/* Read data from an IO object. If offset if -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 AMT. */
++kern_return_t
++trivfs_S_io_read(struct trivfs_protid *cred,
++ mach_port_t reply, mach_msg_type_name_t replytype,
++ data_t *data,
++ mach_msg_type_number_t *datalen,
++ loff_t offs,
++ vm_size_t amt)
++{
++ int i,n;
++ if (!cred)
++ return EOPNOTSUPP;
++ else if (!(cred->po->openmodes & O_READ))
++ return EBADF;
++
++ mutex_lock (&mouse.lock);
++ while (!mouse.cnt)
++ {
++ if (cred->po->openmodes & O_NONBLOCK)
++ {
++ mutex_unlock (&mouse.lock);
++ return EWOULDBLOCK;
++ }
++ if (hurd_condition_wait (&mouse.fill, &mouse.lock))
++ {
++ mutex_unlock (&mouse.lock);
++ return EINTR;
++ }
++ }
++ if ((n = amt / sizeof (kd_event)) > mouse.cnt)
++ n = mouse.cnt;
++ for (i = 0; i < n; i++)
++ {
++ (*(kd_event **)data)[i] = mouse.buf[mouse.out];
++ mouse.out = (mouse.out + 1 ) % MOUSE_BUF_SIZE;
++ mouse.cnt--;
++ }
++ *datalen = n * sizeof (kd_event);
++ if (n)
++ condition_signal (&mouse.notfull);
++ mutex_unlock (&mouse.lock);
++ return 0;
++}
++
++
++/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG.
++ Block until one of the indicated types of i/o can be done "quickly", and
++ return the types that are then available. ID_TAG is returned as passed; it
++ is just for the convenience of the user in matching up reply messages with
++ specific requests sent. */
++
++kern_return_t
++trivfs_S_io_select (struct trivfs_protid *cred,
++ mach_port_t reply, mach_msg_type_name_t replytype,
++ int *type)
++{
++ if (!cred)
++ return EOPNOTSUPP;
++ if(*type & ~SELECT_READ )
++ return EINVAL;
++
++ mutex_lock (&mouse.lock);
++ while (1)
++ {
++ if (mouse.cnt)
++ {
++ *type = SELECT_READ;
++ mutex_unlock (&mouse.lock);
++ return 0;
++ }
++ ports_interrupt_self_on_port_death (cred, reply);
++ if (hurd_condition_wait (&mouse.fill, &mouse.lock))
++ {
++ *type = 0;
++ mutex_unlock (&mouse.lock);
++ return EINTR;
++ }
++ }
++}
++