patch-2.3.43 linux/drivers/char/pc110pad.c
Next file: linux/drivers/char/pc_keyb.c
Previous file: linux/drivers/char/nvram.c
Back to the patch index
Back to the overall index
- Lines: 458
- Date:
Thu Feb 10 12:29:58 2000
- Orig file:
v2.3.42/linux/drivers/char/pc110pad.c
- Orig date:
Fri Jan 7 19:13:21 2000
diff -u --recursive --new-file v2.3.42/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
@@ -1,5 +1,9 @@
/*
* 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
@@ -7,13 +11,24 @@
* 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.
+ * 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>
@@ -56,7 +71,9 @@
static struct semaphore reader_lock;
/*
- * Utility to reset a timer to go off some time in the future.
+ * set_timer_callback:
+ *
+ * Utility to reset a timer to go off some time in the future.
*/
static void set_timer_callback(struct timer_list *timer, int ticks)
@@ -67,10 +84,14 @@
}
-/*
- * 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.
+/**
+ * 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)
@@ -112,7 +133,10 @@
static struct timer_list tap_timer = { NULL, NULL, 0, 0, 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
@@ -136,7 +160,9 @@
}
-/*
+/**
+ * notify_pad_up_down:
+ *
* Called by the raw pad read routines when a (debounced) up/down
* transition is detected.
*/
@@ -159,6 +185,13 @@
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)
{
@@ -216,12 +249,17 @@
static struct timer_list bounce_timer = { NULL, NULL, 0, 0, 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)
{
- /*
- * No further up/down transitions happened within the
- * bounce period, so treat this as a genuine transition.
- */
switch(bounce)
{
case NO_BOUNCE:
@@ -230,7 +268,7 @@
* Strange; the timer callback should only go off if
* we were expecting to do bounce processing!
*/
- printk("pc110pad, bounce_timeout: bounce flag not set!\n");
+ printk(KERN_WARNING "pc110pad, bounce_timeout: bounce flag not set!\n");
break;
}
case JUST_GONE_UP:
@@ -242,7 +280,7 @@
bounce=NO_BOUNCE;
if(debounced_down==raw_down)
{
- printk("pc110pad, bounce_timeout: raw already debounced!\n");
+ printk(KERN_WARNING "pc110pad, bounce_timeout: raw already debounced!\n");
}
debounced_down=raw_down;
@@ -263,10 +301,17 @@
}
-/*
+/**
+ * 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.
+ * 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)
{
@@ -356,6 +401,18 @@
}
}
+/**
+ * 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)
{
@@ -384,6 +441,12 @@
static int read_bytes[3];
static int read_byte_count=0;
+/**
+ * sample_raw:
+ * @d: sample buffer
+ *
+ * Retrieve a triple of sample data.
+ */
static void sample_raw(int d[3])
@@ -393,6 +456,14 @@
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])
{
@@ -409,20 +480,40 @@
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;
+
+ save_flags(flags);
cli();
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);
- sti();
+ restore_flags(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])
{
@@ -474,7 +565,16 @@
}
-
+/**
+ * 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;
@@ -486,9 +586,16 @@
}
-/*
- * close access to the pad
+/**
+ * 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)
{
fasync_pad(-1, file, 0);
@@ -500,9 +607,17 @@
}
-/*
- * open access to the pad
+/**
+ * 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;
@@ -533,15 +648,31 @@
}
-/*
- * writes are disallowed
+/**
+ * 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)
@@ -554,9 +685,17 @@
}
-/*
- * Read pad data. Currently never blocks.
+/**
+ * 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;
@@ -578,8 +717,14 @@
}
-/*
- * select for pad input
+/**
+ * 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)
@@ -591,6 +736,20 @@
}
+/**
+ * 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)
{
@@ -627,19 +786,13 @@
static struct file_operations pad_fops = {
- NULL, /* pad_seek */
- read_pad,
- write_pad,
- NULL, /* pad_readdir */
- pad_poll,
- pad_ioctl,
- NULL, /* pad_mmap */
- open_pad,
- NULL, /* flush */
- close_pad,
- NULL, /* fsync */
- fasync_pad,
- NULL /* lock */
+ read: read_pad,
+ write: write_pad,
+ poll: pad_poll,
+ ioctl: pad_ioctl,
+ open: open_pad,
+ release: close_pad,
+ fasync: fasync_pad,
};
@@ -648,6 +801,15 @@
};
+/**
+ * pc110pad_init:
+ *
+ * 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.
+ */
+
int pc110pad_init(void)
{
current_params = default_params;
@@ -675,6 +837,13 @@
#ifdef MODULE
+/**
+ * pc110pad_unload:
+ *
+ * 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 pc110pad_unload(void)
{
outb(0x30, current_params.io+2); /* switch off digitiser */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)