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

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)