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

📄 ucb1x00-ts.c~

📁 基于pxa270的touch screen的源码
💻 C~
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/misc/ucb1x00-ts.c * *  Copyright (C) 2001 Russell King, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 21-Jan-2002 <jco@ict.es> : * * Added support for synchronous A/D mode. This mode is useful to * avoid noise induced in the touchpanel by the LCD, provided that * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin. * It is important to note that the signal connected to the ADCSYNC * pin should provide pulses even when the LCD is blanked, otherwise * a pen touch needed to unblank the LCD will never be read. */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include <linux/completion.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/pm.h>#include <asm/dma.h>#include <asm/semaphore.h>#include "ucb1x00.h"/* * Define this if you want the UCB1x00 stuff to talk to the input layer */#ifdef CONFIG_INPUT#define USE_INPUT#else#undef USE_INPUT#endif#ifndef USE_INPUT#include <linux/fs.h>#include <linux/miscdevice.h>#include <linux/poll.h>/* * This structure is nonsense - millisecs is not very useful * since the field size is too small.  Also, we SHOULD NOT * be exposing jiffies to user space directly. */struct ts_event {	u16		pressure;	u16		x;	u16		y;	u16		pad;	struct timeval	stamp;};#define NR_EVENTS	16#else#include <linux/input.h>#endifstruct ucb1x00_ts {#ifdef USE_INPUT	struct input_dev	idev;#endif	struct ucb1x00		*ucb;#ifdef CONFIG_PM	struct pm_dev		*pmdev;#endif	struct semaphore	irq_wait;	struct semaphore	sem;	struct completion	init_exit;	struct task_struct	*rtask;	int			use_count;	u16			x_res;	u16			y_res;#ifndef USE_INPUT	struct fasync_struct	*fasync;	wait_queue_head_t	read_wait;	u8			evt_head;	u8			evt_tail;	struct ts_event		events[NR_EVENTS];#endif	int			restart:1;	int			adcsync:1;};static struct ucb1x00_ts ucbts;static int adcsync = UCB_NOSYNC;static int ucb1x00_ts_startup(struct ucb1x00_ts *ts);static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts);extern int pm_updatetimer(int);#ifndef USE_INPUT#define ucb1x00_ts_evt_pending(ts)	((volatile u8)(ts)->evt_head != (ts)->evt_tail)#define ucb1x00_ts_evt_get(ts)		((ts)->events + (ts)->evt_tail)#define ucb1x00_ts_evt_pull(ts)		((ts)->evt_tail = ((ts)->evt_tail + 1) & (NR_EVENTS - 1))#define ucb1x00_ts_evt_clear(ts)	((ts)->evt_head = (ts)->evt_tail = 0)static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y){	int next_head;	next_head = (ts->evt_head + 1) & (NR_EVENTS - 1);	if (next_head != ts->evt_tail) {		ts->events[ts->evt_head].pressure = pressure;		ts->events[ts->evt_head].x = x;		ts->events[ts->evt_head].y = y;		do_gettimeofday(&ts->events[ts->evt_head].stamp);		ts->evt_head = next_head;		if (ts->fasync)			kill_fasync(&ts->fasync, SIGIO, POLL_IN);		wake_up_interruptible(&ts->read_wait);	}}static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts){	ucb1x00_ts_evt_add(ts, 0, 0, 0);}/* * User space driver interface. */static ssize_tucb1x00_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){	DECLARE_WAITQUEUE(wait, current);	struct ucb1x00_ts *ts = filp->private_data;	char *ptr = buffer;	int err = 0;	add_wait_queue(&ts->read_wait, &wait);	while (count >= sizeof(struct ts_event)) {		err = -ERESTARTSYS;		if (signal_pending(current))			break;		if (ucb1x00_ts_evt_pending(ts)) {			struct ts_event *evt = ucb1x00_ts_evt_get(ts);			err = copy_to_user(ptr, evt, sizeof(struct ts_event));			ucb1x00_ts_evt_pull(ts);			if (err)				break;			ptr += sizeof(struct ts_event);			count -= sizeof(struct ts_event);			continue;		}		set_current_state(TASK_INTERRUPTIBLE);		err = -EAGAIN;		if (filp->f_flags & O_NONBLOCK)			break;		schedule();	}	current->state = TASK_RUNNING;	remove_wait_queue(&ts->read_wait, &wait); 	return ptr == buffer ? err : ptr - buffer;}static unsigned int ucb1x00_ts_poll(struct file *filp, poll_table *wait){	struct ucb1x00_ts *ts = filp->private_data;	int ret = 0;	poll_wait(filp, &ts->read_wait, wait);	if (ucb1x00_ts_evt_pending(ts))		ret = POLLIN | POLLRDNORM;	return ret;}static int ucb1x00_ts_fasync(int fd, struct file *filp, int on){	struct ucb1x00_ts *ts = filp->private_data;	return fasync_helper(fd, filp, on, &ts->fasync);}static int ucb1x00_ts_open(struct inode *inode, struct file *filp){	struct ucb1x00_ts *ts = &ucbts;	int ret = 0;	ret = ucb1x00_ts_startup(ts);	if (ret == 0)		filp->private_data = ts;	return ret;}/* * Release touchscreen resources.  Disable IRQs. */static int ucb1x00_ts_release(struct inode *inode, struct file *filp){	struct ucb1x00_ts *ts = filp->private_data;	down(&ts->sem);	ucb1x00_ts_fasync(-1, filp, 0);	ucb1x00_ts_shutdown(ts);	up(&ts->sem);	return 0;}static struct file_operations ucb1x00_fops = {	owner:		THIS_MODULE,	read:		ucb1x00_ts_read,	poll:		ucb1x00_ts_poll,	open:		ucb1x00_ts_open,	release:	ucb1x00_ts_release,	fasync:		ucb1x00_ts_fasync,};/* * The official UCB1x00 touchscreen is a miscdevice: *   10 char        Non-serial mice, misc features *                   14 = /dev/touchscreen/ucb1x00  UCB 1x00 touchscreen */static struct miscdevice ucb1x00_ts_dev = {	minor:	14,	name:	"touchscreen/ucb1x00",	fops:	&ucb1x00_fops,};static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts){	init_waitqueue_head(&ts->read_wait);	return misc_register(&ucb1x00_ts_dev);}static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts){	misc_deregister(&ucb1x00_ts_dev);}#else#define ucb1x00_ts_evt_clear(ts)	do { } while (0)static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y){	input_report_abs(&ts->idev, ABS_X, x);	input_report_abs(&ts->idev, ABS_Y, y);	input_report_abs(&ts->idev, ABS_PRESSURE, pressure);}static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts){	input_report_abs(&ts->idev, ABS_PRESSURE, 0);}static int ucb1x00_ts_open(struct input_dev *idev){	struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;	return ucb1x00_ts_startup(ts);}static void ucb1x00_ts_close(struct input_dev *idev){	struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;	down(&ts->sem);	ucb1x00_ts_shutdown(ts);	up(&ts->sem);}static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts){	ts->idev.name      = "Touchscreen panel";	ts->idev.idproduct = ts->ucb->id;	ts->idev.open      = ucb1x00_ts_open;	ts->idev.close     = ucb1x00_ts_close;	__set_bit(EV_ABS, ts->idev.evbit);	__set_bit(ABS_X, ts->idev.absbit);	__set_bit(ABS_Y, ts->idev.absbit);	__set_bit(ABS_PRESSURE, ts->idev.absbit);	input_register_device(&ts->idev);	return 0;}static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts){         input_unregister_device(&ts->idev);}#endif/* * Switch to interrupt mode. */static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts){	if (ts->ucb->id == UCB_ID_1400_BUGGY)		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,				UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |				UCB_TS_CR_MODE_INT);	else		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,				UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |				UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |				UCB_TS_CR_MODE_INT);}/* * Switch to pressure mode, and read pressure.  We don't need to wait * here, since both plates are being driven. */static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts){	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,			UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);	return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);}/* * Switch to X position mode and measure Y plate.  We switch the plate * configuration in pressure mode, then switch to position mode.  This * gives a faster response time.  Even so, we need to wait about 55us * for things to stabilise. */static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts){   int a,b,c;//bruce         unsigned int d;   int n=10000;		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);	udelay(55);	//bruce	a=ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);	udelay(30);	b=ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);	udelay(30);	c=ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);	//d=ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);	//printk(KERN_EMERG "a:%d\n",a);	//printk(KERN_EMERG "b:%d\n",b);	//printk(KERN_EMERG "c:%d\n",c);	//printk(KERN_EMERG "d:%d\n",d);	//while(((b-a)>2)||((b-a)<-2)){	//a=(a+b)/2;	//printk(KERN_EMERG "a:%d\n",a);	//b=ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);	//printk(KERN_EMERG "b:%d\n",b);	  	//}	//c=(a+b)/2;	//while(((b-a)>1)||((b-a)<-1)){	//a=b;	//b=ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);		//printk(KERN_EMERG "b:%d\n",b);	  	//}	//c=b;	while(((b-a)>4)||((b-a)<-4)||((c-a)>4)||((c-a)<-4)){	  if(n>0){	    n--;	    a=b;

⌨️ 快捷键说明

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