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 + -
显示快捷键?