📄 skyeye_ts_drv.c
字号:
put_in_queue((char *)&ts_pen,DATA_LENGTH); /* queue event */
/* tell user space progs that a new state occure */
new_pen_state = 1;
/* signal asynchronous readers that data arrives */
if(queue->fasync)
kill_fasync(&queue->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&queue->proc_list); /* tell user space progs */
break;
case CONV_LOOP: /* pen is down, conversion continue */
ts_pen.state &= 0; /* clear */
ts_pen.state &= ST_PEN_DOWN;
switch(state_counter) { /* It could be a move */
case 1: /* the pen just went down, it's a new state */
ts_pen.x = current_pos.x;
ts_pen.y = current_pos.y;
ts_pen.dx = 0;
ts_pen.dy = 0;
ts_pen.event = EV_PEN_DOWN; /* event = pen go to down */
ts_pen.ev_no = ev_counter++; /* get no of event */
//ts_pen.ev_time = set_ev_time(); /* get time of event */
copy_info(); /* remember info */
if(current_params.event_queue_on)
put_in_queue((char *)&ts_pen,DATA_LENGTH); /* queue event */
/* tell user space progs that a new state occure */
new_pen_state = 1;
/* signal asynchronous readers that data arrives */
if(queue->fasync)
kill_fasync(&queue->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&queue->proc_list); /* tell user space progs */
break;
case 2: /* the pen is down for at least 2 loop of the state machine */
if(is_moving()) {
ts_pen.event = EV_PEN_MOVE;
ts_pen.x = current_pos.x;
ts_pen.y = current_pos.y;
ts_pen.dx = ts_pen.x - ts_pen_prev.x;
ts_pen.dy = ts_pen.y - ts_pen_prev.y;
ts_pen.ev_no = ev_counter++; /* get no of event */
// ts_pen.ev_time = set_ev_time(); /* get time of event */
copy_info(); /* remember info */
if(current_params.event_queue_on)
put_in_queue((char *)&ts_pen,DATA_LENGTH); /* queue event */
/*
* pen is moving, then it's anyway a good reason to tell it to
* user space progs
*/
new_pen_state = 1;
/* signal asynchronous readers that data arrives */
if(queue->fasync)
kill_fasync(&queue->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&queue->proc_list);
}
else {
if(ts_pen_prev.event == EV_PEN_MOVE) /* if previous state was moving */
ts_pen.event = EV_PEN_MOVE; /* -> keep it! */
ts_pen.x = ts_pen_prev.x; /* No coord passing to */
ts_pen.y = ts_pen_prev.y; /* avoid Parkinson effects */
ts_pen.dx = 0;
ts_pen.dy = 0; /* no wake-up interruptible because nothing new */
copy_info(); /* remember info */
}
break;
}
break;
case CONV_END: /* pen is up, conversion ends */
ts_pen.state &= 0; /* clear */
ts_pen.state |= ST_PEN_UP;
ts_pen.event = EV_PEN_UP;
ts_pen.x = current_pos.x;
ts_pen.y = current_pos.y;
ts_pen.dx = ts_pen.x - ts_pen_prev.x;
ts_pen.dy = ts_pen.y - ts_pen_prev.y;
// ts_pen.ev_time = set_ev_time(); /* get time of event */
ts_pen.ev_no = ev_counter++; /* get no of event */
copy_info(); /* remember info */
if(current_params.event_queue_on)
put_in_queue((char *)&ts_pen,DATA_LENGTH); /* queue event */
/* tell user space progs that a new state occure */
new_pen_state = 1;
/* signal asynchronous readers that data arrives */
if(queue->fasync)
kill_fasync(&queue->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&queue->proc_list);
break;
}
}
/*----------------------------------------------------------------------------*/
/* Interrupt functions -------------------------------------------------------*/
/*
* pen irq.
*/
static void handle_pen_irq(int irq, void *dev_id, struct pt_regs *regs) {
unsigned long flags;
int bypass_initial_timer = 0;
/* if unwanted interrupts come, trash them */
if(!device_open)
return;
//PENIRQ_DATA &= ~PEN_MASK;
/* - Disabling the penirq has no effect; we keep on getting irqs even when
* penirq is disabled; this is not too annoying: we just trash pen irq events
* that come when disabled.
*/
// printk("enter the pen irq ,INTSR=%x",INTSR);
if(!(INTSR&EINT2)) {
return;
}
save_flags(flags); /* disable interrupts */
cli();
skyeye_read_now(); //ywc 2004-04-11
switch(ts_drv_state) {
case TS_DRV_IDLE:
// DISABLE_PEN_IRQ;
// ts_drv_state++; /* update driver state */
// if(current_params.deglitch_on)
// set_timer_irq(&ts_wake_time,sample_ticks);
// else
// bypass_initial_timer = 1;
break;
default: /* Error */
/* PENIRQ is enable then just init the driver
* Its not necessary to pull down the busy signal
*/
// init_ts_state();
break;
}
DISABLE_PEN_IRQ;
restore_flags(flags); /* Enable interrupts */
}
/*----------------------------------------------------------------------------*/
/* file_operations functions -------------------------------------------------*/
/*
* Called whenever a process attempts to read the device it has already open.
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
static ssize_t ts_read (struct file *file,
char *buff0, /* the buffer to fill with data */
size_t len, /* the length of the buffer. */
loff_t *offset) { /* Our offset in the file */
#else
static int ts_read(struct inode *inode, struct file *file,
char *buff0, /* the buffer to fill with data */
int len) { /* the length of the buffer. */
/* NO WRITE beyond that !!! */
#endif
char *p_buffer;
char c;
int i;
int err;
int havedata=0;
// printk("!!!enter ts_read\n");
/*
while(!current_pos.state) { //no new data come
if(file->f_flags & O_NONBLOCK)
return -EAGAIN;
interruptible_sleep_on(&queue->proc_list);
#if (LINUX_VERSION_CODE >= 0x020100)
if(signal_pending(current))
#else
if(current->signal & ~current->blocked) // a signal arrived
#endif
return -ERESTARTSYS; //tell the fs layer to handle it
// otherwise loop
}
*/
/* Force length to the one available */
len = DATA_LENGTH;
/* verify that the user space address to write is valid */
err = verify_area(VERIFY_WRITE,buff0,len);
if (err) {
printk("verify_area error ,err=%d",err);
return err;
}
/*
for(i=0;i<len;i++){
buff[i]=*((char *)¤t_pos+i);
}
*/
//another copy way???
// struct ts_pen_info * buff;
if(current_pos.ev_no==1){
buff=(struct ts_pen_info *)buff0;
buff->x = current_pos.x;
buff->y = current_pos.y;
buff->dx = current_pos.dx;
buff->dy = current_pos.dy;
buff->event = current_pos.event;
buff->state = current_pos.state;
buff->ev_no = current_pos.ev_no;
buff->ev_time = current_pos.ev_time;
// printk("current_pos.x=%d,buff->x=%d\n",current_pos.x,buff->x);
// printk("current_pos.y=%d,buff->y=%d\n",current_pos.y,buff->y);
havedata=1;
}
current_pos.ev_no=0;// ywc 2004-04-12 data have been read ,set it to 0
// printk("!!!leave ts_read\n");
return havedata;
}
/*
* Called whenever a process attempts to open the device file.
*/
static int ts_open(struct inode *inode, struct file *file) {
int err;
/* To talk to only one device at a time */
printk("!!!enter ts_open\n");
if(device_open) return -EBUSY;
/* IRQ registration have to be done before the hardware is instructed to
* generate interruptions.
*/
/* IRQ for pen */
err = request_irq(PEN_IRQ_NUM, handle_pen_irq,
IRQ_FLG_STD,"touch_screen",NULL);
if(err) {
printk("%s: Error. Cannot attach IRQ %d to touch screen device\n",
__file__, PEN_IRQ_NUM);
return err;
}
printk("%s: IRQ %d attached to touch screen\n",
__file__, PEN_IRQ_NUM);
init_ts_drv();
printk("skyeye touch screen driver: init hardware done..\n\n");
/* Init the queue */
queue = (struct ts_queue *) kmalloc(sizeof(*queue),GFP_KERNEL);
memset(queue,0,sizeof(*queue));
queue->head = queue->tail = 0;
init_waitqueue_head(&queue->proc_list);
/* Increment the usage count (number of opened references to the module)
* to be sure the module couldn't be removed while the file is open.
*/
MOD_INC_USE_COUNT;
/* And my own counter too */
device_open++;
//ts_read(0,0,0,0);
//file->f_op->read(1,1,1,1);
return 0; /* open succeed */
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
static int ts_fasync(int inode, struct file *file, int mode) {
#else
static int ts_fasync(struct inode *inode, struct file *file, int mode) {
#endif
int retval;
retval = fasync_helper(inode,file,mode,&queue->fasync);
if(retval < 0)
return retval;
return 0;
}
/*
* Called whenever a process attempts to close the device file.
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
static int ts_release(struct inode *inode, struct file *file) {
#else
static void ts_release(struct inode *inode, struct file *file) {
#endif
/* Remove this file from the asynchronously notified file's */
ts_fasync(inode,file,0);
/* Release hardware */
release_ts_drv();
/* Free the allocated memory for the queue */
kfree(queue);
/* IRQ have to be freed after the hardware is instructed not to interrupt
* the processor any more.
*/
//free_irq(SPI_IRQ_NUM,NULL);
free_irq(PEN_IRQ_NUM,NULL);
/* Decrement the usage count, otherwise once the file is open we'll never
* get rid of the module.
*/
MOD_DEC_USE_COUNT;
/* And my own counter too */
device_open--;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
return 0;
#endif
}
static struct file_operations ts_fops = {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
owner: THIS_MODULE,
read: ts_read,
//poll: ts_poll,
//ioctl: ts_ioctl,
open: ts_open,
release: ts_release,
fasync: ts_fasync,
#else
NULL, /* lseek */
ts_read, /* read */
NULL, /* write */
NULL, /* readdir */
# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
ts_poll, /* poll */
# else
ts_select, /* select */
# endif
ts_ioctl, /* ioctl */
NULL, /* mmap */
ts_open, /* open */
# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
NULL, /* flush */
# endif
ts_release, /* release (close) */
NULL, /* fsync */
ts_fasync /* async notification */
#endif
};
/*
* miscdevice structure for misc driver registration.
*/
static struct miscdevice mc68328_digi = {
// MC68328DIGI_MINOR,"mc68328 digitizer",&ts_fops
SKYEYE_TS_MINOR,"skyeye touch screen",&ts_fops
};
/*
* Initialize the driver.
*/
static int __init mc68328digi_init(void) {
int err;
int ts;
printk("%s: SkyEye touch screen driver initialize\n", __file__);
/* Register the misc device driver */
err = misc_register(&mc68328_digi);
if(err<0)
printk("%s: Error registering the device\n", __file__);
else
printk("%s: Device register with name: %s and number: %d %d\n",
__file__, mc68328_digi.name, SKYEYE_TS_MAJOR, mc68328_digi.minor);
/* Init prameters settings at boot time */
init_ts_settings();
//******************* test by ywc 2004-3-27 *****************
/*
* open up the touch-panel device.
* Return the fd if successful, or negative if unsuccessful.
*/
/* opened by application on ts_driver!
ts = ts_open("/dev/ts", O_NONBLOCK | O_RDWR);
if (ts < 0) {
printk("Error opening touch panel\n");
return ts;
}
*/
//******************* test by ywc 2004-3-27 *****************
return err; /* A non zero value means that init_module failed */
}
/*
* Cleanup - undid whatever mc68328digi_init did.
*/
void mc68328digi_cleanup(void) {
/* Unregister device driver */
misc_deregister(&mc68328_digi);
}
module_init(mc68328digi_init);
module_exit(mc68328digi_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -