1 /*
2  *	Linux driver for the PC110 pad
3  */
4 
5 /**
6  * 	DOC: PC110 Digitizer Hardware
7  *
8  *	The pad provides triples of data. The first byte has
9  *	0x80=bit 8 X, 0x01=bit 7 X, 0x08=bit 8 Y, 0x01=still down
10  *	The second byte is bits 0-6 X
11  *	The third is bits 0-6 Y
12  *
13  *	This is read internally and used to synthesize a stream of
14  *	triples in the form expected from a PS/2 device. Specialist
15  *	applications can choose to obtain the pad data in other formats
16  *	including a debugging mode.
17  *
18  *	It would be good to add a joystick driver mode to this pad so
19  *	that doom and other game playing are better. One possible approach
20  *	would be to deactive the mouse mode while the joystick port is opened.
21  */
22 
23 /*
24  *	History
25  *
26  *	0.0 1997-05-16 Alan Cox <alan@redhat.com> - Pad reader
27  *	0.1 1997-05-19 Robin O'Leary <robin@acm.org> - PS/2 emulation
28  *	0.2 1997-06-03 Robin O'Leary <robin@acm.org> - tap gesture
29  *	0.3 1997-06-27 Alan Cox <alan@redhat.com> - 2.1 commit
30  *	0.4 1997-11-09 Alan Cox <alan@redhat.com> - Single Unix VFS API changes
31  *	0.5 2000-02-10 Alan Cox <alan@redhat.com> - 2.3.x cleanup, documentation
32  */
33 
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/signal.h>
37 #include <linux/errno.h>
38 #include <linux/mm.h>
39 #include <linux/miscdevice.h>
40 #include <linux/ptrace.h>
41 #include <linux/poll.h>
42 #include <linux/ioport.h>
43 #include <linux/interrupt.h>
44 #include <linux/smp_lock.h>
45 #include <linux/init.h>
46 
47 #include <asm/signal.h>
48 #include <asm/io.h>
49 #include <asm/irq.h>
50 #include <asm/semaphore.h>
51 #include <linux/spinlock.h>
52 #include <asm/uaccess.h>
53 
54 #include "pc110pad.h"
55 
56 
57 static struct pc110pad_params default_params = {
58 	mode:			PC110PAD_PS2,
59 	bounce_interval:	50 MS,
60 	tap_interval:		200 MS,
61 	irq:			10,
62 	io:			0x15E0,
63 };
64 
65 static struct pc110pad_params current_params;
66 
67 
68 /* driver/filesystem interface management */
69 static wait_queue_head_t queue;
70 static struct fasync_struct *asyncptr;
71 static int active;	/* number of concurrent open()s */
72 static struct semaphore reader_lock;
73 
74 /**
75  *	wake_readers:
76  *
77  *	Take care of letting any waiting processes know that
78  *	now would be a good time to do a read().  Called
79  *	whenever a state transition occurs, real or synthetic. Also
80  *	issue any SIGIO's to programs that use SIGIO on mice (eg
81  *	Executor)
82  */
83 
wake_readers(void)84 static void wake_readers(void)
85 {
86 	wake_up_interruptible(&queue);
87 	kill_fasync(&asyncptr, SIGIO, POLL_IN);
88 }
89 
90 
91 /*****************************************************************************/
92 /*
93  * Deal with the messy business of synthesizing button tap and drag
94  * events.
95  *
96  * Exports:
97  *	notify_pad_up_down()
98  *		Must be called whenever debounced pad up/down state changes.
99  *	button_pending
100  *		Flag is set whenever read_button() has new values
101  *		to return.
102  *	read_button()
103  *		Obtains the current synthetic mouse button state.
104  */
105 
106 /*
107  * These keep track of up/down transitions needed to generate the
108  * synthetic mouse button events.  While recent_transition is set,
109  * up/down events cause transition_count to increment.  tap_timer
110  * turns off the recent_transition flag and may cause some synthetic
111  * up/down mouse events to be created by incrementing synthesize_tap.
112  */
113 
114 static int button_pending;
115 static int recent_transition;
116 static int transition_count;
117 static int synthesize_tap;
118 static void tap_timeout(unsigned long data);
119 static struct timer_list tap_timer = { function: tap_timeout };
120 
121 
122 /**
123  * tap_timeout:
124  * @data: Unused
125  *
126  * This callback goes off a short time after an up/down transition;
127  * before it goes off, transitions will be considered part of a
128  * single PS/2 event and counted in transition_count.  Once the
129  * timeout occurs the recent_transition flag is cleared and
130  * any synthetic mouse up/down events are generated.
131  */
132 
tap_timeout(unsigned long data)133 static void tap_timeout(unsigned long data)
134 {
135 	if(!recent_transition)
136 	{
137 		printk(KERN_ERR "pc110pad: tap_timeout but no recent transition!\n");
138 	}
139 	if( transition_count==2 || transition_count==4 || transition_count==6 )
140 	{
141 		synthesize_tap+=transition_count;
142 		button_pending = 1;
143 		wake_readers();
144 	}
145 	recent_transition=0;
146 }
147 
148 
149 /**
150  * notify_pad_up_down:
151  *
152  * Called by the raw pad read routines when a (debounced) up/down
153  * transition is detected.
154  */
155 
notify_pad_up_down(void)156 void notify_pad_up_down(void)
157 {
158 	if(recent_transition)
159 	{
160 		transition_count++;
161 	}
162 	else
163 	{
164 		transition_count=1;
165 		recent_transition=1;
166 	}
167 	mod_timer(&tap_timer, jiffies + current_params.tap_interval);
168 
169 	/* changes to transition_count can cause reported button to change */
170 	button_pending = 1;
171 	wake_readers();
172 }
173 
174 /**
175  *	read_button:
176  *	@b: pointer to the button status.
177  *
178  *	The actual button state depends on what we are seeing. We have to check
179  *	for the tap gesture and also for dragging.
180  */
181 
read_button(int * b)182 static void read_button(int *b)
183 {
184 	if(synthesize_tap)
185 	{
186 		*b=--synthesize_tap & 1;
187 	}
188 	else
189 	{
190 		*b=(!recent_transition && transition_count==3);	/* drag */
191 	}
192 	button_pending=(synthesize_tap>0);
193 }
194 
195 
196 /*****************************************************************************/
197 /*
198  * Read pad absolute co-ordinates and debounced up/down state.
199  *
200  * Exports:
201  *	pad_irq()
202  *		Function to be called whenever the pad signals
203  *		that it has new data available.
204  *	read_raw_pad()
205  *		Returns the most current pad state.
206  *	xy_pending
207  *		Flag is set whenever read_raw_pad() has new values
208  *		to return.
209  * Imports:
210  *	wake_readers()
211  *		Called when movement occurs.
212  *	notify_pad_up_down()
213  *		Called when debounced up/down status changes.
214  */
215 
216 /*
217  * These are up/down state and absolute co-ords read directly from pad
218  */
219 
220 static int raw_data[3];
221 static int raw_data_count;
222 static int raw_x, raw_y;	/* most recent absolute co-ords read */
223 static int raw_down;		/* raw up/down state */
224 static int debounced_down;	/* up/down state after debounce processing */
225 static enum { NO_BOUNCE, JUST_GONE_UP, JUST_GONE_DOWN } bounce=NO_BOUNCE;
226 				/* set just after an up/down transition */
227 static int xy_pending;	/* set if new data have not yet been read */
228 
229 /*
230  * Timer goes off a short while after an up/down transition and copies
231  * the value of raw_down to debounced_down.
232  */
233 
234 static void bounce_timeout(unsigned long data);
235 static struct timer_list bounce_timer = { function: bounce_timeout };
236 
237 
238 
239 /**
240  * bounce_timeout:
241  * @data: Unused
242  *
243  * No further up/down transitions happened within the
244  * bounce period, so treat this as a genuine transition.
245  */
246 
bounce_timeout(unsigned long data)247 static void bounce_timeout(unsigned long data)
248 {
249 	switch(bounce)
250 	{
251 		case NO_BOUNCE:
252 		{
253 			/*
254 			 * Strange; the timer callback should only go off if
255 			 * we were expecting to do bounce processing!
256 			 */
257 			printk(KERN_WARNING "pc110pad, bounce_timeout: bounce flag not set!\n");
258 			break;
259 		}
260 		case JUST_GONE_UP:
261 		{
262 			/*
263 			 * The last up we spotted really was an up, so set
264 			 * debounced state the same as raw state.
265 			 */
266 			bounce=NO_BOUNCE;
267 			if(debounced_down==raw_down)
268 			{
269 				printk(KERN_WARNING "pc110pad, bounce_timeout: raw already debounced!\n");
270 			}
271 			debounced_down=raw_down;
272 
273 			notify_pad_up_down();
274 			break;
275 		}
276 		case JUST_GONE_DOWN:
277 		{
278 			/*
279 			 * We don't debounce down events, but we still time
280 			 * out soon after one occurs so we can avoid the (x,y)
281 			 * skittering that sometimes happens.
282 			 */
283 			bounce=NO_BOUNCE;
284 			break;
285 		}
286 	}
287 }
288 
289 
290 /**
291  * pad_irq:
292  * @irq: Interrupt number
293  * @ptr: Unused
294  * @regs: Unused
295  *
296  * Callback when pad's irq goes off; copies values in to raw_* globals;
297  * initiates debounce processing. This isn't SMP safe however there are
298  * no SMP machines with a PC110 touchpad on them.
299  */
300 
pad_irq(int irq,void * ptr,struct pt_regs * regs)301 static void pad_irq(int irq, void *ptr, struct pt_regs *regs)
302 {
303 
304 	/* Obtain byte from pad and prime for next byte */
305 	{
306 		int value=inb_p(current_params.io);
307 		int handshake=inb_p(current_params.io+2);
308 		outb_p(handshake | 1, current_params.io+2);
309 		outb_p(handshake &~1, current_params.io+2);
310 		inb_p(0x64);
311 
312 		raw_data[raw_data_count++]=value;
313 	}
314 
315 	if(raw_data_count==3)
316 	{
317 		int new_down=raw_data[0]&0x01;
318 		int new_x=raw_data[1];
319 		int new_y=raw_data[2];
320 		if(raw_data[0]&0x10) new_x+=128;
321 		if(raw_data[0]&0x80) new_x+=256;
322 		if(raw_data[0]&0x08) new_y+=128;
323 
324 		if( (raw_x!=new_x) || (raw_y!=new_y) )
325 		{
326 			raw_x=new_x;
327 			raw_y=new_y;
328 			xy_pending=1;
329 		}
330 
331 		if(new_down != raw_down)
332 		{
333 			/* Down state has changed.  raw_down always holds
334 			 * the most recently observed state.
335 			 */
336 			raw_down=new_down;
337 
338 			/* Forget any earlier bounce processing */
339 			if(bounce)
340 			{
341 				del_timer(&bounce_timer);
342 				bounce=NO_BOUNCE;
343 			}
344 
345 			if(new_down)
346 			{
347 				if(debounced_down)
348 				{
349 					/* pad gone down, but we were reporting
350 					 * it down anyway because we suspected
351 					 * (correctly) that the last up was just
352 					 * a bounce
353 					 */
354 				}
355 				else
356 				{
357 					bounce=JUST_GONE_DOWN;
358 					mod_timer(&bounce_timer,
359 						jiffies+current_params.bounce_interval);
360 					/* start new stroke/tap */
361 					debounced_down=new_down;
362 					notify_pad_up_down();
363 				}
364 			}
365 			else /* just gone up */
366 			{
367 				if(recent_transition)
368 				{
369 					/* early bounces are probably part of
370 					 * a multi-tap gesture, so process
371 					 * immediately
372 					 */
373 					debounced_down=new_down;
374 					notify_pad_up_down();
375 				}
376 				else
377 				{
378 					/* don't trust it yet */
379 					bounce=JUST_GONE_UP;
380 					mod_timer(&bounce_timer,
381 						jiffies+current_params.bounce_interval);
382 				}
383 			}
384 		}
385 		wake_readers();
386 		raw_data_count=0;
387 	}
388 }
389 
390 /**
391  *	read_raw_pad:
392  *	@down: set if the pen is down
393  *	@debounced: set if the debounced pen position is down
394  *	@x: X position
395  *	@y: Y position
396  *
397  *	Retrieve the data saved by the interrupt handler and indicate we
398  *	have no more pending XY to do.
399  *
400  *	FIXME: We should switch to a spinlock for this.
401  */
402 
read_raw_pad(int * down,int * debounced,int * x,int * y)403 static void read_raw_pad(int *down, int *debounced, int *x, int *y)
404 {
405 	disable_irq(current_params.irq);
406 	{
407 		*down=raw_down;
408 		*debounced=debounced_down;
409 		*x=raw_x;
410 		*y=raw_y;
411 		xy_pending = 0;
412 	}
413 	enable_irq(current_params.irq);
414 }
415 
416 /*****************************************************************************/
417 /*
418  * Filesystem interface
419  */
420 
421 /*
422  * Read returns byte triples, so we need to keep track of
423  * how much of a triple has been read.  This is shared across
424  * all processes which have this device open---not that anything
425  * will make much sense in that case.
426  */
427 static int read_bytes[3];
428 static int read_byte_count;
429 
430 /**
431  *	sample_raw:
432  *	@d: sample buffer
433  *
434  *	Retrieve a triple of sample data.
435  */
436 
437 
sample_raw(int d[3])438 static void sample_raw(int d[3])
439 {
440 	d[0]=raw_data[0];
441 	d[1]=raw_data[1];
442 	d[2]=raw_data[2];
443 }
444 
445 /**
446  *	sample_rare:
447  *	@d: sample buffer
448  *
449  *	Retrieve a triple of sample data and sanitize it. We do the needed
450  *	scaling and masking to get the current status.
451  */
452 
453 
sample_rare(int d[3])454 static void sample_rare(int d[3])
455 {
456 	int thisd, thisdd, thisx, thisy;
457 
458 	read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
459 
460 	d[0]=(thisd?0x80:0)
461 	   | (thisx/256)<<4
462 	   | (thisdd?0x08:0)
463 	   | (thisy/256)
464 	;
465 	d[1]=thisx%256;
466 	d[2]=thisy%256;
467 }
468 
469 /**
470  *	sample_debug:
471  *	@d: sample buffer
472  *
473  *	Retrieve a triple of sample data and mix it up with the state
474  *	information in the gesture parser. Not useful for normal users but
475  *	handy when debugging
476  */
477 
sample_debug(int d[3])478 static void sample_debug(int d[3])
479 {
480 	int thisd, thisdd, thisx, thisy;
481 	int b;
482 	unsigned long flags;
483 
484 	save_flags(flags);
485 	cli();
486 	read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
487 	d[0]=(thisd?0x80:0) | (thisdd?0x40:0) | bounce;
488 	d[1]=(recent_transition?0x80:0)+transition_count;
489 	read_button(&b);
490 	d[2]=(synthesize_tap<<4) | (b?0x01:0);
491 	restore_flags(flags);
492 }
493 
494 /**
495  *	sample_ps2:
496  *	@d: sample buffer
497  *
498  *	Retrieve a triple of sample data and turn the debounced tap and
499  *	stroke information into what appears to be a PS/2 mouse. This means
500  *	the PC110 pad needs no funny application side support.
501  */
502 
503 
sample_ps2(int d[3])504 static void sample_ps2(int d[3])
505 {
506 	static int lastx, lasty, lastd;
507 
508 	int thisd, thisdd, thisx, thisy;
509 	int dx, dy, b;
510 
511 	/*
512 	 * Obtain the current mouse parameters and limit as appropriate for
513 	 * the return data format.  Interrupts are only disabled while
514 	 * obtaining the parameters, NOT during the puts_fs_byte() calls,
515 	 * so paging in put_user() does not affect mouse tracking.
516 	 */
517 	read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
518 	read_button(&b);
519 
520 	/* Now compare with previous readings.  Note that we use the
521 	 * raw down flag rather than the debounced one.
522 	 */
523 	if( (thisd && !lastd) /* new stroke */
524 	 || (bounce!=NO_BOUNCE) )
525 	{
526 		dx=0;
527 		dy=0;
528 	}
529 	else
530 	{
531 		dx =  (thisx-lastx);
532 		dy = -(thisy-lasty);
533 	}
534 	lastx=thisx;
535 	lasty=thisy;
536 	lastd=thisd;
537 
538 /*
539 	d[0]= ((dy<0)?0x20:0)
540 	    | ((dx<0)?0x10:0)
541 	    | 0x08
542 	    | (b? 0x01:0x00)
543 	;
544 */
545 	d[0]= ((dy<0)?0x20:0)
546 	    | ((dx<0)?0x10:0)
547 	    | (b? 0x00:0x08)
548 	;
549 	d[1]=dx;
550 	d[2]=dy;
551 }
552 
553 
554 /**
555  *	fasync_pad:
556  *	@fd:	file number for the file
557  *	@filp:	file handle
558  *	@on:	1 to add, 0 to remove a notifier
559  *
560  *	Update the queue of asynchronous event notifiers. We can use the
561  *	same helper the mice do and that does almost everything we need.
562  */
563 
fasync_pad(int fd,struct file * filp,int on)564 static int fasync_pad(int fd, struct file *filp, int on)
565 {
566 	int retval;
567 
568 	retval = fasync_helper(fd, filp, on, &asyncptr);
569 	if (retval < 0)
570 		return retval;
571 	return 0;
572 }
573 
574 
575 /**
576  *	close_pad:
577  *	@inode: inode of pad
578  *	@file: file handle to pad
579  *
580  *	Close access to the pad. We turn the pad power off if this is the
581  *	last user of the pad. I've not actually measured the power draw but
582  *	the DOS driver is careful to do this so we follow suit.
583  */
584 
close_pad(struct inode * inode,struct file * file)585 static int close_pad(struct inode * inode, struct file * file)
586 {
587 	lock_kernel();
588 	fasync_pad(-1, file, 0);
589 	if (!--active)
590 		outb(0x30, current_params.io+2);  /* switch off digitiser */
591 	unlock_kernel();
592 	return 0;
593 }
594 
595 
596 /**
597  *	open_pad:
598  *	@inode: inode of pad
599  *	@file: file handle to pad
600  *
601  *	Open access to the pad. We turn the pad off first (we turned it off
602  *	on close but if this is the first open after a crash the state is
603  *	indeterminate). The device has a small fifo so we empty that before
604  *	we kick it back into action.
605  */
606 
open_pad(struct inode * inode,struct file * file)607 static int open_pad(struct inode * inode, struct file * file)
608 {
609 	unsigned long flags;
610 
611 	if (active++)
612 		return 0;
613 
614 	save_flags(flags);
615 	cli();
616 	outb(0x30, current_params.io+2);	/* switch off digitiser */
617 	pad_irq(0,0,0);		/* read to flush any pending bytes */
618 	pad_irq(0,0,0);		/* read to flush any pending bytes */
619 	pad_irq(0,0,0);		/* read to flush any pending bytes */
620 	outb(0x38, current_params.io+2);	/* switch on digitiser */
621 	current_params = default_params;
622 	raw_data_count=0;		/* re-sync input byte counter */
623 	read_byte_count=0;		/* re-sync output byte counter */
624 	button_pending=0;
625 	recent_transition=0;
626 	transition_count=0;
627 	synthesize_tap=0;
628 	del_timer(&bounce_timer);
629 	del_timer(&tap_timer);
630 	restore_flags(flags);
631 
632 	return 0;
633 }
634 
635 
636 /**
637  *	write_pad:
638  *	@file: File handle to the pad
639  *	@buffer: Unused
640  *	@count: Unused
641  *	@ppos: Unused
642  *
643  *	Writes are disallowed. A true PS/2 mouse lets you write stuff. Everyone
644  *	seems happy with this and not faking the write modes.
645  */
646 
write_pad(struct file * file,const char * buffer,size_t count,loff_t * ppos)647 static ssize_t write_pad(struct file * file, const char * buffer, size_t count, loff_t *ppos)
648 {
649 	return -EINVAL;
650 }
651 
652 
653 /*
654  *	new_sample:
655  *	@d: sample buffer
656  *
657  *	Fetch a new sample according the current mouse mode the pad is
658  *	using.
659  */
660 
new_sample(int d[3])661 void new_sample(int d[3])
662 {
663 	switch(current_params.mode)
664 	{
665 		case PC110PAD_RAW:	sample_raw(d);		break;
666 		case PC110PAD_RARE:	sample_rare(d);		break;
667 		case PC110PAD_DEBUG:	sample_debug(d);	break;
668 		case PC110PAD_PS2:	sample_ps2(d);		break;
669 	}
670 }
671 
672 
673 /**
674  * read_pad:
675  * @file: File handle to pad
676  * @buffer: Target for the mouse data
677  * @count: Buffer length
678  * @ppos: Offset (unused)
679  *
680  * Read data from the pad. We use the reader_lock to avoid mess when there are
681  * two readers. This shouldnt be happening anyway but we play safe.
682  */
683 
read_pad(struct file * file,char * buffer,size_t count,loff_t * ppos)684 static ssize_t read_pad(struct file * file, char * buffer, size_t count, loff_t *ppos)
685 {
686 	int r;
687 
688 	down(&reader_lock);
689 	for(r=0; r<count; r++)
690 	{
691 		if(!read_byte_count)
692 			new_sample(read_bytes);
693 		if(put_user(read_bytes[read_byte_count], buffer+r))
694 		{
695 			r = -EFAULT;
696 			break;
697 		}
698 		read_byte_count = (read_byte_count+1)%3;
699 	}
700 	up(&reader_lock);
701 	return r;
702 }
703 
704 
705 /**
706  * pad_poll:
707  * @file: File of the pad device
708  * @wait: Poll table
709  *
710  * The pad is ready to read if there is a button or any position change
711  * pending in the queue. The reading and interrupt routines maintain the
712  * required state for us and do needed wakeups.
713  */
714 
pad_poll(struct file * file,poll_table * wait)715 static unsigned int pad_poll(struct file *file, poll_table * wait)
716 {
717 	poll_wait(file, &queue, wait);
718     	if(button_pending || xy_pending)
719 		return POLLIN | POLLRDNORM;
720 	return 0;
721 }
722 
723 
724 /**
725  *	pad_ioctl;
726  *	@inode: Inode of the pad
727  *	@file: File handle to the pad
728  *	@cmd: Ioctl command
729  *	@arg: Argument pointer
730  *
731  *	The PC110 pad supports two ioctls both of which use the pc110pad_params
732  *	structure. GETP queries the current pad status. SETP changes the pad
733  *	configuration. Changing configuration during normal mouse operations
734  *	may give momentarily odd results as things like tap gesture state
735  *	may be lost.
736  */
737 
pad_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)738 static int pad_ioctl(struct inode *inode, struct file * file,
739 	unsigned int cmd, unsigned long arg)
740 {
741 	struct pc110pad_params new;
742 
743 	if (!inode)
744 		return -EINVAL;
745 
746 	switch (cmd) {
747 	case PC110PADIOCGETP:
748 		new = current_params;
749 		if(copy_to_user((void *)arg, &new, sizeof(new)))
750 			return -EFAULT;
751 		return 0;
752 
753 	case PC110PADIOCSETP:
754 		if(copy_from_user(&new, (void *)arg, sizeof(new)))
755 			return -EFAULT;
756 
757 		if( (new.mode<PC110PAD_RAW)
758 		 || (new.mode>PC110PAD_PS2)
759 		 || (new.bounce_interval<0)
760 		 || (new.tap_interval<0)
761 		)
762 			return -EINVAL;
763 
764 		current_params.mode	= new.mode;
765 		current_params.bounce_interval	= new.bounce_interval;
766 		current_params.tap_interval	= new.tap_interval;
767 		return 0;
768 	}
769 	return -ENOTTY;
770 }
771 
772 
773 static struct file_operations pad_fops = {
774 	owner:		THIS_MODULE,
775 	read:		read_pad,
776 	write:		write_pad,
777 	poll:		pad_poll,
778 	ioctl:		pad_ioctl,
779 	open:		open_pad,
780 	release:	close_pad,
781 	fasync:		fasync_pad,
782 };
783 
784 
785 static struct miscdevice pc110_pad = {
786 	minor:		PC110PAD_MINOR,
787 	name:		"pc110 pad",
788 	fops:		&pad_fops,
789 };
790 
791 
792 /**
793  *	pc110pad_init_driver:
794  *
795  *	We configure the pad with the default parameters (that is PS/2
796  *	emulation mode. We then claim the needed I/O and interrupt resources.
797  *	Finally as a matter of paranoia we turn the pad off until we are
798  *	asked to open it by an application.
799  */
800 
801 static char banner[] __initdata = KERN_INFO "PC110 digitizer pad at 0x%X, irq %d.\n";
802 
pc110pad_init_driver(void)803 static int __init pc110pad_init_driver(void)
804 {
805 	init_MUTEX(&reader_lock);
806 	current_params = default_params;
807 
808 	if (request_irq(current_params.irq, pad_irq, 0, "pc110pad", 0)) {
809 		printk(KERN_ERR "pc110pad: Unable to get IRQ.\n");
810 		return -EBUSY;
811 	}
812 	if (!request_region(current_params.io, 4, "pc110pad"))	{
813 		printk(KERN_ERR "pc110pad: I/O area in use.\n");
814 		free_irq(current_params.irq,0);
815 		return -EBUSY;
816 	}
817 	init_waitqueue_head(&queue);
818 	printk(banner, current_params.io, current_params.irq);
819 	misc_register(&pc110_pad);
820 	outb(0x30, current_params.io+2);	/* switch off digitiser */
821 	return 0;
822 }
823 
824 /*
825  *	pc110pad_exit_driver:
826  *
827  *	Free the resources we acquired when the module was loaded. We also
828  *	turn the pad off to be sure we don't leave it using power.
829  */
830 
pc110pad_exit_driver(void)831 static void __exit pc110pad_exit_driver(void)
832 {
833 	outb(0x30, current_params.io+2);	/* switch off digitiser */
834 	if (current_params.irq)
835 		free_irq(current_params.irq, 0);
836 	current_params.irq = 0;
837 	release_region(current_params.io, 4);
838 	misc_deregister(&pc110_pad);
839 }
840 
841 module_init(pc110pad_init_driver);
842 module_exit(pc110pad_exit_driver);
843 
844 MODULE_AUTHOR("Alan Cox, Robin O'Leary");
845 MODULE_DESCRIPTION("Driver for the touchpad on the IBM PC110 palmtop");
846 MODULE_LICENSE("GPL");
847 
848 EXPORT_NO_SYMBOLS;
849