⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pc110pad.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	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 *	The second byte is bits 0-6 X *	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. 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>#include <linux/kernel.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/ptrace.h>#include <linux/poll.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/smp_lock.h>#include <linux/init.h>#include <asm/signal.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/semaphore.h>#include <linux/spinlock.h>#include <asm/uaccess.h>#include "pc110pad.h"static struct pc110pad_params default_params = {	mode:			PC110PAD_PS2,	bounce_interval:	50 MS,	tap_interval:		200 MS,	irq:			10,	io:			0x15E0,};static struct pc110pad_params current_params;/* driver/filesystem interface management */static wait_queue_head_t queue;static struct fasync_struct *asyncptr;static int active;	/* number of concurrent open()s */static struct semaphore reader_lock;/** *	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){	wake_up_interruptible(&queue);	kill_fasync(&asyncptr, SIGIO, POLL_IN);}/*****************************************************************************//* * Deal with the messy business of synthesizing button tap and drag * events. * * Exports: *	notify_pad_up_down() *		Must be called whenever debounced pad up/down state changes. *	button_pending *		Flag is set whenever read_button() has new values *		to return. *	read_button() *		Obtains the current synthetic mouse button state. *//* * These keep track of up/down transitions needed to generate the * synthetic mouse button events.  While recent_transition is set, * up/down events cause transition_count to increment.  tap_timer * turns off the recent_transition flag and may cause some synthetic * up/down mouse events to be created by incrementing synthesize_tap. */ static int button_pending;static int recent_transition;static int transition_count;static int synthesize_tap;static void tap_timeout(unsigned long data);static struct timer_list tap_timer = { function: 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 * timeout occurs the recent_transition flag is cleared and * any synthetic mouse up/down events are generated. */ static void tap_timeout(unsigned long data){	if(!recent_transition)	{		printk(KERN_ERR "pc110pad: tap_timeout but no recent transition!\n");	}	if( transition_count==2 || transition_count==4 || transition_count==6 )	{		synthesize_tap+=transition_count;		button_pending = 1;		wake_readers();	}	recent_transition=0;}/** * notify_pad_up_down: * * Called by the raw pad read routines when a (debounced) up/down * transition is detected. */ void notify_pad_up_down(void){	if(recent_transition)	{		transition_count++;	}	else	{		transition_count=1;		recent_transition=1;	}	mod_timer(&tap_timer, jiffies + current_params.tap_interval);	/* changes to transition_count can cause reported button to change */	button_pending = 1;	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){	if(synthesize_tap)	{		*b=--synthesize_tap & 1;	}	else	{		*b=(!recent_transition && transition_count==3);	/* drag */	}	button_pending=(synthesize_tap>0);}/*****************************************************************************//* * Read pad absolute co-ordinates and debounced up/down state. * * Exports: *	pad_irq() *		Function to be called whenever the pad signals *		that it has new data available. *	read_raw_pad() *		Returns the most current pad state. *	xy_pending *		Flag is set whenever read_raw_pad() has new values *		to return. * Imports: *	wake_readers() *		Called when movement occurs. *	notify_pad_up_down() *		Called when debounced up/down status changes. *//* * These are up/down state and absolute co-ords read directly from pad  */static int raw_data[3];static int raw_data_count;static int raw_x, raw_y;	/* most recent absolute co-ords read */static int raw_down;		/* raw up/down state */static int debounced_down;	/* up/down state after debounce processing */static enum { NO_BOUNCE, JUST_GONE_UP, JUST_GONE_DOWN } bounce=NO_BOUNCE;				/* set just after an up/down transition */static int xy_pending;	/* set if new data have not yet been read *//*  * Timer goes off a short while after an up/down transition and copies * the value of raw_down to debounced_down. */ static void bounce_timeout(unsigned long data);static struct timer_list bounce_timer = { function: 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){	switch(bounce)	{		case NO_BOUNCE:		{			/*			 * Strange; the timer callback should only go off if			 * we were expecting to do bounce processing!			 */			printk(KERN_WARNING "pc110pad, bounce_timeout: bounce flag not set!\n");			break;		}		case JUST_GONE_UP:		{			/*			 * The last up we spotted really was an up, so set			 * debounced state the same as raw state.			 */			bounce=NO_BOUNCE;			if(debounced_down==raw_down)			{				printk(KERN_WARNING "pc110pad, bounce_timeout: raw already debounced!\n");			}			debounced_down=raw_down;			notify_pad_up_down();			break;		}		case JUST_GONE_DOWN:		{			/*			 * We don't debounce down events, but we still time			 * out soon after one occurs so we can avoid the (x,y)			 * skittering that sometimes happens.			 */			bounce=NO_BOUNCE;			break;		}	}}/** * 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. 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){	/* Obtain byte from pad and prime for next byte */	{		int value=inb_p(current_params.io);		int handshake=inb_p(current_params.io+2);		outb_p(handshake | 1, current_params.io+2);		outb_p(handshake &~1, current_params.io+2);		inb_p(0x64);		raw_data[raw_data_count++]=value;	}	if(raw_data_count==3)	{		int new_down=raw_data[0]&0x01;		int new_x=raw_data[1];		int new_y=raw_data[2];		if(raw_data[0]&0x10) new_x+=128;		if(raw_data[0]&0x80) new_x+=256;		if(raw_data[0]&0x08) new_y+=128;		if( (raw_x!=new_x) || (raw_y!=new_y) )		{			raw_x=new_x;			raw_y=new_y;			xy_pending=1;		}		if(new_down != raw_down)		{			/* Down state has changed.  raw_down always holds			 * the most recently observed state.			 */			raw_down=new_down;			/* Forget any earlier bounce processing */			if(bounce)			{				del_timer(&bounce_timer);				bounce=NO_BOUNCE;			}			if(new_down)			{				if(debounced_down)				{					/* pad gone down, but we were reporting					 * it down anyway because we suspected					 * (correctly) that the last up was just					 * a bounce					 */				}				else				{					bounce=JUST_GONE_DOWN;					mod_timer(&bounce_timer,						jiffies+current_params.bounce_interval);					/* start new stroke/tap */					debounced_down=new_down;					notify_pad_up_down();				}			}			else /* just gone up */			{				if(recent_transition)				{					/* early bounces are probably part of					 * a multi-tap gesture, so process					 * immediately					 */					debounced_down=new_down;					notify_pad_up_down();				}				else				{					/* don't trust it yet */					bounce=JUST_GONE_UP;					mod_timer(&bounce_timer,						jiffies+current_params.bounce_interval);				}			}		}		wake_readers();		raw_data_count=0;	}}/** *	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){	disable_irq(current_params.irq);	{		*down=raw_down;		*debounced=debounced_down;		*x=raw_x;		*y=raw_y;		xy_pending = 0;	}	enable_irq(current_params.irq);}/*****************************************************************************//* * Filesystem interface *//*  * Read returns byte triples, so we need to keep track of * how much of a triple has been read.  This is shared across * all processes which have this device open---not that anything * will make much sense in that case.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -