--- hurd-20040301.orig/hurd/subsystems +++ hurd-20040301/hurd/subsystems @@ -37,6 +37,7 @@ pfinet 37000 Internet configuration calls password 38000 Password checker 100000- First subsystem of ioctl class 'f' (lowest class) +kdioctl 120000 Ioctl class 'k' (kd) tioctl 156000 Ioctl class 't' (terminals) tioctl 156200 (continued) 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 + +/* Ioctl class `k'; the subsystem is derived from calculations in + . */ +subsystem kdioctl 120000; + +import ; + +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 + + 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#include +#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 + + 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +const char *argp_program_version = STANDARD_HURD_VERSION (mouse); + +#include +#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; + } + } +} +