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@redhat.com> - 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@redhat.com> - 2.1 commit
16 * 0.4 1997-11-09 Alan Cox <alan@redhat.com> - Single Unix VFS API changes
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/signal.h>
22 #include <linux/errno.h>
24 #include <linux/miscdevice.h>
25 #include <linux/ptrace.h>
26 #include <linux/poll.h>
27 #include <linux/ioport.h>
28 #include <linux/interrupt.h>
30 #include <asm/signal.h>
33 #include <asm/uaccess.h>
38 static struct pc110pad_params default_params
= {
39 PC110PAD_PS2
, /* read mode */
40 50 MS
, /* bounce interval */
41 200 MS
, /* tap interval */
43 0x15E0, /* I/O port */
47 static struct pc110pad_params current_params
;
50 /* driver/filesystem interface management */
51 static wait_queue_head_t queue
;
52 static struct fasync_struct
*asyncptr
;
53 static int active
=0; /* number of concurrent open()s */
57 * Utility to reset a timer to go off some time in the future.
60 static void set_timer_callback(struct timer_list
*timer
, int ticks
)
63 timer
->expires
= jiffies
+ticks
;
69 * Take care of letting any waiting processes know that
70 * now would be a good time to do a read(). Called
71 * whenever a state transition occurs, real or synthetic.
74 static void wake_readers(void)
76 wake_up_interruptible(&queue
);
78 kill_fasync(asyncptr
, SIGIO
);
82 /*****************************************************************************/
84 * Deal with the messy business of synthesizing button tap and drag
88 * notify_pad_up_down()
89 * Must be called whenever debounced pad up/down state changes.
91 * Flag is set whenever read_button() has new values
94 * Obtains the current synthetic mouse button state.
98 * These keep track of up/down transitions needed to generate the
99 * synthetic mouse button events. While recent_transition is set,
100 * up/down events cause transition_count to increment. tap_timer
101 * turns off the recent_transition flag and may cause some synthetic
102 * up/down mouse events to be created by incrementing synthesize_tap.
105 static int button_pending
=0;
106 static int recent_transition
=0;
107 static int transition_count
=0;
108 static int synthesize_tap
=0;
109 static void tap_timeout(unsigned long data
);
110 static struct timer_list tap_timer
= { NULL
, NULL
, 0, 0, tap_timeout
};
114 * This callback goes off a short time after an up/down transition;
115 * before it goes off, transitions will be considered part of a
116 * single PS/2 event and counted in transition_count. Once the
117 * timeout occurs the recent_transition flag is cleared and
118 * any synthetic mouse up/down events are generated.
121 static void tap_timeout(unsigned long data
)
123 if(!recent_transition
)
125 printk("pc110pad: tap_timeout but no recent transition!\n");
127 if( transition_count
==2 || transition_count
==4 || transition_count
==6 )
129 synthesize_tap
+=transition_count
;
138 * Called by the raw pad read routines when a (debounced) up/down
139 * transition is detected.
142 void notify_pad_up_down(void)
144 if(recent_transition
)
153 set_timer_callback(&tap_timer
, current_params
.tap_interval
);
155 /* changes to transition_count can cause reported button to change */
161 static void read_button(int *b
)
165 *b
=--synthesize_tap
& 1;
169 *b
=(!recent_transition
&& transition_count
==3); /* drag */
171 button_pending
=(synthesize_tap
>0);
175 /*****************************************************************************/
177 * Read pad absolute co-ordinates and debounced up/down state.
181 * Function to be called whenever the pad signals
182 * that it has new data available.
184 * Returns the most current pad state.
186 * Flag is set whenever read_raw_pad() has new values
190 * Called when movement occurs.
191 * notify_pad_up_down()
192 * Called when debounced up/down status changes.
196 * These are up/down state and absolute co-ords read directly from pad
199 static int raw_data
[3];
200 static int raw_data_count
=0;
201 static int raw_x
=0, raw_y
=0; /* most recent absolute co-ords read */
202 static int raw_down
=0; /* raw up/down state */
203 static int debounced_down
=0; /* up/down state after debounce processing */
204 static enum { NO_BOUNCE
, JUST_GONE_UP
, JUST_GONE_DOWN
} bounce
=NO_BOUNCE
;
205 /* set just after an up/down transition */
206 static int xy_pending
=0; /* set if new data have not yet been read */
209 * Timer goes off a short while after an up/down transition and copies
210 * the value of raw_down to debounced_down.
213 static void bounce_timeout(unsigned long data
);
214 static struct timer_list bounce_timer
= { NULL
, NULL
, 0, 0, bounce_timeout
};
217 static void bounce_timeout(unsigned long data
)
220 * No further up/down transitions happened within the
221 * bounce period, so treat this as a genuine transition.
228 * Strange; the timer callback should only go off if
229 * we were expecting to do bounce processing!
231 printk("pc110pad, bounce_timeout: bounce flag not set!\n");
237 * The last up we spotted really was an up, so set
238 * debounced state the same as raw state.
241 if(debounced_down
==raw_down
)
243 printk("pc110pad, bounce_timeout: raw already debounced!\n");
245 debounced_down
=raw_down
;
247 notify_pad_up_down();
253 * We don't debounce down events, but we still time
254 * out soon after one occurs so we can avoid the (x,y)
255 * skittering that sometimes happens.
265 * Callback when pad's irq goes off; copies values in to raw_* globals;
266 * initiates debounce processing.
268 static void pad_irq(int irq
, void *ptr
, struct pt_regs
*regs
)
271 /* Obtain byte from pad and prime for next byte */
273 int value
=inb_p(current_params
.io
);
274 int handshake
=inb_p(current_params
.io
+2);
275 outb_p(handshake
| 1, current_params
.io
+2);
276 outb_p(handshake
&~1, current_params
.io
+2);
279 raw_data
[raw_data_count
++]=value
;
282 if(raw_data_count
==3)
284 int new_down
=raw_data
[0]&0x01;
285 int new_x
=raw_data
[1];
286 int new_y
=raw_data
[2];
287 if(raw_data
[0]&0x10) new_x
+=128;
288 if(raw_data
[0]&0x80) new_x
+=256;
289 if(raw_data
[0]&0x08) new_y
+=128;
291 if( (raw_x
!=new_x
) || (raw_y
!=new_y
) )
298 if(new_down
!= raw_down
)
300 /* Down state has changed. raw_down always holds
301 * the most recently observed state.
305 /* Forget any earlier bounce processing */
308 del_timer(&bounce_timer
);
316 /* pad gone down, but we were reporting
317 * it down anyway because we suspected
318 * (correctly) that the last up was just
324 bounce
=JUST_GONE_DOWN
;
325 set_timer_callback(&bounce_timer
,
326 current_params
.bounce_interval
);
327 /* start new stroke/tap */
328 debounced_down
=new_down
;
329 notify_pad_up_down();
332 else /* just gone up */
334 if(recent_transition
)
336 /* early bounces are probably part of
337 * a multi-tap gesture, so process
340 debounced_down
=new_down
;
341 notify_pad_up_down();
345 /* don't trust it yet */
347 set_timer_callback(&bounce_timer
,
348 current_params
.bounce_interval
);
358 static void read_raw_pad(int *down
, int *debounced
, int *x
, int *y
)
360 disable_irq(current_params
.irq
);
363 *debounced
=debounced_down
;
368 enable_irq(current_params
.irq
);
371 /*****************************************************************************/
373 * Filesystem interface
377 * Read returns byte triples, so we need to keep track of
378 * how much of a triple has been read. This is shared across
379 * all processes which have this device open---not that anything
380 * will make much sense in that case.
382 static int read_bytes
[3];
383 static int read_byte_count
=0;
387 static void sample_raw(int d
[3])
395 static void sample_rare(int d
[3])
397 int thisd
, thisdd
, thisx
, thisy
;
399 read_raw_pad(&thisd
, &thisdd
, &thisx
, &thisy
);
411 static void sample_debug(int d
[3])
413 int thisd
, thisdd
, thisx
, thisy
;
416 read_raw_pad(&thisd
, &thisdd
, &thisx
, &thisy
);
417 d
[0]=(thisd
?0x80:0) | (thisdd
?0x40:0) | bounce
;
418 d
[1]=(recent_transition
?0x80:0)+transition_count
;
420 d
[2]=(synthesize_tap
<<4) | (b
?0x01:0);
425 static void sample_ps2(int d
[3])
427 static int lastx
, lasty
, lastd
;
429 int thisd
, thisdd
, thisx
, thisy
;
433 * Obtain the current mouse parameters and limit as appropriate for
434 * the return data format. Interrupts are only disabled while
435 * obtaining the parameters, NOT during the puts_fs_byte() calls,
436 * so paging in put_user() does not affect mouse tracking.
438 read_raw_pad(&thisd
, &thisdd
, &thisx
, &thisy
);
441 /* Now compare with previous readings. Note that we use the
442 * raw down flag rather than the debounced one.
444 if( (thisd
&& !lastd
) /* new stroke */
445 || (bounce
!=NO_BOUNCE
) )
460 d[0]= ((dy<0)?0x20:0)
466 d
[0]= ((dy
<0)?0x20:0)
476 static int fasync_pad(int fd
, struct file
*filp
, int on
)
480 retval
= fasync_helper(fd
, filp
, on
, &asyncptr
);
488 * close access to the pad
490 static int close_pad(struct inode
* inode
, struct file
* file
)
492 fasync_pad(-1, file
, 0);
495 outb(0x30, current_params
.io
+2); /* switch off digitiser */
502 * open access to the pad
504 static int open_pad(struct inode
* inode
, struct file
* file
)
511 outb(0x30, current_params
.io
+2); /* switch off digitiser */
512 pad_irq(0,0,0); /* read to flush any pending bytes */
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 outb(0x38, current_params
.io
+2); /* switch on digitiser */
516 current_params
= default_params
;
517 raw_data_count
=0; /* re-sync input byte counter */
518 read_byte_count
=0; /* re-sync output byte counter */
523 del_timer(&bounce_timer
);
524 del_timer(&tap_timer
);
532 * writes are disallowed
534 static ssize_t
write_pad(struct file
* file
, const char * buffer
, size_t count
, loff_t
*ppos
)
540 void new_sample(int d
[3])
542 switch(current_params
.mode
)
544 case PC110PAD_RAW
: sample_raw(d
); break;
545 case PC110PAD_RARE
: sample_rare(d
); break;
546 case PC110PAD_DEBUG
: sample_debug(d
); break;
547 case PC110PAD_PS2
: sample_ps2(d
); break;
553 * Read pad data. Currently never blocks.
555 static ssize_t
read_pad(struct file
* file
, char * buffer
, size_t count
, loff_t
*ppos
)
559 for(r
=0; r
<count
; r
++)
562 new_sample(read_bytes
);
563 if(put_user(read_bytes
[read_byte_count
], buffer
+r
))
565 read_byte_count
= (read_byte_count
+1)%3;
572 * select for pad input
575 static unsigned int pad_poll(struct file
*file
, poll_table
* wait
)
577 poll_wait(file
, &queue
, wait
);
578 if(button_pending
|| xy_pending
)
579 return POLLIN
| POLLRDNORM
;
584 static int pad_ioctl(struct inode
*inode
, struct file
* file
,
585 unsigned int cmd
, unsigned long arg
)
587 struct pc110pad_params
new;
593 case PC110PADIOCGETP
:
594 new = current_params
;
595 if(copy_to_user((void *)arg
, &new, sizeof(new)))
599 case PC110PADIOCSETP
:
600 if(copy_from_user(&new, (void *)arg
, sizeof(new)))
603 if( (new.mode
<PC110PAD_RAW
)
604 || (new.mode
>PC110PAD_PS2
)
605 || (new.bounce_interval
<0)
606 || (new.tap_interval
<0)
610 current_params
.mode
= new.mode
;
611 current_params
.bounce_interval
= new.bounce_interval
;
612 current_params
.tap_interval
= new.tap_interval
;
619 static struct file_operations pad_fops
= {
623 NULL
, /* pad_readdir */
632 NULL
, /* check_media_change */
633 NULL
, /* revalidate */
638 static struct miscdevice pc110_pad
= {
639 PC110PAD_MINOR
, "pc110 pad", &pad_fops
643 int pc110pad_init(void)
645 current_params
= default_params
;
647 if(request_irq(current_params
.irq
, pad_irq
, 0, "pc110pad", 0))
649 printk("pc110pad: Unable to get IRQ.\n");
652 if(check_region(current_params
.io
, 4))
654 printk("pc110pad: I/O area in use.\n");
655 free_irq(current_params
.irq
,0);
658 request_region(current_params
.io
, 4, "pc110pad");
659 init_waitqueue_head(&queue
);
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)