psm.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,239 行 · 第 1/5 页
C
2,239 行
/*- * Copyright (c) 1992, 1993 Erik Forsberg. * Copyright (c) 1996, 1997 Kazutaka YOKOTA. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: psm.c,v 1.60 1999/01/12 00:36:33 eivind Exp $ *//* * Ported to 386bsd Oct 17, 1992 * Sandi Donno, Computer Science, University of Cape Town, South Africa * Please send bug reports to sandi@cs.uct.ac.za * * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca - * although I was only partially successful in getting the alpha release * of his "driver for the Logitech and ATI Inport Bus mice for use with * 386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless * found his code to be an invaluable reference when porting this driver * to 386bsd. * * Further modifications for latest 386BSD+patchkit and port to NetBSD, * Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993 * * Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by * Andrew Herbert - 12 June 1993 * * Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu> * - 13 June 1993 * * Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp> * - 24 October 1993 * * Hardware access routines and probe logic rewritten by * Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp> * - 3, 14, 22 October 1996. * - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'... * - 14, 30 November 1996. Uses `kbdio.c'. * - 13 December 1996. Uses queuing version of `kbdio.c'. * - January/February 1997. Tweaked probe logic for * HiNote UltraII/Latitude/Armada laptops. * - 30 July 1997. Added APM support. * - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX). * Improved sync check logic. * Vendor specific support routines. */#include "psm.h"#include "apm.h"#include "opt_devfs.h"#include "opt_psm.h"#if NPSM > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/poll.h>#include <sys/syslog.h>#include <sys/malloc.h>#ifdef DEVFS#include <sys/devfsext.h>#endif#include <sys/select.h>#include <sys/uio.h>#include <machine/apm_bios.h>#include <machine/clock.h>#include <machine/limits.h>#include <machine/mouse.h>#include <dev/kbd/atkbdcreg.h>#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>/* * Driver specific options: the following options may be set by * `options' statements in the kernel configuration file. *//* debugging */#ifndef PSM_DEBUG#define PSM_DEBUG 0 /* logging: 0: none, 1: brief, 2: verbose */#endif/* features *//* #define PSM_HOOKAPM hook the APM resume event *//* #define PSM_RESETAFTERSUSPEND reset the device at the resume event */#if NAPM <= 0#undef PSM_HOOKAPM#endif /* NAPM */#ifndef PSM_HOOKAPM#undef PSM_RESETAFTERSUSPEND#endif /* PSM_HOOKAPM *//* end of driver specific options *//* input queue */#define PSM_BUFSIZE 960#define PSM_SMALLBUFSIZE 240/* operation levels */#define PSM_LEVEL_BASE 0#define PSM_LEVEL_STANDARD 1#define PSM_LEVEL_NATIVE 2#define PSM_LEVEL_MIN PSM_LEVEL_BASE#define PSM_LEVEL_MAX PSM_LEVEL_NATIVE/* some macros */#define PSM_UNIT(dev) (minor(dev) >> 1)#define PSM_NBLOCKIO(dev) (minor(dev) & 1)#define PSM_MKMINOR(unit,block) (((unit) << 1) | ((block) ? 0:1))#ifndef max#define max(x,y) ((x) > (y) ? (x) : (y))#endif#ifndef min#define min(x,y) ((x) < (y) ? (x) : (y))#endif/* ring buffer */typedef struct ringbuf { int count; /* # of valid elements in the buffer */ int head; /* head pointer */ int tail; /* tail poiner */ unsigned char buf[PSM_BUFSIZE];} ringbuf_t;/* driver control block */static struct psm_softc { /* Driver status information */ struct selinfo rsel; /* Process selecting for Input */ unsigned char state; /* Mouse driver state */ int config; /* driver configuration flags */ int flags; /* other flags */ KBDC kbdc; /* handle to access the keyboard controller */ int addr; /* I/O port address */ mousehw_t hw; /* hardware information */ mousemode_t mode; /* operation mode */ mousemode_t dflt_mode; /* default operation mode */ mousestatus_t status; /* accumulated mouse movement */ ringbuf_t queue; /* mouse status queue */ unsigned char ipacket[16]; /* interim input buffer */ int inputbytes; /* # of bytes in the input buffer */ int button; /* the latest button state */#ifdef DEVFS void *devfs_token; void *b_devfs_token;#endif#ifdef PSM_HOOKAPM struct apmhook resumehook;#endif} *psm_softc[NPSM];/* driver state flags (state) */#define PSM_VALID 0x80#define PSM_OPEN 1 /* Device is open */#define PSM_ASLP 2 /* Waiting for mouse data *//* driver configuration flags (config) */#define PSM_CONFIG_RESOLUTION 0x000f /* resolution */#define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */#define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */#define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */#define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */#define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */#define PSM_CONFIG_IGNPORTERROR 0x1000 /* ignore error in aux port test */#define PSM_CONFIG_FLAGS (PSM_CONFIG_RESOLUTION \ | PSM_CONFIG_ACCEL \ | PSM_CONFIG_NOCHECKSYNC \ | PSM_CONFIG_NOIDPROBE \ | PSM_CONFIG_NORESET \ | PSM_CONFIG_FORCETAP \ | PSM_CONFIG_IGNPORTERROR)/* other flags (flags) *//* for backward compatibility */#define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t)#define OLD_MOUSE_GETMODE _IOR('M', 2, old_mousemode_t)#define OLD_MOUSE_SETMODE _IOW('M', 3, old_mousemode_t)typedef struct old_mousehw { int buttons; int iftype; int type; int hwid;} old_mousehw_t;typedef struct old_mousemode { int protocol; int rate; int resolution; int accelfactor;} old_mousemode_t;/* packet formatting function */typedef int packetfunc_t __P((struct psm_softc *, unsigned char *, int *, int, mousestatus_t *));/* function prototypes */static int psmprobe __P((struct isa_device *));static int psmattach __P((struct isa_device *));static void psm_drvinit __P((void *));#ifdef PSM_HOOKAPMstatic int psmresume __P((void *));#endifstatic d_open_t psmopen;static d_close_t psmclose;static d_read_t psmread;static d_ioctl_t psmioctl;static d_poll_t psmpoll;static int enable_aux_dev __P((KBDC));static int disable_aux_dev __P((KBDC));static int get_mouse_status __P((KBDC, int *, int, int));static int get_aux_id __P((KBDC));static int set_mouse_sampling_rate __P((KBDC, int));static int set_mouse_scaling __P((KBDC, int));static int set_mouse_resolution __P((KBDC, int));#ifdef PSM_RESETAFTERSUSPENDstatic int set_mouse_mode __P((KBDC));#endif /* PSM_RESETAFTERSUSPEND */static int get_mouse_buttons __P((KBDC));static int is_a_mouse __P((int));static void recover_from_error __P((KBDC));static int restore_controller __P((KBDC, int));#ifdef PSM_RESETAFTERSUSPENDstatic int reinitialize __P((int, mousemode_t *));#endifstatic int doopen __P((int, int));static char *model_name(int);static ointhand2_t psmintr;/* vendor specific features */typedef int probefunc_t __P((struct psm_softc *));static int mouse_id_proc1 __P((KBDC, int, int, int *));static probefunc_t enable_groller;static probefunc_t enable_gmouse;static probefunc_t enable_aglide; static probefunc_t enable_kmouse;static probefunc_t enable_msintelli;static probefunc_t enable_mmanplus;static int tame_mouse __P((struct psm_softc *, mousestatus_t *, unsigned char *));static struct { int model; unsigned char syncmask; int packetsize; probefunc_t *probefunc;} vendortype[] = { { MOUSE_MODEL_NET, /* Genius NetMouse */ 0xc8, MOUSE_INTELLI_PACKETSIZE, enable_gmouse, }, { MOUSE_MODEL_NETSCROLL, /* Genius NetScroll */ 0xc8, 6, enable_groller, }, { MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ 0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide, }, { MOUSE_MODEL_MOUSEMANPLUS, /* Logitech MouseMan+ */ 0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus, }, { MOUSE_MODEL_THINK, /* Kensignton ThinkingMouse */ 0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse, }, { MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ 0xc8, MOUSE_INTELLI_PACKETSIZE, enable_msintelli, }, { MOUSE_MODEL_GENERIC, 0xc0, MOUSE_PS2_PACKETSIZE, NULL, },};#define GENERIC_MOUSE_ENTRY 6/* device driver declarateion */struct isa_driver psmdriver = { psmprobe, psmattach, "psm", FALSE };#define CDEV_MAJOR 21static struct cdevsw psm_cdevsw = { psmopen, psmclose, psmread, nowrite, /* 21 */ psmioctl, nostop, nullreset, nodevtotty, psmpoll, nommap, NULL, "psm", NULL, -1};/* debug message level */static int verbose = PSM_DEBUG;/* device I/O routines */static intenable_aux_dev(KBDC kbdc){ int res; res = send_aux_command(kbdc, PSMC_ENABLE_DEV); if (verbose >= 2) log(LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res); return (res == PSM_ACK);}static intdisable_aux_dev(KBDC kbdc){ int res; res = send_aux_command(kbdc, PSMC_DISABLE_DEV); if (verbose >= 2) log(LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res); return (res == PSM_ACK);}static intget_mouse_status(KBDC kbdc, int *status, int flag, int len){ int cmd; int res; int i; switch (flag) { case 0: default: cmd = PSMC_SEND_DEV_STATUS; break; case 1: cmd = PSMC_SEND_DEV_DATA; break; } empty_aux_buffer(kbdc, 5); res = send_aux_command(kbdc, cmd); if (verbose >= 2) log(LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n", (flag == 1) ? "DATA" : "STATUS", res); if (res != PSM_ACK) return 0; for (i = 0; i < len; ++i) { status[i] = read_aux_data(kbdc); if (status[i] < 0) break; } if (verbose) { log(LOG_DEBUG, "psm: %s %02x %02x %02x\n", (flag == 1) ? "data" : "status", status[0], status[1], status[2]); } return i;}static intget_aux_id(KBDC kbdc){ int res; int id; empty_aux_buffer(kbdc, 5); res = send_aux_command(kbdc, PSMC_SEND_DEV_ID); if (verbose >= 2) log(LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res); if (res != PSM_ACK) return (-1); /* 10ms delay */ DELAY(10000); id = read_aux_data(kbdc); if (verbose >= 2) log(LOG_DEBUG, "psm: device ID: %04x\n", id); return id;}static intset_mouse_sampling_rate(KBDC kbdc, int rate){ int res; res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate); if (verbose >= 2) log(LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res); return ((res == PSM_ACK) ? rate : -1);}static intset_mouse_scaling(KBDC kbdc, int scale){ int res; switch (scale) { case 1: default: scale = PSMC_SET_SCALING11; break; case 2: scale = PSMC_SET_SCALING21; break; } res = send_aux_command(kbdc, scale); if (verbose >= 2) log(LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n", (scale == PSMC_SET_SCALING21) ? "21" : "11", res); return (res == PSM_ACK);}/* `val' must be 0 through PSMD_MAX_RESOLUTION */static intset_mouse_resolution(KBDC kbdc, int val){ int res; res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val); if (verbose >= 2) log(LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res); return ((res == PSM_ACK) ? val : -1);}#ifdef PSM_RESETAFTERSUSPEND/* * NOTE: once `set_mouse_mode()' is called, the mouse device must be * re-enabled by calling `enable_aux_dev()' */static intset_mouse_mode(KBDC kbdc){ int res; res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?