diff options
Diffstat (limited to 'debian/patches-contrib/kbd.patch')
-rw-r--r-- | debian/patches-contrib/kbd.patch | 815 |
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; ++ } ++ } ++} ++ |