Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
42ec7868
Commit
42ec7868
authored
Jul 08, 2002
by
Vojtech Pavlik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove mouse drivers no longer needed, because these mice are
now handled by the input subsystem.
parent
a49e82a5
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
2 additions
and
2289 deletions
+2
-2289
drivers/char/Config.help
drivers/char/Config.help
+0
-89
drivers/char/Config.in
drivers/char/Config.in
+1
-16
drivers/char/Makefile
drivers/char/Makefile
+1
-8
drivers/char/adbmouse.c
drivers/char/adbmouse.c
+0
-209
drivers/char/amigamouse.c
drivers/char/amigamouse.c
+0
-213
drivers/char/atixlmouse.c
drivers/char/atixlmouse.c
+0
-151
drivers/char/logibusmouse.c
drivers/char/logibusmouse.c
+0
-165
drivers/char/msbusmouse.c
drivers/char/msbusmouse.c
+0
-175
drivers/char/pc110pad.c
drivers/char/pc110pad.c
+0
-851
drivers/char/pc110pad.h
drivers/char/pc110pad.h
+0
-31
drivers/char/qpmouse.c
drivers/char/qpmouse.c
+0
-381
No files found.
drivers/char/Config.help
View file @
42ec7868
...
...
@@ -633,37 +633,6 @@ CONFIG_BUSMOUSE
The module will be called busmouse.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_MOUSE
This is for machines with a mouse which is neither a serial nor a
bus mouse. Examples are PS/2 mice (such as the track balls on some
laptops) and some digitizer pads. Most people have a regular serial
MouseSystem or Microsoft mouse (made by Logitech) that plugs into a
COM port (rectangular with 9 or 25 pins). These people say N here.
If you have something else, read the Busmouse-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>. This HOWTO contains
information about all non-serial mice, not just bus mice.
If you have a laptop, you either have to check the documentation or
experiment a bit to find out whether the trackball is a serial mouse
or not; it's best to say Y here for you.
Note that the answer to this question won't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about non-serial mice. If unsure, say Y.
CONFIG_LOGIBUSMOUSE
Logitech mouse connected to a proprietary interface card. It's
generally a round connector with 9 pins. Note that the newer mice
made by Logitech don't use the Logitech protocol anymore; for those,
you don't need this option. You want to read the Busmouse-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called busmouse.o. If you are unsure, say N and read the
HOWTO nevertheless: it will tell you what you have.
CONFIG_PSMOUSE
The PS/2 mouse connects to a special mouse port that looks much like
the keyboard port (small circular connector with 6 pins). This way,
...
...
@@ -683,64 +652,6 @@ CONFIG_PSMOUSE
<ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.
CONFIG_82C710_MOUSE
This is a certain kind of PS/2 mouse used on the TI Travelmate. If
you are unsure, try first to say N here and come back if the mouse
doesn't work. Read the Busmouse-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
CONFIG_PC110_PAD
This drives the digitizer pad on the IBM PC110 palmtop. It can turn
the digitizer pad into a PS/2 mouse emulation with tap gestures or
into an absolute pad.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called pc110pad.o.
CONFIG_MS_BUSMOUSE
These animals (also called Inport mice) are connected to an
expansion board using a round connector with 9 pins. If this is what
you have, say Y and read the Busmouse-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
If you are unsure, say N and read the HOWTO nevertheless: it will
tell you what you have. Also be aware that several vendors talk
about 'Microsoft busmouse' and actually mean PS/2 busmouse -- so
count the pins on the connector.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called msbusmouse.o.
CONFIG_ADBMOUSE
Say Y here if you have this type of bus mouse (4 pin connector) as
is common on Macintoshes. You may want to read the Busmouse-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called adbmouse.o.
CONFIG_ATIXL_BUSMOUSE
This is a rare type of busmouse that is connected to the back of an
ATI video card. Say Y if you have one of those. Note however that
most mice by ATI are actually Microsoft busmice; you should say Y to
"Microsoft busmouse support" above if you have one of those. Read
the Busmouse-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called atixlmouse.o.
If you are unsure, say N and read the HOWTO nevertheless: it will
tell you what you have.
CONFIG_QIC02_TAPE
If you have a non-SCSI tape drive like that, say Y. Or, if you want
to compile this driver as a module ( = code which can be inserted in
...
...
drivers/char/Config.in
View file @
42ec7868
...
...
@@ -114,22 +114,7 @@ source drivers/i2c/Config.in
mainmenu_option next_comment
comment 'Mice'
tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
if [ "$CONFIG_BUSMOUSE" != "n" ]; then
dep_tristate ' ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
dep_tristate ' Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
dep_tristate ' Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
if [ "$CONFIG_ADB" = "y" -a "$CONFIG_ADB_KEYBOARD" = "y" ]; then
dep_tristate ' Apple Desktop Bus mouse support (old driver)' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
fi
fi
tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
if [ "$CONFIG_MOUSE" != "n" ]; then
bool ' PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
tristate ' C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
tristate ' PC110 digitizer pad support' CONFIG_PC110_PAD
fi
endmenu
bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
...
...
drivers/char/Makefile
View file @
42ec7868
...
...
@@ -155,8 +155,6 @@ obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o
obj-$(CONFIG_SERIAL_TX3912)
+=
generic_serial.o serial_tx3912.o
obj-$(CONFIG_HVC_CONSOLE)
+=
hvc_console.o
obj-$(CONFIG_ATIXL_BUSMOUSE)
+=
atixlmouse.o
obj-$(CONFIG_LOGIBUSMOUSE)
+=
logibusmouse.o
obj-$(CONFIG_PRINTER)
+=
lp.o
obj-$(CONFIG_BUSMOUSE)
+=
busmouse.o
...
...
@@ -164,12 +162,7 @@ obj-$(CONFIG_DTLK) += dtlk.o
obj-$(CONFIG_R3964)
+=
n_r3964.o
obj-$(CONFIG_APPLICOM)
+=
applicom.o
obj-$(CONFIG_SONYPI)
+=
sonypi.o
obj-$(CONFIG_MS_BUSMOUSE)
+=
msbusmouse.o
obj-$(CONFIG_82C710_MOUSE)
+=
qpmouse.o
obj-$(CONFIG_AMIGAMOUSE)
+=
amigamouse.o
obj-$(CONFIG_ATARIMOUSE)
+=
atarimouse.o
obj-$(CONFIG_ADBMOUSE)
+=
adbmouse.o
obj-$(CONFIG_PC110_PAD)
+=
pc110pad.o
obj-$(CONFIG_RTC)
+=
rtc.o
obj-$(CONFIG_EFI_RTC)
+=
efirtc.o
ifeq
($(CONFIG_PPC),)
...
...
drivers/char/adbmouse.c
deleted
100644 → 0
View file @
a49e82a5
/*
* Macintosh ADB Mouse driver for Linux
*
* 27 Oct 1997 Michael Schmitz
* logitech fixes by anthony tong
* further hacking by Paul Mackerras
*
* Apple mouse protocol according to:
*
* Device code shamelessly stolen from:
*/
/*
* Atari Mouse Driver for Linux
* by Robert de Vries (robert@and.nl) 19Jul93
*
* 16 Nov 1994 Andreas Schwab
* Compatibility with busmouse
* Support for three button mouse (shamelessly stolen from MiNT)
* third button wired to one of the joystick directions on joystick 1
*
* 1996/02/11 Andreas Schwab
* Module support
* Allow multiple open's
*
* Converted to use new generic busmouse code. 11 July 1998
* Russell King <rmk@arm.uk.linux.org>
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/adb_mouse.h>
#ifdef __powerpc__
#include <asm/processor.h>
#endif
#if defined(__mc68000__) || defined(MODULE)
#include <asm/setup.h>
#endif
#include "busmouse.h"
static
int
msedev
;
static
unsigned
char
adb_mouse_buttons
[
16
];
extern
void
(
*
adb_mouse_interrupt_hook
)(
unsigned
char
*
,
int
);
extern
int
adb_emulate_buttons
;
extern
int
adb_button2_keycode
;
extern
int
adb_button3_keycode
;
/*
* XXX: need to figure out what ADB mouse packets mean ...
* This is the stuff stolen from the Atari driver ...
*/
static
void
adb_mouse_interrupt
(
unsigned
char
*
buf
,
int
nb
)
{
int
buttons
,
id
;
char
dx
,
dy
;
/*
Handler 1 -- 100cpi original Apple mouse protocol.
Handler 2 -- 200cpi original Apple mouse protocol.
For Apple's standard one-button mouse protocol the data array will
contain the following values:
BITS COMMENTS
data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
data[1] = bxxx xxxx First button and x-axis motion.
data[2] = byyy yyyy Second button and y-axis motion.
Handler 4 -- Apple Extended mouse protocol.
For Apple's 3-button mouse protocol the data array will contain the
following values:
BITS COMMENTS
data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
data[1] = bxxx xxxx Left button and x-axis motion.
data[2] = byyy yyyy Second button and y-axis motion.
data[3] = byyy bxxx Third button and fourth button.
Y is additiona. high bits of y-axis motion.
X is additional high bits of x-axis motion.
'buttons' here means 'button down' states!
Button 1 (left) : bit 2, busmouse button 3
Button 2 (right) : bit 0, busmouse button 1
Button 3 (middle): bit 1, busmouse button 2
*/
/* x/y and buttons swapped */
id
=
(
buf
[
0
]
>>
4
)
&
0xf
;
buttons
=
adb_mouse_buttons
[
id
];
/* button 1 (left, bit 2) */
buttons
=
(
buttons
&
3
)
|
(
buf
[
1
]
&
0x80
?
4
:
0
);
/* 1+2 unchanged */
/* button 2 (middle) */
buttons
=
(
buttons
&
5
)
|
(
buf
[
2
]
&
0x80
?
2
:
0
);
/* 2+3 unchanged */
/* button 3 (right) present?
* on a logitech mouseman, the right and mid buttons sometimes behave
* strangely until they both have been pressed after booting. */
/* data valid only if extended mouse format ! */
if
(
nb
>=
4
)
buttons
=
(
buttons
&
6
)
|
(
buf
[
3
]
&
0x80
?
1
:
0
);
/* 1+3 unchanged */
adb_mouse_buttons
[
id
]
=
buttons
;
/* a button is down if it is down on any mouse */
for
(
id
=
0
;
id
<
16
;
++
id
)
buttons
&=
adb_mouse_buttons
[
id
];
dx
=
((
buf
[
2
]
&
0x7f
)
<
64
?
(
buf
[
2
]
&
0x7f
)
:
(
buf
[
2
]
&
0x7f
)
-
128
);
dy
=
((
buf
[
1
]
&
0x7f
)
<
64
?
(
buf
[
1
]
&
0x7f
)
:
(
buf
[
1
]
&
0x7f
)
-
128
);
busmouse_add_movementbuttons
(
msedev
,
dx
,
-
dy
,
buttons
);
if
(
console_loglevel
>=
8
)
printk
(
" %X %X %X dx %d dy %d
\n
"
,
buf
[
1
],
buf
[
2
],
buf
[
3
],
dx
,
dy
);
}
static
int
release_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
adb_mouse_interrupt_hook
=
NULL
;
/*
* FIXME?: adb_mouse_interrupt_hook may still be executing
* on another CPU.
*/
return
0
;
}
static
int
open_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
adb_mouse_interrupt_hook
=
adb_mouse_interrupt
;
return
0
;
}
static
struct
busmouse
adb_mouse
=
{
ADB_MOUSE_MINOR
,
"adbmouse"
,
THIS_MODULE
,
open_mouse
,
release_mouse
,
7
};
static
int
__init
adb_mouse_init
(
void
)
{
#ifdef __powerpc__
if
((
_machine
!=
_MACH_chrp
)
&&
(
_machine
!=
_MACH_Pmac
))
return
-
ENODEV
;
#endif
#ifdef __mc68000__
if
(
!
MACH_IS_MAC
)
return
-
ENODEV
;
#endif
/* all buttons up */
memset
(
adb_mouse_buttons
,
7
,
sizeof
(
adb_mouse_buttons
));
msedev
=
register_busmouse
(
&
adb_mouse
);
if
(
msedev
<
0
)
printk
(
KERN_WARNING
"Unable to register ADB mouse driver.
\n
"
);
else
printk
(
KERN_INFO
"Macintosh ADB mouse driver installed.
\n
"
);
return
msedev
<
0
?
msedev
:
0
;
}
#ifndef MODULE
/*
* XXX this function is misnamed.
* It is called if the kernel is booted with the adb_buttons=xxx
* option, which is about using ADB keyboard buttons to emulate
* mouse buttons. -- paulus
*/
static
int
__init
adb_mouse_setup
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>=
1
)
{
adb_emulate_buttons
=
ints
[
1
];
if
(
ints
[
0
]
>=
2
)
adb_button2_keycode
=
ints
[
2
];
if
(
ints
[
0
]
>=
3
)
adb_button3_keycode
=
ints
[
3
];
}
return
1
;
}
__setup
(
"adb_buttons="
,
adb_mouse_setup
);
#endif
/* !MODULE */
static
void
__exit
adb_mouse_cleanup
(
void
)
{
unregister_busmouse
(
msedev
);
}
module_init
(
adb_mouse_init
);
module_exit
(
adb_mouse_cleanup
);
MODULE_LICENSE
(
"GPL"
);
drivers/char/amigamouse.c
deleted
100644 → 0
View file @
a49e82a5
/*
* Amiga Mouse Driver for Linux 68k by Michael Rausch
* based upon:
*
* Logitech Bus Mouse Driver for Linux
* by James Banks
*
* Mods by Matthew Dillon
* calls verify_area()
* tracks better when X is busy or paging
*
* Heavily modified by David Giller
* changed from queue- to counter- driven
* hacked out a (probably incorrect) mouse_poll
*
* Modified again by Nathan Laredo to interface with
* 0.96c-pl1 IRQ handling changes (13JUL92)
* didn't bother touching poll code.
*
* Modified the poll() code blindly to conform to the VFS
* requirements. 92.07.14 - Linus. Somebody should test it out.
*
* Modified by Johan Myreen to make room for other mice (9AUG92)
* removed assignment chr_fops[10] = &mouse_fops; see mouse.c
* renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
* renamed this file mouse.c => busmouse.c
*
* Modified for use in the 1.3 kernels by Jes Sorensen.
*
* Moved the isr-allocation to the mouse_{open,close} calls, as there
* is no reason to service the mouse in the vertical blank isr if
* the mouse is not in use. Jes Sorensen
*
* Converted to use new generic busmouse code. 5 Apr 1998
* Russell King <rmk@arm.uk.linux.org>
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/logibusmouse.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include "busmouse.h"
#if AMIGA_OLD_INT
#define AMI_MSE_INT_ON() mouseint_allowed = 1
#define AMI_MSE_INT_OFF() mouseint_allowed = 0
static
int
mouseint_allowed
;
#endif
static
int
msedev
;
static
void
mouse_interrupt
(
int
irq
,
void
*
dummy
,
struct
pt_regs
*
fp
)
{
static
int
lastx
=
0
,
lasty
=
0
;
int
dx
,
dy
;
int
nx
,
ny
;
unsigned
char
buttons
;
unsigned
short
joy0dat
,
potgor
;
#if AMIGA_OLD_INT
if
(
!
mouseint_allowed
)
return
;
AMI_MSE_INT_OFF
();
#endif
/*
* This routine assumes, just like Kickstart, that the mouse
* has not moved more than 127 ticks since last VBL.
*/
joy0dat
=
custom
.
joy0dat
;
nx
=
joy0dat
&
0xff
;
ny
=
joy0dat
>>
8
;
dx
=
nx
-
lastx
;
if
(
dx
<
-
127
)
dx
=
(
256
+
nx
)
-
lastx
;
if
(
dx
>
127
)
dx
=
(
nx
-
256
)
-
lastx
;
dy
=
ny
-
lasty
;
if
(
dy
<
-
127
)
dy
=
(
256
+
ny
)
-
lasty
;
if
(
dy
>
127
)
dy
=
(
ny
-
256
)
-
lasty
;
lastx
=
nx
;
lasty
=
ny
;
#if 0
dx = -lastdx;
dx += (lastdx = joy0dat & 0xff);
if (dx < -127)
dx = -255-dx; /* underrun */
else
if (dx > 127)
dx = 255-dx; /* overflow */
dy = -lastdy;
dy += (lastdy = joy0dat >> 8);
if (dy < -127)
dy = -255-dy;
else
if (dy > 127)
dy = 255-dy;
#endif
potgor
=
custom
.
potgor
;
buttons
=
(
ciaa
.
pra
&
0x40
?
4
:
0
)
|
/* left button; note that the bits are low-active, as are the expected results -> double negation */
#if 1
(
potgor
&
0x0100
?
2
:
0
)
|
/* middle button; emulation goes here */
#endif
(
potgor
&
0x0400
?
1
:
0
);
/* right button */
busmouse_add_movementbuttons
(
msedev
,
dx
,
-
dy
,
buttons
);
#if AMIGA_OLD_INT
AMI_MSE_INT_ON
();
#endif
}
/*
* close access to the mouse
*/
static
int
release_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
free_irq
(
IRQ_AMIGA_VERTB
,
mouse_interrupt
);
#if AMIGA_OLD_INT
AMI_MSE_INT_OFF
();
#endif
return
0
;
}
/*
* open access to the mouse, currently only one open is
* allowed.
*/
static
int
open_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
/*
* use VBL to poll mouse deltas
*/
if
(
request_irq
(
IRQ_AMIGA_VERTB
,
mouse_interrupt
,
0
,
"Amiga mouse"
,
mouse_interrupt
))
{
printk
(
KERN_INFO
"Installing Amiga mouse failed.
\n
"
);
return
-
EIO
;
}
#if AMIGA_OLD_INT
AMI_MSE_INT_ON
();
#endif
return
0
;
}
static
struct
busmouse
amigamouse
=
{
AMIGAMOUSE_MINOR
,
"amigamouse"
,
THIS_MODULE
,
open_mouse
,
release_mouse
,
7
};
static
int
__init
amiga_mouse_init
(
void
)
{
if
(
!
MACH_IS_AMIGA
||
!
AMIGAHW_PRESENT
(
AMI_MOUSE
))
return
-
ENODEV
;
if
(
!
request_mem_region
(
CUSTOM_PHYSADDR
+
10
,
2
,
"amigamouse [Denise]"
))
return
-
EBUSY
;
custom
.
joytest
=
0
;
/* reset counters */
#if AMIGA_OLD_INT
AMI_MSE_INT_OFF
();
#endif
msedev
=
register_busmouse
(
&
amigamouse
);
if
(
msedev
<
0
)
printk
(
KERN_WARNING
"Unable to install Amiga mouse driver.
\n
"
);
else
printk
(
KERN_INFO
"Amiga mouse installed.
\n
"
);
return
msedev
<
0
?
msedev
:
0
;
}
static
void
__exit
amiga_mouse_exit
(
void
)
{
unregister_busmouse
(
msedev
);
release_mem_region
(
CUSTOM_PHYSADDR
+
10
,
2
);
}
module_init
(
amiga_mouse_init
);
module_exit
(
amiga_mouse_exit
);
MODULE_LICENSE
(
"GPL"
);
drivers/char/atixlmouse.c
deleted
100644 → 0
View file @
a49e82a5
/*
* ATI XL Bus Mouse Driver for Linux
* by Bob Harris (rth@sparta.com)
*
* Uses VFS interface for linux 0.98 (01OCT92)
*
* Modified by Chris Colohan (colohan@eecg.toronto.edu)
* Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*
* Converted to use new generic busmouse code. 5 Apr 1998
* Russell King <rmk@arm.uk.linux.org>
*
* version 0.3a
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
#include "busmouse.h"
#define ATIXL_MOUSE_IRQ 5
/* H/W interrupt # set up on ATIXL board */
#define ATIXL_BUSMOUSE 3
/* Minor device # (mknod c 10 3 /dev/bm) */
/* ATI XL Inport Busmouse Definitions */
#define ATIXL_MSE_DATA_PORT 0x23d
#define ATIXL_MSE_SIGNATURE_PORT 0x23e
#define ATIXL_MSE_CONTROL_PORT 0x23c
#define ATIXL_MSE_READ_BUTTONS 0x00
#define ATIXL_MSE_READ_X 0x01
#define ATIXL_MSE_READ_Y 0x02
/* Some nice ATI XL macros */
/* Select IR7, HOLD UPDATES (INT ENABLED), save X,Y */
#define ATIXL_MSE_DISABLE_UPDATE() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
outb( (0x20 | inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
/* Select IR7, Enable updates (INT ENABLED) */
#define ATIXL_MSE_ENABLE_UPDATE() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
outb( (0xdf & inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
/* Select IR7 - Mode Register, NO INTERRUPTS */
#define ATIXL_MSE_INT_OFF() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
outb( (0xe7 & inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
/* Select IR7 - Mode Register, DATA INTERRUPTS ENABLED */
#define ATIXL_MSE_INT_ON() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
outb( (0x08 | inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
/* Same general mouse structure */
static
int
msedev
;
static
void
mouse_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
char
dx
,
dy
,
buttons
;
ATIXL_MSE_DISABLE_UPDATE
();
/* Note that interrupts are still enabled */
outb
(
ATIXL_MSE_READ_X
,
ATIXL_MSE_CONTROL_PORT
);
/* Select IR1 - X movement */
dx
=
inb
(
ATIXL_MSE_DATA_PORT
);
outb
(
ATIXL_MSE_READ_Y
,
ATIXL_MSE_CONTROL_PORT
);
/* Select IR2 - Y movement */
dy
=
inb
(
ATIXL_MSE_DATA_PORT
);
outb
(
ATIXL_MSE_READ_BUTTONS
,
ATIXL_MSE_CONTROL_PORT
);
/* Select IR0 - Button Status */
buttons
=
inb
(
ATIXL_MSE_DATA_PORT
);
busmouse_add_movementbuttons
(
msedev
,
dx
,
-
dy
,
buttons
);
ATIXL_MSE_ENABLE_UPDATE
();
}
static
int
release_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
ATIXL_MSE_INT_OFF
();
/* Interrupts are really shut down here */
free_irq
(
ATIXL_MOUSE_IRQ
,
NULL
);
return
0
;
}
static
int
open_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
request_irq
(
ATIXL_MOUSE_IRQ
,
mouse_interrupt
,
0
,
"ATIXL mouse"
,
NULL
))
return
-
EBUSY
;
ATIXL_MSE_INT_ON
();
/* Interrupts are really enabled here */
return
0
;
}
static
struct
busmouse
atixlmouse
=
{
ATIXL_BUSMOUSE
,
"atixl"
,
THIS_MODULE
,
open_mouse
,
release_mouse
,
0
};
static
int
__init
atixl_busmouse_init
(
void
)
{
unsigned
char
a
,
b
,
c
;
/*
* We must request the resource and claim it atomically
* nowdays. We can throw it away on error. Otherwise we
* may race another module load of the same I/O
*/
if
(
!
request_region
(
ATIXL_MSE_DATA_PORT
,
3
,
"atixlmouse"
))
return
-
EIO
;
a
=
inb
(
ATIXL_MSE_SIGNATURE_PORT
);
/* Get signature */
b
=
inb
(
ATIXL_MSE_SIGNATURE_PORT
);
c
=
inb
(
ATIXL_MSE_SIGNATURE_PORT
);
if
((
a
!=
b
)
&&
(
a
==
c
))
printk
(
KERN_INFO
"
\n
ATI Inport "
);
else
{
release_region
(
ATIXL_MSE_DATA_PORT
,
3
);
return
-
EIO
;
}
outb
(
0x80
,
ATIXL_MSE_CONTROL_PORT
);
/* Reset the Inport device */
outb
(
0x07
,
ATIXL_MSE_CONTROL_PORT
);
/* Select Internal Register 7 */
outb
(
0x0a
,
ATIXL_MSE_DATA_PORT
);
/* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */
msedev
=
register_busmouse
(
&
atixlmouse
);
if
(
msedev
<
0
)
{
printk
(
"Bus mouse initialisation error.
\n
"
);
release_region
(
ATIXL_MSE_DATA_PORT
,
3
);
/* Was missing */
}
else
printk
(
"Bus mouse detected and installed.
\n
"
);
return
msedev
<
0
?
msedev
:
0
;
}
static
void
__exit
atixl_cleanup
(
void
)
{
release_region
(
ATIXL_MSE_DATA_PORT
,
3
);
unregister_busmouse
(
msedev
);
}
module_init
(
atixl_busmouse_init
);
module_exit
(
atixl_cleanup
);
MODULE_LICENSE
(
"GPL"
);
drivers/char/logibusmouse.c
deleted
100644 → 0
View file @
a49e82a5
/*
* Logitech Bus Mouse Driver for Linux
* by James Banks
*
* Mods by Matthew Dillon
* calls verify_area()
* tracks better when X is busy or paging
*
* Heavily modified by David Giller
* changed from queue- to counter- driven
* hacked out a (probably incorrect) mouse_select
*
* Modified again by Nathan Laredo to interface with
* 0.96c-pl1 IRQ handling changes (13JUL92)
* didn't bother touching select code.
*
* Modified the select() code blindly to conform to the VFS
* requirements. 92.07.14 - Linus. Somebody should test it out.
*
* Modified by Johan Myreen to make room for other mice (9AUG92)
* removed assignment chr_fops[10] = &mouse_fops; see mouse.c
* renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
* renamed this file mouse.c => busmouse.c
*
* Minor addition by Cliff Matthews
* added fasync support
*
* Modularised 6-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*
* Replaced dumb busy loop with udelay() 16 Nov 95
* Nathan Laredo <laredo@gnu.ai.mit.edu>
*
* Track I/O ports with request_region(). 12 Dec 95 Philip Blundell
*
* Converted to use new generic busmouse code. 5 Apr 1998
* Russell King <rmk@arm.uk.linux.org>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/logibusmouse.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
#include "busmouse.h"
static
int
msedev
;
static
int
mouse_irq
=
MOUSE_IRQ
;
MODULE_PARM
(
mouse_irq
,
"i"
);
#ifndef MODULE
static
int
__init
bmouse_setup
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>
0
)
mouse_irq
=
ints
[
1
];
return
1
;
}
__setup
(
"logi_busmouse="
,
bmouse_setup
);
#endif
/* !MODULE */
static
void
mouse_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
char
dx
,
dy
;
unsigned
char
buttons
;
outb
(
MSE_READ_X_LOW
,
MSE_CONTROL_PORT
);
dx
=
(
inb
(
MSE_DATA_PORT
)
&
0xf
);
outb
(
MSE_READ_X_HIGH
,
MSE_CONTROL_PORT
);
dx
|=
(
inb
(
MSE_DATA_PORT
)
&
0xf
)
<<
4
;
outb
(
MSE_READ_Y_LOW
,
MSE_CONTROL_PORT
);
dy
=
(
inb
(
MSE_DATA_PORT
)
&
0xf
);
outb
(
MSE_READ_Y_HIGH
,
MSE_CONTROL_PORT
);
buttons
=
inb
(
MSE_DATA_PORT
);
dy
|=
(
buttons
&
0xf
)
<<
4
;
buttons
=
((
buttons
>>
5
)
&
0x07
);
busmouse_add_movementbuttons
(
msedev
,
dx
,
-
dy
,
buttons
);
MSE_INT_ON
();
}
/*
* close access to the mouse
*/
static
int
close_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
MSE_INT_OFF
();
free_irq
(
mouse_irq
,
NULL
);
return
0
;
}
/*
* open access to the mouse
*/
static
int
open_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
request_irq
(
mouse_irq
,
mouse_interrupt
,
0
,
"busmouse"
,
NULL
))
return
-
EBUSY
;
MSE_INT_ON
();
return
0
;
}
static
struct
busmouse
busmouse
=
{
LOGITECH_BUSMOUSE
,
"busmouse"
,
THIS_MODULE
,
open_mouse
,
close_mouse
,
7
};
static
int
__init
logi_busmouse_init
(
void
)
{
if
(
!
request_region
(
LOGIBM_BASE
,
LOGIBM_EXTENT
,
"busmouse"
))
return
-
EIO
;
outb
(
MSE_CONFIG_BYTE
,
MSE_CONFIG_PORT
);
outb
(
MSE_SIGNATURE_BYTE
,
MSE_SIGNATURE_PORT
);
udelay
(
100L
);
/* wait for reply from mouse */
if
(
inb
(
MSE_SIGNATURE_PORT
)
!=
MSE_SIGNATURE_BYTE
)
{
release_region
(
LOGIBM_BASE
,
LOGIBM_EXTENT
);
return
-
EIO
;
}
outb
(
MSE_DEFAULT_MODE
,
MSE_CONFIG_PORT
);
MSE_INT_OFF
();
msedev
=
register_busmouse
(
&
busmouse
);
if
(
msedev
<
0
)
{
release_region
(
LOGIBM_BASE
,
LOGIBM_EXTENT
);
printk
(
KERN_WARNING
"Unable to register busmouse driver.
\n
"
);
}
else
printk
(
KERN_INFO
"Logitech busmouse installed.
\n
"
);
return
msedev
<
0
?
msedev
:
0
;
}
static
void
__exit
logi_busmouse_cleanup
(
void
)
{
unregister_busmouse
(
msedev
);
release_region
(
LOGIBM_BASE
,
LOGIBM_EXTENT
);
}
module_init
(
logi_busmouse_init
);
module_exit
(
logi_busmouse_cleanup
);
MODULE_LICENSE
(
"GPL"
);
drivers/char/msbusmouse.c
deleted
100644 → 0
View file @
a49e82a5
/*
* Microsoft busmouse driver based on Logitech driver (see busmouse.c)
*
* Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
*
* Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
* 8/28/92
*
* Microsoft Bus Mouse support folded into 0.97pl4 code
* by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
* Changes: Logitech and Microsoft support in the same kernel.
* Defined new constants in busmouse.h for MS mice.
* Added int mse_busmouse_type to distinguish busmouse types
* Added a couple of new functions to handle differences in using
* MS vs. Logitech (where the int variable wasn't appropriate).
*
* Modified by Peter Cervasio (address above) (26SEP92)
* Changes: Included code to (properly?) detect when a Microsoft mouse is
* really attached to the machine. Don't know what this does to
* Logitech bus mice, but all it does is read ports.
*
* Modified by Christoph Niemann (niemann@rubdv15.etdv.ruhr-uni-bochum.de)
* Changes: Better interrupt-handler (like in busmouse.c).
* Some changes to reduce code-size.
* Changed detection code to use inb_p() instead of doing empty
* loops to delay i/o.
*
* Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*
* Converted to use new generic busmouse code. 5 Apr 1998
* Russell King <rmk@arm.uk.linux.org>
*
* version 0.3b
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/logibusmouse.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
#include "busmouse.h"
static
int
msedev
;
static
int
mouse_irq
=
MOUSE_IRQ
;
MODULE_PARM
(
mouse_irq
,
"i"
);
#ifndef MODULE
static
int
__init
msmouse_setup
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>
0
)
mouse_irq
=
ints
[
1
];
return
1
;
}
__setup
(
"msmouse="
,
msmouse_setup
);
#endif
/* !MODULE */
static
void
ms_mouse_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
char
dx
,
dy
;
unsigned
char
buttons
;
outb
(
MS_MSE_COMMAND_MODE
,
MS_MSE_CONTROL_PORT
);
outb
((
inb
(
MS_MSE_DATA_PORT
)
|
0x20
),
MS_MSE_DATA_PORT
);
outb
(
MS_MSE_READ_X
,
MS_MSE_CONTROL_PORT
);
dx
=
inb
(
MS_MSE_DATA_PORT
);
outb
(
MS_MSE_READ_Y
,
MS_MSE_CONTROL_PORT
);
dy
=
inb
(
MS_MSE_DATA_PORT
);
outb
(
MS_MSE_READ_BUTTONS
,
MS_MSE_CONTROL_PORT
);
buttons
=
~
(
inb
(
MS_MSE_DATA_PORT
))
&
0x07
;
outb
(
MS_MSE_COMMAND_MODE
,
MS_MSE_CONTROL_PORT
);
outb
((
inb
(
MS_MSE_DATA_PORT
)
&
0xdf
),
MS_MSE_DATA_PORT
);
/* why did the original have:
* if (dx != 0 || dy != 0 || buttons != mouse.buttons ||
* ((~buttons) & 0x07))
* ^^^^^^^^^^^^^^^^^^^ this?
*/
busmouse_add_movementbuttons
(
msedev
,
dx
,
-
dy
,
buttons
);
}
static
int
release_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
MS_MSE_INT_OFF
();
free_irq
(
mouse_irq
,
NULL
);
return
0
;
}
static
int
open_mouse
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
request_irq
(
mouse_irq
,
ms_mouse_interrupt
,
0
,
"MS Busmouse"
,
NULL
))
return
-
EBUSY
;
outb
(
MS_MSE_START
,
MS_MSE_CONTROL_PORT
);
MS_MSE_INT_ON
();
return
0
;
}
static
struct
busmouse
msbusmouse
=
{
MICROSOFT_BUSMOUSE
,
"msbusmouse"
,
THIS_MODULE
,
open_mouse
,
release_mouse
,
0
};
static
int
__init
ms_bus_mouse_init
(
void
)
{
int
present
=
0
;
int
mse_byte
,
i
;
if
(
check_region
(
MS_MSE_CONTROL_PORT
,
0x04
))
return
-
ENODEV
;
if
(
inb_p
(
MS_MSE_SIGNATURE_PORT
)
==
0xde
)
{
mse_byte
=
inb_p
(
MS_MSE_SIGNATURE_PORT
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
inb_p
(
MS_MSE_SIGNATURE_PORT
)
==
0xde
)
{
if
(
inb_p
(
MS_MSE_SIGNATURE_PORT
)
==
mse_byte
)
present
=
1
;
else
present
=
0
;
}
else
present
=
0
;
}
}
if
(
present
==
0
)
return
-
EIO
;
if
(
!
request_region
(
MS_MSE_CONTROL_PORT
,
0x04
,
"MS Busmouse"
))
return
-
EIO
;
MS_MSE_INT_OFF
();
msedev
=
register_busmouse
(
&
msbusmouse
);
if
(
msedev
<
0
)
{
printk
(
KERN_WARNING
"Unable to register msbusmouse driver.
\n
"
);
release_region
(
MS_MSE_CONTROL_PORT
,
0x04
);
}
else
printk
(
KERN_INFO
"Microsoft BusMouse detected and installed.
\n
"
);
return
msedev
<
0
?
msedev
:
0
;
}
static
void
__exit
ms_bus_mouse_exit
(
void
)
{
unregister_busmouse
(
msedev
);
release_region
(
MS_MSE_CONTROL_PORT
,
0x04
);
}
module_init
(
ms_bus_mouse_init
)
module_exit
(
ms_bus_mouse_exit
)
MODULE_LICENSE
(
"GPL"
);
drivers/char/pc110pad.c
deleted
100644 → 0
View file @
a49e82a5
/*
* Linux driver for the PC110 pad
*/
/**
* DOC: PC110 Digitizer Hardware
*
* The pad provides triples of data. The first byte has
* 0x80=bit 8 X, 0x01=bit 7 X, 0x08=bit 8 Y, 0x01=still down
* The second byte is bits 0-6 X
* The third is bits 0-6 Y
*
* This is read internally and used to synthesize a stream of
* triples in the form expected from a PS/2 device. Specialist
* applications can choose to obtain the pad data in other formats
* including a debugging mode.
*
* It would be good to add a joystick driver mode to this pad so
* that doom and other game playing are better. One possible approach
* would be to deactive the mouse mode while the joystick port is opened.
*/
/*
* History
*
* 0.0 1997-05-16 Alan Cox <alan@redhat.com> - Pad reader
* 0.1 1997-05-19 Robin O'Leary <robin@acm.org> - PS/2 emulation
* 0.2 1997-06-03 Robin O'Leary <robin@acm.org> - tap gesture
* 0.3 1997-06-27 Alan Cox <alan@redhat.com> - 2.1 commit
* 0.4 1997-11-09 Alan Cox <alan@redhat.com> - Single Unix VFS API changes
* 0.5 2000-02-10 Alan Cox <alan@redhat.com> - 2.3.x cleanup, documentation
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/ptrace.h>
#include <linux/poll.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/semaphore.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include "pc110pad.h"
static
struct
pc110pad_params
default_params
=
{
mode:
PC110PAD_PS2
,
bounce_interval:
50
MS
,
tap_interval:
200
MS
,
irq:
10
,
io:
0x15E0
,
};
static
struct
pc110pad_params
current_params
;
/* driver/filesystem interface management */
static
wait_queue_head_t
queue
;
static
struct
fasync_struct
*
asyncptr
;
static
int
active_count
=
0
;
/* number of concurrent open()s */
static
spinlock_t
pc110_lock
=
SPIN_LOCK_UNLOCKED
;
/* this lock should be held when referencing active_count */
static
struct
semaphore
reader_lock
;
/**
* wake_readers:
*
* Take care of letting any waiting processes know that
* now would be a good time to do a read(). Called
* whenever a state transition occurs, real or synthetic. Also
* issue any SIGIO's to programs that use SIGIO on mice (eg
* Executor)
*/
static
void
wake_readers
(
void
)
{
wake_up_interruptible
(
&
queue
);
kill_fasync
(
&
asyncptr
,
SIGIO
,
POLL_IN
);
}
/*****************************************************************************/
/*
* Deal with the messy business of synthesizing button tap and drag
* events.
*
* Exports:
* notify_pad_up_down()
* Must be called whenever debounced pad up/down state changes.
* button_pending
* Flag is set whenever read_button() has new values
* to return.
* read_button()
* Obtains the current synthetic mouse button state.
*/
/*
* These keep track of up/down transitions needed to generate the
* synthetic mouse button events. While recent_transition is set,
* up/down events cause transition_count to increment. tap_timer
* turns off the recent_transition flag and may cause some synthetic
* up/down mouse events to be created by incrementing synthesize_tap.
*/
static
int
button_pending
;
static
int
recent_transition
;
static
int
transition_count
;
static
int
synthesize_tap
;
static
void
tap_timeout
(
unsigned
long
data
);
static
struct
timer_list
tap_timer
=
{
function
:
tap_timeout
};
/**
* tap_timeout:
* @data: Unused
*
* This callback goes off a short time after an up/down transition;
* before it goes off, transitions will be considered part of a
* single PS/2 event and counted in transition_count. Once the
* timeout occurs the recent_transition flag is cleared and
* any synthetic mouse up/down events are generated.
*/
static
void
tap_timeout
(
unsigned
long
data
)
{
if
(
!
recent_transition
)
{
printk
(
KERN_ERR
"pc110pad: tap_timeout but no recent transition!
\n
"
);
}
if
(
transition_count
==
2
||
transition_count
==
4
||
transition_count
==
6
)
{
synthesize_tap
+=
transition_count
;
button_pending
=
1
;
wake_readers
();
}
recent_transition
=
0
;
}
/**
* notify_pad_up_down:
*
* Called by the raw pad read routines when a (debounced) up/down
* transition is detected.
*/
void
notify_pad_up_down
(
void
)
{
if
(
recent_transition
)
{
transition_count
++
;
}
else
{
transition_count
=
1
;
recent_transition
=
1
;
}
mod_timer
(
&
tap_timer
,
jiffies
+
current_params
.
tap_interval
);
/* changes to transition_count can cause reported button to change */
button_pending
=
1
;
wake_readers
();
}
/**
* read_button:
* @b: pointer to the button status.
*
* The actual button state depends on what we are seeing. We have to check
* for the tap gesture and also for dragging.
*/
static
void
read_button
(
int
*
b
)
{
if
(
synthesize_tap
)
{
*
b
=--
synthesize_tap
&
1
;
}
else
{
*
b
=
(
!
recent_transition
&&
transition_count
==
3
);
/* drag */
}
button_pending
=
(
synthesize_tap
>
0
);
}
/*****************************************************************************/
/*
* Read pad absolute co-ordinates and debounced up/down state.
*
* Exports:
* pad_irq()
* Function to be called whenever the pad signals
* that it has new data available.
* read_raw_pad()
* Returns the most current pad state.
* xy_pending
* Flag is set whenever read_raw_pad() has new values
* to return.
* Imports:
* wake_readers()
* Called when movement occurs.
* notify_pad_up_down()
* Called when debounced up/down status changes.
*/
/*
* These are up/down state and absolute co-ords read directly from pad
*/
static
int
raw_data
[
3
];
static
int
raw_data_count
;
static
int
raw_x
,
raw_y
;
/* most recent absolute co-ords read */
static
int
raw_down
;
/* raw up/down state */
static
int
debounced_down
;
/* up/down state after debounce processing */
static
enum
{
NO_BOUNCE
,
JUST_GONE_UP
,
JUST_GONE_DOWN
}
bounce
=
NO_BOUNCE
;
/* set just after an up/down transition */
static
int
xy_pending
;
/* set if new data have not yet been read */
/*
* Timer goes off a short while after an up/down transition and copies
* the value of raw_down to debounced_down.
*/
static
void
bounce_timeout
(
unsigned
long
data
);
static
struct
timer_list
bounce_timer
=
{
function
:
bounce_timeout
};
/**
* bounce_timeout:
* @data: Unused
*
* No further up/down transitions happened within the
* bounce period, so treat this as a genuine transition.
*/
static
void
bounce_timeout
(
unsigned
long
data
)
{
switch
(
bounce
)
{
case
NO_BOUNCE
:
{
/*
* Strange; the timer callback should only go off if
* we were expecting to do bounce processing!
*/
printk
(
KERN_WARNING
"pc110pad, bounce_timeout: bounce flag not set!
\n
"
);
break
;
}
case
JUST_GONE_UP
:
{
/*
* The last up we spotted really was an up, so set
* debounced state the same as raw state.
*/
bounce
=
NO_BOUNCE
;
if
(
debounced_down
==
raw_down
)
{
printk
(
KERN_WARNING
"pc110pad, bounce_timeout: raw already debounced!
\n
"
);
}
debounced_down
=
raw_down
;
notify_pad_up_down
();
break
;
}
case
JUST_GONE_DOWN
:
{
/*
* We don't debounce down events, but we still time
* out soon after one occurs so we can avoid the (x,y)
* skittering that sometimes happens.
*/
bounce
=
NO_BOUNCE
;
break
;
}
}
}
/**
* pad_irq:
* @irq: Interrupt number
* @ptr: Unused
* @regs: Unused
*
* Callback when pad's irq goes off; copies values in to raw_* globals;
* initiates debounce processing. This isn't SMP safe however there are
* no SMP machines with a PC110 touchpad on them.
*/
static
void
pad_irq
(
int
irq
,
void
*
ptr
,
struct
pt_regs
*
regs
)
{
/* Obtain byte from pad and prime for next byte */
{
int
value
=
inb_p
(
current_params
.
io
);
int
handshake
=
inb_p
(
current_params
.
io
+
2
);
outb_p
(
handshake
|
1
,
current_params
.
io
+
2
);
outb_p
(
handshake
&~
1
,
current_params
.
io
+
2
);
inb_p
(
0x64
);
raw_data
[
raw_data_count
++
]
=
value
;
}
if
(
raw_data_count
==
3
)
{
int
new_down
=
raw_data
[
0
]
&
0x01
;
int
new_x
=
raw_data
[
1
];
int
new_y
=
raw_data
[
2
];
if
(
raw_data
[
0
]
&
0x10
)
new_x
+=
128
;
if
(
raw_data
[
0
]
&
0x80
)
new_x
+=
256
;
if
(
raw_data
[
0
]
&
0x08
)
new_y
+=
128
;
if
(
(
raw_x
!=
new_x
)
||
(
raw_y
!=
new_y
)
)
{
raw_x
=
new_x
;
raw_y
=
new_y
;
xy_pending
=
1
;
}
if
(
new_down
!=
raw_down
)
{
/* Down state has changed. raw_down always holds
* the most recently observed state.
*/
raw_down
=
new_down
;
/* Forget any earlier bounce processing */
if
(
bounce
)
{
del_timer
(
&
bounce_timer
);
bounce
=
NO_BOUNCE
;
}
if
(
new_down
)
{
if
(
debounced_down
)
{
/* pad gone down, but we were reporting
* it down anyway because we suspected
* (correctly) that the last up was just
* a bounce
*/
}
else
{
bounce
=
JUST_GONE_DOWN
;
mod_timer
(
&
bounce_timer
,
jiffies
+
current_params
.
bounce_interval
);
/* start new stroke/tap */
debounced_down
=
new_down
;
notify_pad_up_down
();
}
}
else
/* just gone up */
{
if
(
recent_transition
)
{
/* early bounces are probably part of
* a multi-tap gesture, so process
* immediately
*/
debounced_down
=
new_down
;
notify_pad_up_down
();
}
else
{
/* don't trust it yet */
bounce
=
JUST_GONE_UP
;
mod_timer
(
&
bounce_timer
,
jiffies
+
current_params
.
bounce_interval
);
}
}
}
wake_readers
();
raw_data_count
=
0
;
}
}
/**
* read_raw_pad:
* @down: set if the pen is down
* @debounced: set if the debounced pen position is down
* @x: X position
* @y: Y position
*
* Retrieve the data saved by the interrupt handler and indicate we
* have no more pending XY to do.
*
* FIXME: We should switch to a spinlock for this.
*/
static
void
read_raw_pad
(
int
*
down
,
int
*
debounced
,
int
*
x
,
int
*
y
)
{
disable_irq
(
current_params
.
irq
);
{
*
down
=
raw_down
;
*
debounced
=
debounced_down
;
*
x
=
raw_x
;
*
y
=
raw_y
;
xy_pending
=
0
;
}
enable_irq
(
current_params
.
irq
);
}
/*****************************************************************************/
/*
* Filesystem interface
*/
/*
* Read returns byte triples, so we need to keep track of
* how much of a triple has been read. This is shared across
* all processes which have this device open---not that anything
* will make much sense in that case.
*/
static
int
read_bytes
[
3
];
static
int
read_byte_count
;
/**
* sample_raw:
* @d: sample buffer
*
* Retrieve a triple of sample data.
*/
static
void
sample_raw
(
int
d
[
3
])
{
d
[
0
]
=
raw_data
[
0
];
d
[
1
]
=
raw_data
[
1
];
d
[
2
]
=
raw_data
[
2
];
}
/**
* sample_rare:
* @d: sample buffer
*
* Retrieve a triple of sample data and sanitize it. We do the needed
* scaling and masking to get the current status.
*/
static
void
sample_rare
(
int
d
[
3
])
{
int
thisd
,
thisdd
,
thisx
,
thisy
;
read_raw_pad
(
&
thisd
,
&
thisdd
,
&
thisx
,
&
thisy
);
d
[
0
]
=
(
thisd
?
0x80
:
0
)
|
(
thisx
/
256
)
<<
4
|
(
thisdd
?
0x08
:
0
)
|
(
thisy
/
256
)
;
d
[
1
]
=
thisx
%
256
;
d
[
2
]
=
thisy
%
256
;
}
/**
* sample_debug:
* @d: sample buffer
*
* Retrieve a triple of sample data and mix it up with the state
* information in the gesture parser. Not useful for normal users but
* handy when debugging
*/
static
void
sample_debug
(
int
d
[
3
])
{
int
thisd
,
thisdd
,
thisx
,
thisy
;
int
b
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
pc110_lock
,
flags
);
read_raw_pad
(
&
thisd
,
&
thisdd
,
&
thisx
,
&
thisy
);
d
[
0
]
=
(
thisd
?
0x80
:
0
)
|
(
thisdd
?
0x40
:
0
)
|
bounce
;
d
[
1
]
=
(
recent_transition
?
0x80
:
0
)
+
transition_count
;
read_button
(
&
b
);
d
[
2
]
=
(
synthesize_tap
<<
4
)
|
(
b
?
0x01
:
0
);
spin_unlock_irqrestore
(
&
pc110_lock
,
flags
);
}
/**
* sample_ps2:
* @d: sample buffer
*
* Retrieve a triple of sample data and turn the debounced tap and
* stroke information into what appears to be a PS/2 mouse. This means
* the PC110 pad needs no funny application side support.
*/
static
void
sample_ps2
(
int
d
[
3
])
{
static
int
lastx
,
lasty
,
lastd
;
int
thisd
,
thisdd
,
thisx
,
thisy
;
int
dx
,
dy
,
b
;
/*
* Obtain the current mouse parameters and limit as appropriate for
* the return data format. Interrupts are only disabled while
* obtaining the parameters, NOT during the puts_fs_byte() calls,
* so paging in put_user() does not affect mouse tracking.
*/
read_raw_pad
(
&
thisd
,
&
thisdd
,
&
thisx
,
&
thisy
);
read_button
(
&
b
);
/* Now compare with previous readings. Note that we use the
* raw down flag rather than the debounced one.
*/
if
(
(
thisd
&&
!
lastd
)
/* new stroke */
||
(
bounce
!=
NO_BOUNCE
)
)
{
dx
=
0
;
dy
=
0
;
}
else
{
dx
=
(
thisx
-
lastx
);
dy
=
-
(
thisy
-
lasty
);
}
lastx
=
thisx
;
lasty
=
thisy
;
lastd
=
thisd
;
/*
d[0]= ((dy<0)?0x20:0)
| ((dx<0)?0x10:0)
| 0x08
| (b? 0x01:0x00)
;
*/
d
[
0
]
=
((
dy
<
0
)
?
0x20
:
0
)
|
((
dx
<
0
)
?
0x10
:
0
)
|
(
b
?
0x00
:
0x08
)
;
d
[
1
]
=
dx
;
d
[
2
]
=
dy
;
}
/**
* fasync_pad:
* @fd: file number for the file
* @filp: file handle
* @on: 1 to add, 0 to remove a notifier
*
* Update the queue of asynchronous event notifiers. We can use the
* same helper the mice do and that does almost everything we need.
*/
static
int
fasync_pad
(
int
fd
,
struct
file
*
filp
,
int
on
)
{
int
retval
;
retval
=
fasync_helper
(
fd
,
filp
,
on
,
&
asyncptr
);
if
(
retval
<
0
)
return
retval
;
return
0
;
}
/**
* close_pad:
* @inode: inode of pad
* @file: file handle to pad
*
* Close access to the pad. We turn the pad power off if this is the
* last user of the pad. I've not actually measured the power draw but
* the DOS driver is careful to do this so we follow suit.
*/
static
int
close_pad
(
struct
inode
*
inode
,
struct
file
*
file
)
{
unsigned
long
flags
;
fasync_pad
(
-
1
,
file
,
0
);
spin_lock_irqsave
(
&
pc110_lock
,
flags
);
if
(
!--
active_count
)
outb
(
0x30
,
current_params
.
io
+
2
);
/* switch off digitiser */
spin_unlock_irqrestore
(
&
pc110_lock
,
flags
);
return
0
;
}
/**
* open_pad:
* @inode: inode of pad
* @file: file handle to pad
*
* Open access to the pad. We turn the pad off first (we turned it off
* on close but if this is the first open after a crash the state is
* indeterminate). The device has a small fifo so we empty that before
* we kick it back into action.
*/
static
int
open_pad
(
struct
inode
*
inode
,
struct
file
*
file
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
pc110_lock
,
flags
);
if
(
active_count
++
)
{
spin_unlock_irqrestore
(
&
pc110_lock
,
flags
);
return
0
;
}
outb
(
0x30
,
current_params
.
io
+
2
);
/* switch off digitiser */
pad_irq
(
0
,
0
,
0
);
/* read to flush any pending bytes */
pad_irq
(
0
,
0
,
0
);
/* read to flush any pending bytes */
pad_irq
(
0
,
0
,
0
);
/* read to flush any pending bytes */
outb
(
0x38
,
current_params
.
io
+
2
);
/* switch on digitiser */
current_params
=
default_params
;
raw_data_count
=
0
;
/* re-sync input byte counter */
read_byte_count
=
0
;
/* re-sync output byte counter */
button_pending
=
0
;
recent_transition
=
0
;
transition_count
=
0
;
synthesize_tap
=
0
;
del_timer
(
&
bounce_timer
);
del_timer
(
&
tap_timer
);
spin_unlock_irqrestore
(
&
pc110_lock
,
flags
);
return
0
;
}
/**
* write_pad:
* @file: File handle to the pad
* @buffer: Unused
* @count: Unused
* @ppos: Unused
*
* Writes are disallowed. A true PS/2 mouse lets you write stuff. Everyone
* seems happy with this and not faking the write modes.
*/
static
ssize_t
write_pad
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
return
-
EINVAL
;
}
/*
* new_sample:
* @d: sample buffer
*
* Fetch a new sample according the current mouse mode the pad is
* using.
*/
void
new_sample
(
int
d
[
3
])
{
switch
(
current_params
.
mode
)
{
case
PC110PAD_RAW
:
sample_raw
(
d
);
break
;
case
PC110PAD_RARE
:
sample_rare
(
d
);
break
;
case
PC110PAD_DEBUG
:
sample_debug
(
d
);
break
;
case
PC110PAD_PS2
:
sample_ps2
(
d
);
break
;
}
}
/**
* read_pad:
* @file: File handle to pad
* @buffer: Target for the mouse data
* @count: Buffer length
* @ppos: Offset (unused)
*
* Read data from the pad. We use the reader_lock to avoid mess when there are
* two readers. This shouldnt be happening anyway but we play safe.
*/
static
ssize_t
read_pad
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
int
r
;
down
(
&
reader_lock
);
for
(
r
=
0
;
r
<
count
;
r
++
)
{
if
(
!
read_byte_count
)
new_sample
(
read_bytes
);
if
(
put_user
(
read_bytes
[
read_byte_count
],
buffer
+
r
))
{
r
=
-
EFAULT
;
break
;
}
read_byte_count
=
(
read_byte_count
+
1
)
%
3
;
}
up
(
&
reader_lock
);
return
r
;
}
/**
* pad_poll:
* @file: File of the pad device
* @wait: Poll table
*
* The pad is ready to read if there is a button or any position change
* pending in the queue. The reading and interrupt routines maintain the
* required state for us and do needed wakeups.
*/
static
unsigned
int
pad_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
poll_wait
(
file
,
&
queue
,
wait
);
if
(
button_pending
||
xy_pending
)
return
POLLIN
|
POLLRDNORM
;
return
0
;
}
/**
* pad_ioctl;
* @inode: Inode of the pad
* @file: File handle to the pad
* @cmd: Ioctl command
* @arg: Argument pointer
*
* The PC110 pad supports two ioctls both of which use the pc110pad_params
* structure. GETP queries the current pad status. SETP changes the pad
* configuration. Changing configuration during normal mouse operations
* may give momentarily odd results as things like tap gesture state
* may be lost.
*/
static
int
pad_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
pc110pad_params
new
;
if
(
!
inode
)
return
-
EINVAL
;
switch
(
cmd
)
{
case
PC110PADIOCGETP
:
new
=
current_params
;
if
(
copy_to_user
((
void
*
)
arg
,
&
new
,
sizeof
(
new
)))
return
-
EFAULT
;
return
0
;
case
PC110PADIOCSETP
:
if
(
copy_from_user
(
&
new
,
(
void
*
)
arg
,
sizeof
(
new
)))
return
-
EFAULT
;
if
(
(
new
.
mode
<
PC110PAD_RAW
)
||
(
new
.
mode
>
PC110PAD_PS2
)
||
(
new
.
bounce_interval
<
0
)
||
(
new
.
tap_interval
<
0
)
)
return
-
EINVAL
;
current_params
.
mode
=
new
.
mode
;
current_params
.
bounce_interval
=
new
.
bounce_interval
;
current_params
.
tap_interval
=
new
.
tap_interval
;
return
0
;
}
return
-
ENOTTY
;
}
static
struct
file_operations
pad_fops
=
{
owner:
THIS_MODULE
,
read:
read_pad
,
write:
write_pad
,
poll:
pad_poll
,
ioctl:
pad_ioctl
,
open:
open_pad
,
release:
close_pad
,
fasync:
fasync_pad
,
};
static
struct
miscdevice
pc110_pad
=
{
minor:
PC110PAD_MINOR
,
name:
"pc110 pad"
,
fops:
&
pad_fops
,
};
/**
* pc110pad_init_driver:
*
* We configure the pad with the default parameters (that is PS/2
* emulation mode. We then claim the needed I/O and interrupt resources.
* Finally as a matter of paranoia we turn the pad off until we are
* asked to open it by an application.
*/
static
char
banner
[]
__initdata
=
KERN_INFO
"PC110 digitizer pad at 0x%X, irq %d.
\n
"
;
static
int
__init
pc110pad_init_driver
(
void
)
{
init_MUTEX
(
&
reader_lock
);
current_params
=
default_params
;
if
(
request_irq
(
current_params
.
irq
,
pad_irq
,
0
,
"pc110pad"
,
0
))
{
printk
(
KERN_ERR
"pc110pad: Unable to get IRQ.
\n
"
);
return
-
EBUSY
;
}
if
(
!
request_region
(
current_params
.
io
,
4
,
"pc110pad"
))
{
printk
(
KERN_ERR
"pc110pad: I/O area in use.
\n
"
);
free_irq
(
current_params
.
irq
,
0
);
return
-
EBUSY
;
}
init_waitqueue_head
(
&
queue
);
printk
(
banner
,
current_params
.
io
,
current_params
.
irq
);
misc_register
(
&
pc110_pad
);
outb
(
0x30
,
current_params
.
io
+
2
);
/* switch off digitiser */
return
0
;
}
/*
* pc110pad_exit_driver:
*
* Free the resources we acquired when the module was loaded. We also
* turn the pad off to be sure we don't leave it using power.
*/
static
void
__exit
pc110pad_exit_driver
(
void
)
{
outb
(
0x30
,
current_params
.
io
+
2
);
/* switch off digitiser */
if
(
current_params
.
irq
)
free_irq
(
current_params
.
irq
,
0
);
current_params
.
irq
=
0
;
release_region
(
current_params
.
io
,
4
);
misc_deregister
(
&
pc110_pad
);
}
module_init
(
pc110pad_init_driver
);
module_exit
(
pc110pad_exit_driver
);
MODULE_AUTHOR
(
"Alan Cox, Robin O'Leary"
);
MODULE_DESCRIPTION
(
"Driver for the touchpad on the IBM PC110 palmtop"
);
MODULE_LICENSE
(
"GPL"
);
drivers/char/pc110pad.h
deleted
100644 → 0
View file @
a49e82a5
#ifndef _PC110PAD_H
#define _PC110PAD_H
#include <linux/ioctl.h>
enum
pc110pad_mode
{
PC110PAD_RAW
,
/* bytes as they come out of the hardware */
PC110PAD_RARE
,
/* debounced up/down and absolute x,y */
PC110PAD_DEBUG
,
/* up/down, debounced, transitions, button */
PC110PAD_PS2
,
/* ps2 relative (default) */
};
struct
pc110pad_params
{
enum
pc110pad_mode
mode
;
int
bounce_interval
;
int
tap_interval
;
int
irq
;
int
io
;
};
#define MS *HZ/1000
/* Appears as device major=10 (MISC), minor=PC110_PAD */
#define PC110PAD_IOCTL_TYPE 0x9a
#define PC110PADIOCGETP _IOR(PC110PAD_IOCTL_TYPE, 0, struct pc110pad_params)
#define PC110PADIOCSETP _IOW(PC110PAD_IOCTL_TYPE, 1, struct pc110pad_params)
#endif
/* _PC110PAD_H */
drivers/char/qpmouse.c
deleted
100644 → 0
View file @
a49e82a5
/*
* linux/drivers/char/qpmouse.c
*
* Driver for a 82C710 C&T mouse interface chip.
*
* Based on the PS/2 driver by Johan Myreen.
*
* Corrections in device setup for some laptop mice & trackballs.
* 02Feb93 (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
*
* Modified by Johan Myreen (jem@iki.fi) 04Aug93
* to include support for QuickPort mouse.
*
* Changed references to "QuickPort" with "82C710" since "QuickPort"
* is not what this driver is all about -- QuickPort is just a
* connector type, and this driver is for the mouse port on the Chips
* & Technologies 82C710 interface chip. 15Nov93 jem@iki.fi
*
* Added support for SIGIO. 28Jul95 jem@iki.fi
*
* Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com
*
* Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/semaphore.h>
#include <linux/pc_keyb.h>
/* mouse enable command.. */
/*
* We use the same minor number as the PS/2 mouse for (bad) historical
* reasons..
*/
#define PSMOUSE_MINOR 1
/* Minor device # for this mouse */
#define QP_BUF_SIZE 2048
struct
qp_queue
{
unsigned
long
head
;
unsigned
long
tail
;
wait_queue_head_t
proc_list
;
struct
fasync_struct
*
fasync
;
unsigned
char
buf
[
QP_BUF_SIZE
];
};
static
struct
qp_queue
*
queue
;
static
unsigned
int
get_from_queue
(
void
)
{
unsigned
int
result
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
result
=
queue
->
buf
[
queue
->
tail
];
queue
->
tail
=
(
queue
->
tail
+
1
)
&
(
QP_BUF_SIZE
-
1
);
restore_flags
(
flags
);
return
result
;
}
static
inline
int
queue_empty
(
void
)
{
return
queue
->
head
==
queue
->
tail
;
}
static
int
fasync_qp
(
int
fd
,
struct
file
*
filp
,
int
on
)
{
int
retval
;
retval
=
fasync_helper
(
fd
,
filp
,
on
,
&
queue
->
fasync
);
if
(
retval
<
0
)
return
retval
;
return
0
;
}
/*
* 82C710 Interface
*/
#define QP_DATA 0x310
/* Data Port I/O Address */
#define QP_STATUS 0x311
/* Status Port I/O Address */
#define QP_DEV_IDLE 0x01
/* Device Idle */
#define QP_RX_FULL 0x02
/* Device Char received */
#define QP_TX_IDLE 0x04
/* Device XMIT Idle */
#define QP_RESET 0x08
/* Device Reset */
#define QP_INTS_ON 0x10
/* Device Interrupt On */
#define QP_ERROR_FLAG 0x20
/* Device Error */
#define QP_CLEAR 0x40
/* Device Clear */
#define QP_ENABLE 0x80
/* Device Enable */
#define QP_IRQ 12
static
int
qp_present
;
static
int
qp_count
;
static
spinlock_t
qp_count_lock
=
SPIN_LOCK_UNLOCKED
;
static
int
qp_data
=
QP_DATA
;
static
int
qp_status
=
QP_STATUS
;
static
int
poll_qp_status
(
void
);
static
int
probe_qp
(
void
);
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static
void
qp_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
int
head
=
queue
->
head
;
int
maxhead
=
(
queue
->
tail
-
1
)
&
(
QP_BUF_SIZE
-
1
);
add_mouse_randomness
(
queue
->
buf
[
head
]
=
inb
(
qp_data
));
if
(
head
!=
maxhead
)
{
head
++
;
head
&=
QP_BUF_SIZE
-
1
;
}
queue
->
head
=
head
;
kill_fasync
(
&
queue
->
fasync
,
SIGIO
,
POLL_IN
);
wake_up_interruptible
(
&
queue
->
proc_list
);
}
static
int
release_qp
(
struct
inode
*
inode
,
struct
file
*
file
)
{
unsigned
char
status
;
fasync_qp
(
-
1
,
file
,
0
);
spin_lock
(
&
qp_count_lock
);
if
(
!--
qp_count
)
{
if
(
!
poll_qp_status
())
printk
(
KERN_WARNING
"Warning: Mouse device busy in release_qp()
\n
"
);
status
=
inb_p
(
qp_status
);
outb_p
(
status
&
~
(
QP_ENABLE
|
QP_INTS_ON
),
qp_status
);
if
(
!
poll_qp_status
())
printk
(
KERN_WARNING
"Warning: Mouse device busy in release_qp()
\n
"
);
free_irq
(
QP_IRQ
,
NULL
);
}
spin_unlock
(
&
qp_count_lock
);
return
0
;
}
/*
* Install interrupt handler.
* Enable the device, enable interrupts.
*/
static
int
open_qp
(
struct
inode
*
inode
,
struct
file
*
file
)
{
unsigned
char
status
;
if
(
!
qp_present
)
return
-
EINVAL
;
spin_lock
(
&
qp_count_lock
);
if
(
qp_count
++
)
{
spin_unlock
(
&
qp_count_lock
);
return
0
;
}
spin_unlock
(
&
qp_count_lock
);
if
(
request_irq
(
QP_IRQ
,
qp_interrupt
,
0
,
"PS/2 Mouse"
,
NULL
))
{
qp_count
--
;
return
-
EBUSY
;
}
status
=
inb_p
(
qp_status
);
status
|=
(
QP_ENABLE
|
QP_RESET
);
outb_p
(
status
,
qp_status
);
status
&=
~
(
QP_RESET
);
outb_p
(
status
,
qp_status
);
queue
->
head
=
queue
->
tail
=
0
;
/* Flush input queue */
status
|=
QP_INTS_ON
;
outb_p
(
status
,
qp_status
);
/* Enable interrupts */
while
(
!
poll_qp_status
())
{
printk
(
KERN_ERR
"Error: Mouse device busy in open_qp()
\n
"
);
qp_count
--
;
status
&=
~
(
QP_ENABLE
|
QP_INTS_ON
);
outb_p
(
status
,
qp_status
);
free_irq
(
QP_IRQ
,
NULL
);
return
-
EBUSY
;
}
outb_p
(
AUX_ENABLE_DEV
,
qp_data
);
/* Wake up mouse */
return
0
;
}
/*
* Write to the 82C710 mouse device.
*/
static
ssize_t
write_qp
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
ssize_t
i
=
count
;
while
(
i
--
)
{
char
c
;
if
(
!
poll_qp_status
())
return
-
EIO
;
get_user
(
c
,
buffer
++
);
outb_p
(
c
,
qp_data
);
}
file
->
f_dentry
->
d_inode
->
i_mtime
=
CURRENT_TIME
;
return
count
;
}
static
unsigned
int
poll_qp
(
struct
file
*
file
,
poll_table
*
wait
)
{
poll_wait
(
file
,
&
queue
->
proc_list
,
wait
);
if
(
!
queue_empty
())
return
POLLIN
|
POLLRDNORM
;
return
0
;
}
/*
* Wait for device to send output char and flush any input char.
*/
#define MAX_RETRIES (60)
static
int
poll_qp_status
(
void
)
{
int
retries
=
0
;
while
((
inb
(
qp_status
)
&
(
QP_RX_FULL
|
QP_TX_IDLE
|
QP_DEV_IDLE
))
!=
(
QP_DEV_IDLE
|
QP_TX_IDLE
)
&&
retries
<
MAX_RETRIES
)
{
if
(
inb_p
(
qp_status
)
&
(
QP_RX_FULL
))
inb_p
(
qp_data
);
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
((
5
*
HZ
+
99
)
/
100
);
retries
++
;
}
return
!
(
retries
==
MAX_RETRIES
);
}
/*
* Put bytes from input queue to buffer.
*/
static
ssize_t
read_qp
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
ssize_t
i
=
count
;
unsigned
char
c
;
if
(
queue_empty
())
{
if
(
file
->
f_flags
&
O_NONBLOCK
)
return
-
EAGAIN
;
add_wait_queue
(
&
queue
->
proc_list
,
&
wait
);
repeat:
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
queue_empty
()
&&
!
signal_pending
(
current
))
{
schedule
();
goto
repeat
;
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
queue
->
proc_list
,
&
wait
);
}
while
(
i
>
0
&&
!
queue_empty
())
{
c
=
get_from_queue
();
put_user
(
c
,
buffer
++
);
i
--
;
}
if
(
count
-
i
)
{
file
->
f_dentry
->
d_inode
->
i_atime
=
CURRENT_TIME
;
return
count
-
i
;
}
if
(
signal_pending
(
current
))
return
-
ERESTARTSYS
;
return
0
;
}
struct
file_operations
qp_fops
=
{
owner:
THIS_MODULE
,
read:
read_qp
,
write:
write_qp
,
poll:
poll_qp
,
open:
open_qp
,
release:
release_qp
,
fasync:
fasync_qp
,
};
/*
* Initialize driver.
*/
static
struct
miscdevice
qp_mouse
=
{
minor:
PSMOUSE_MINOR
,
name:
"QPmouse"
,
fops:
&
qp_fops
,
};
/*
* Function to read register in 82C710.
*/
static
inline
unsigned
char
read_710
(
unsigned
char
index
)
{
outb_p
(
index
,
0x390
);
/* Write index */
return
inb_p
(
0x391
);
/* Read the data */
}
/*
* See if we can find a 82C710 device. Read mouse address.
*/
static
int
__init
probe_qp
(
void
)
{
outb_p
(
0x55
,
0x2fa
);
/* Any value except 9, ff or 36 */
outb_p
(
0xaa
,
0x3fa
);
/* Inverse of 55 */
outb_p
(
0x36
,
0x3fa
);
/* Address the chip */
outb_p
(
0xe4
,
0x3fa
);
/* 390/4; 390 = config address */
outb_p
(
0x1b
,
0x2fa
);
/* Inverse of e4 */
if
(
read_710
(
0x0f
)
!=
0xe4
)
/* Config address found? */
return
0
;
/* No: no 82C710 here */
qp_data
=
read_710
(
0x0d
)
*
4
;
/* Get mouse I/O address */
qp_status
=
qp_data
+
1
;
outb_p
(
0x0f
,
0x390
);
outb_p
(
0x0f
,
0x391
);
/* Close config mode */
return
1
;
}
static
char
msg_banner
[]
__initdata
=
KERN_INFO
"82C710 type pointing device detected -- driver installed.
\n
"
;
static
char
msg_nomem
[]
__initdata
=
KERN_ERR
"qpmouse: no queue memory.
\n
"
;
static
int
__init
qpmouse_init_driver
(
void
)
{
if
(
!
probe_qp
())
return
-
EIO
;
printk
(
msg_banner
);
/* printk("82C710 address = %x (should be 0x310)\n", qp_data); */
queue
=
(
struct
qp_queue
*
)
kmalloc
(
sizeof
(
*
queue
),
GFP_KERNEL
);
if
(
queue
==
NULL
)
{
printk
(
msg_nomem
);
return
-
ENOMEM
;
}
qp_present
=
1
;
misc_register
(
&
qp_mouse
);
memset
(
queue
,
0
,
sizeof
(
*
queue
));
queue
->
head
=
queue
->
tail
=
0
;
init_waitqueue_head
(
&
queue
->
proc_list
);
return
0
;
}
static
void
__exit
qpmouse_exit_driver
(
void
)
{
misc_deregister
(
&
qp_mouse
);
kfree
(
queue
);
}
module_init
(
qpmouse_init_driver
);
module_exit
(
qpmouse_exit_driver
);
MODULE_LICENSE
(
"GPL"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment