2 * Linux driver for the PC110 pad
4 * The pad provides triples of data. The first byte has
5 * 0x80=bit 8 X, 0x01=bit 7 X, 0x08=bit 8 Y, 0x01=still down
6 * The second byte is bits 0-6 X
7 * The third is bits 0-6 Y
9 * This is read internally and used to synthesize a stream of
10 * triples in the form expected from a PS/2 device.
12 * 0.0 1997-05-16 Alan Cox <alan@cymru.net> - Pad reader
13 * 0.1 1997-05-19 Robin O'Leary <robin@acm.org> - PS/2 emulation
14 * 0.2 1997-06-03 Robin O'Leary <robin@acm.org> - tap gesture
15 * 0.3 1997-06-27 Alan Cox <alan@cymru.net> - 2.1 commit
16 * 0.4 1997-11-09 Alan Cox <alan@cymru.net> - Single Unix VFS API changes
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/busmouse.h>
22 #include <linux/signal.h>
23 #include <linux/errno.h>
25 #include <linux/miscdevice.h>
26 #include <linux/ptrace.h>
27 #include <linux/poll.h>
28 #include <linux/ioport.h>
29 #include <linux/interrupt.h>
31 #include <asm/signal.h>
34 #include <asm/uaccess.h>
39 static struct pc110pad_params default_params
= {
40 PC110PAD_PS2
, /* read mode */
41 50 MS
, /* bounce interval */
42 200 MS
, /* tap interval */
44 0x15E0, /* I/O port */
48 static struct pc110pad_params current_params
;
51 /* driver/filesystem interface management */
52 static struct wait_queue
*queue
;
53 static struct fasync_struct
*asyncptr
;
54 static int active
=0; /* number of concurrent open()s */
58 * Utility to reset a timer to go off some time in the future.
61 static void set_timer_callback(struct timer_list
*timer
, int ticks
)
64 timer
->expires
= jiffies
+ticks
;
70 * Take care of letting any waiting processes know that
71 * now would be a good time to do a read(). Called
72 * whenever a state transition occurs, real or synthetic.
75 static void wake_readers(void)
77 wake_up_interruptible(&queue
);
79 kill_fasync(asyncptr
, SIGIO
);
83 /*****************************************************************************/
85 * Deal with the messy business of synthesizing button tap and drag
89 * notify_pad_up_down()
90 * Must be called whenever debounced pad up/down state changes.
92 * Flag is set whenever read_button() has new values
95 * Obtains the current synthetic mouse button state.
99 * These keep track of up/down transitions needed to generate the
100 * synthetic mouse button events. While recent_transition is set,
101 * up/down events cause transition_count to increment. tap_timer
102 * turns off the recent_transition flag and may cause some synthetic
103 * up/down mouse events to be created by incrementing synthesize_tap.
106 static int button_pending
=0;
107 static int recent_transition
=0;
108 static int transition_count
=0;
109 static int synthesize_tap
=0;
110 static void tap_timeout(unsigned long data
);
111 static struct timer_list tap_timer
= { NULL
, NULL
, 0, 0, tap_timeout
};
115 * This callback goes off a short time after an up/down transition;
116 * before it goes off, transitions will be considered part of a
117 * single PS/2 event and counted in transition_count. Once the
118 * timeout occurs the recent_transition flag is cleared and
119 * any synthetic mouse up/down events are generated.
122 static void tap_timeout(unsigned long data
)
124 if(!recent_transition
)
126 printk("pc110pad: tap_timeout but no recent transition!\n");
128 if( transition_count
==2 || transition_count
==4 || transition_count
==6 )
130 synthesize_tap
+=transition_count
;
139 * Called by the raw pad read routines when a (debounced) up/down
140 * transition is detected.
143 void notify_pad_up_down(void)
145 if(recent_transition
)
154 set_timer_callback(&tap_timer
, current_params
.tap_interval
);
156 /* changes to transition_count can cause reported button to change */
162 static void read_button(int *b
)
166 *b
=--synthesize_tap
& 1;
170 *b
=(!recent_transition
&& transition_count
==3); /* drag */
172 button_pending
=(synthesize_tap
>0);
176 /*****************************************************************************/
178 * Read pad absolute co-ordinates and debounced up/down state.
182 * Function to be called whenever the pad signals
183 * that it has new data available.
185 * Returns the most current pad state.
187 * Flag is set whenever read_raw_pad() has new values
191 * Called when movement occurs.
192 * notify_pad_up_down()
193 * Called when debounced up/down status changes.
197 * These are up/down state and absolute co-ords read directly from pad
200 static int raw_data
[3];
201 static int raw_data_count
=0;
202 static int raw_x
=0, raw_y
=0; /* most recent absolute co-ords read */
203 static int raw_down
=0; /* raw up/down state */
204 static int debounced_down
=0; /* up/down state after debounce processing */
205 static enum { NO_BOUNCE
, JUST_GONE_UP
, JUST_GONE_DOWN
} bounce
=NO_BOUNCE
;
206 /* set just after an up/down transition */
207 static int xy_pending
=0; /* set if new data have not yet been read */
210 * Timer goes off a short while after an up/down transition and copies
211 * the value of raw_down to debounced_down.
214 static void bounce_timeout(unsigned long data
);
215 static struct timer_list bounce_timer
= { NULL
, NULL
, 0, 0, bounce_timeout
};
218 static void bounce_timeout(unsigned long data
)
221 * No further up/down transitions happened within the
222 * bounce period, so treat this as a genuine transition.
229 * Strange; the timer callback should only go off if
230 * we were expecting to do bounce processing!
232 printk("pc110pad, bounce_timeout: bounce flag not set!\n");
238 * The last up we spotted really was an up, so set
239 * debounced state the same as raw state.
242 if(debounced_down
==raw_down
)
244 printk("pc110pad, bounce_timeout: raw already debounced!\n");
246 debounced_down
=raw_down
;
248 notify_pad_up_down();
254 * We don't debounce down events, but we still time
255 * out soon after one occurs so we can avoid the (x,y)
256 * skittering that sometimes happens.
266 * Callback when pad's irq goes off; copies values in to raw_* globals;
267 * initiates debounce processing.
269 static void pad_irq(int irq
, void *ptr
, struct pt_regs
*regs
)
272 /* Obtain byte from pad and prime for next byte */
274 int value
=inb_p(current_params
.io
);
275 int handshake
=inb_p(current_params
.io
+2);
276 outb_p(handshake
| 1, current_params
.io
+2);
277 outb_p(handshake
&~1, current_params
.io
+2);
280 raw_data
[raw_data_count
++]=value
;
283 if(raw_data_count
==3)
285 int new_down
=raw_data
[0]&0x01;
286 int new_x
=raw_data
[1];
287 int new_y
=raw_data
[2];
288 if(raw_data
[0]&0x10) new_x
+=128;
289 if(raw_data
[0]&0x80) new_x
+=256;
290 if(raw_data
[0]&0x08) new_y
+=128;
292 if( (raw_x
!=new_x
) || (raw_y
!=new_y
) )
299 if(new_down
!= raw_down
)
301 /* Down state has changed. raw_down always holds
302 * the most recently observed state.
306 /* Forget any earlier bounce processing */
309 del_timer(&bounce_timer
);
317 /* pad gone down, but we were reporting
318 * it down anyway because we suspected
319 * (correctly) that the last up was just
325 bounce
=JUST_GONE_DOWN
;
326 set_timer_callback(&bounce_timer
,
327 current_params
.bounce_interval
);
328 /* start new stroke/tap */
329 debounced_down
=new_down
;
330 notify_pad_up_down();
333 else /* just gone up */
335 if(recent_transition
)
337 /* early bounces are probably part of
338 * a multi-tap gesture, so process
341 debounced_down
=new_down
;
342 notify_pad_up_down();
346 /* don't trust it yet */
348 set_timer_callback(&bounce_timer
,
349 current_params
.bounce_interval
);
359 static void read_raw_pad(int *down
, int *debounced
, int *x
, int *y
)
361 disable_irq(current_params
.irq
);
364 *debounced
=debounced_down
;
369 enable_irq(current_params
.irq
);
372 /*****************************************************************************/
374 * Filesystem interface
378 * Read returns byte triples, so we need to keep track of
379 * how much of a triple has been read. This is shared across
380 * all processes which have this device open---not that anything
381 * will make much sense in that case.
383 static int read_bytes
[3];
384 static int read_byte_count
=0;
388 static void sample_raw(int d
[3])
396 static void sample_rare(int d
[3])
398 int thisd
, thisdd
, thisx
, thisy
;
400 read_raw_pad(&thisd
, &thisdd
, &thisx
, &thisy
);
412 static void sample_debug(int d
[3])
414 int thisd
, thisdd
, thisx
, thisy
;
417 read_raw_pad(&thisd
, &thisdd
, &thisx
, &thisy
);
418 d
[0]=(thisd
?0x80:0) | (thisdd
?0x40:0) | bounce
;
419 d
[1]=(recent_transition
?0x80:0)+transition_count
;
421 d
[2]=(synthesize_tap
<<4) | (b
?0x01:0);
426 static void sample_ps2(int d
[3])
428 static int lastx
, lasty
, lastd
;
430 int thisd
, thisdd
, thisx
, thisy
;
434 * Obtain the current mouse parameters and limit as appropriate for
435 * the return data format. Interrupts are only disabled while
436 * obtaining the parameters, NOT during the puts_fs_byte() calls,
437 * so paging in put_user() does not affect mouse tracking.
439 read_raw_pad(&thisd
, &thisdd
, &thisx
, &thisy
);
442 /* Now compare with previous readings. Note that we use the
443 * raw down flag rather than the debounced one.
445 if( (thisd
&& !lastd
) /* new stroke */
446 || (bounce
!=NO_BOUNCE
) )
461 d[0]= ((dy<0)?0x20:0)
467 d
[0]= ((dy
<0)?0x20:0)
477 static int fasync_pad(int fd
, struct file
*filp
, int on
)
481 retval
= fasync_helper(fd
, filp
, on
, &asyncptr
);
489 * close access to the pad
491 static int close_pad(struct inode
* inode
, struct file
* file
)
493 fasync_pad(-1, file
, 0);
496 outb(0x30, current_params
.io
+2); /* switch off digitiser */
503 * open access to the pad
505 static int open_pad(struct inode
* inode
, struct file
* file
)
512 outb(0x30, current_params
.io
+2); /* switch off digitiser */
513 pad_irq(0,0,0); /* read to flush any pending bytes */
514 pad_irq(0,0,0); /* read to flush any pending bytes */
515 pad_irq(0,0,0); /* read to flush any pending bytes */
516 outb(0x38, current_params
.io
+2); /* switch on digitiser */
517 current_params
= default_params
;
518 raw_data_count
=0; /* re-sync input byte counter */
519 read_byte_count
=0; /* re-sync output byte counter */
524 del_timer(&bounce_timer
);
525 del_timer(&tap_timer
);
533 * writes are disallowed
535 static ssize_t
write_pad(struct file
* file
, const char * buffer
, size_t count
, loff_t
*ppos
)
541 void new_sample(int d
[3])
543 switch(current_params
.mode
)
545 case PC110PAD_RAW
: sample_raw(d
); break;
546 case PC110PAD_RARE
: sample_rare(d
); break;
547 case PC110PAD_DEBUG
: sample_debug(d
); break;
548 case PC110PAD_PS2
: sample_ps2(d
); break;
554 * Read pad data. Currently never blocks.
556 static ssize_t
read_pad(struct file
* file
, char * buffer
, size_t count
, loff_t
*ppos
)
560 for(r
=0; r
<count
; r
++)
563 new_sample(read_bytes
);
564 if(put_user(read_bytes
[read_byte_count
], buffer
+r
))
566 read_byte_count
= (read_byte_count
+1)%3;
573 * select for pad input
576 static unsigned int pad_poll(struct file
*file
, poll_table
* wait
)
578 poll_wait(file
, &queue
, wait
);
579 if(button_pending
|| xy_pending
)
580 return POLLIN
| POLLRDNORM
;
585 static int pad_ioctl(struct inode
*inode
, struct file
* file
,
586 unsigned int cmd
, unsigned long arg
)
588 struct pc110pad_params
new;
594 case PC110PADIOCGETP
:
595 new = current_params
;
596 if(copy_to_user((void *)arg
, &new, sizeof(new)))
600 case PC110PADIOCSETP
:
601 if(copy_from_user(&new, (void *)arg
, sizeof(new)))
604 if( (new.mode
<PC110PAD_RAW
)
605 || (new.mode
>PC110PAD_PS2
)
606 || (new.bounce_interval
<0)
607 || (new.tap_interval
<0)
611 current_params
.mode
= new.mode
;
612 current_params
.bounce_interval
= new.bounce_interval
;
613 current_params
.tap_interval
= new.tap_interval
;
620 static struct file_operations pad_fops
= {
624 NULL
, /* pad_readdir */
633 NULL
, /* check_media_change */
634 NULL
, /* revalidate */
639 static struct miscdevice pc110_pad
= {
640 PC110PAD_MINOR
, "pc110 pad", &pad_fops
644 int pc110pad_init(void)
646 current_params
= default_params
;
648 if(request_irq(current_params
.irq
, pad_irq
, 0, "pc110pad", 0))
650 printk("pc110pad: Unable to get IRQ.\n");
653 if(check_region(current_params
.io
, 4))
655 printk("pc110pad: I/O area in use.\n");
656 free_irq(current_params
.irq
,0);
659 request_region(current_params
.io
, 4, "pc110pad");
660 printk("PC110 digitizer pad at 0x%X, irq %d.\n",
661 current_params
.io
,current_params
.irq
);
662 misc_register(&pc110_pad
);
663 outb(0x30, current_params
.io
+2); /* switch off digitiser */
670 static void pc110pad_unload(void)
672 outb(0x30, current_params
.io
+2); /* switch off digitiser */
673 if(current_params
.irq
)
674 free_irq(current_params
.irq
, 0);
675 current_params
.irq
=0;
676 release_region(current_params
.io
, 4);
677 misc_deregister(&pc110_pad
);
682 int init_module(void)
684 return pc110pad_init();
687 void cleanup_module(void)