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

📄 main.c

📁 触摸屏驱动芯片ADS7843在LINUX2.6内核下的驱动程序
💻 C
字号:
/* * FileName 	main.c * Author 	wangzhenhui * Date 	09/18/06 * Board	SESI_AT91RM9200EDUKIT * Desc	touchscreen driver ads7843 */#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/kernel.h>	/* printk() */#include <linux/slab.h>	/* kmalloc() */#include <linux/fs.h>	/* everything... */#include <linux/errno.h>	/* error codes */#include <linux/types.h>	/* size_t */#include <linux/proc_fs.h>#include <linux/fcntl.h>	/* O_ACCMODE */#include <linux/seq_file.h>#include <linux/cdev.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/jiffies.h>#include <asm/system.h>	/* cli(), *_flags */#include <asm/uaccess.h>	/* copy_*_user */#include <asm/arch/board.h>#include <asm/arch/gpio.h>#include <asm/hardware.h>#include <linux/interrupt.h>#include <asm/irq.h>#include "ads7843.h"//#undef  DEBUG_ADS7843#define DEBUG_ADS7843	1#ifdef DEBUG_ADS7843#define DBG_ADS7843(fmt, args...) printk(fmt,## args)#else#define DBG_ADS7843(fmt, args...)#endifstatic void ads7843_ts_read_pos(struct ads7843_dev *, struct ts_event *);static void ads7843_timer(unsigned long);int ads7843_major =   0;int ads7843_minor =   0;struct ads7843_dev *ads7843_device;static inline void ads7843_ts_evt_add(struct ads7843_dev *ts, unsigned short pressure, unsigned short x, unsigned short 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;	}}static inline void ads7843_ts_event_release(struct ads7843_dev *ts){	ads7843_ts_evt_add(ts, 0, 0, 0);}static irqreturn_t ads7843_pen_irq(int irq, void *dev_id, struct pt_regs *regs){	unsigned long j=jiffies;	printk("ads7843_pen_irq\n");	disable_irq(AT91_PIN_PD0);		mod_timer(&ads7843_device->timer,j+HZ/100);	return 0;}static int ads7843_startup(struct ads7843_dev *ts){	int ret;	unsigned long j=jiffies;	if(down_interruptible(&ts->sem))		return -EINTR;	/* check if open first time */	if(ts->use_count!=0)		return -EBUSY;	/* init PIO */	DBG_ADS7843("ADS7843 init PIO.\n");	at91_set_gpio_output(TS_CS,0);	at91_set_gpio_output(TS_CLK,0);	at91_set_gpio_output(TS_DIN,0);	at91_set_gpio_input(TS_DOUT,0);	at91_set_gpio_input(AT91_PIN_PD0,0);	at91_set_gpio_input(AT91_PIN_PD4,0);	/* reg irq */		ret=request_irq(AT91_PIN_PD0, ads7843_pen_irq,			SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,			"ads7843", ts);	enable_irq(AT91_PIN_PD0);	if(ret)	{		DBG_ADS7843("request irq failed.\n");		return ret;	}	/* init timer */	init_timer(&ts->timer);	ts->timer.expires=j+HZ/100;	ts->timer.data = (unsigned long) ts;	ts->timer.function = ads7843_timer;	add_timer(&ts->timer);	/* clear event queue */	ads7843_ts_evt_clear(ts);	/* module counter add */	ts->use_count++;	up(&ts->sem);	return 0;}static void ads7843_timer(unsigned long handle){	struct ts_event event;	int val;	struct ads7843_dev	*ts = (void *)handle;		/* read position */	ads7843_ts_read_pos(ts, &event);	DBG_ADS7843("read x:0X%x,\ty:0X%x\n",event.x,event.y);	/* get PENIRQ status */	val=at91_get_gpio_value(AT91_PIN_PD0);	if(val!=0)	{		//ads7843_ts_event_release(ts);		enable_irq(AT91_PIN_PD0);		}	else	{		ads7843_ts_evt_add(ts, event.pad, event.x, event.y);		ts->timer.expires+=HZ/100;		mod_timer(&ts->timer,ts->timer.expires);	}	}static unsigned short ads7843_transfer(unsigned char cmd){	int i;	unsigned char bit;	unsigned short read_data = 0;		/* CS# Low */	at91_set_gpio_value(TS_CS, 0);	udelay(40);		/* Transform CMD */	for(i=1; i<=8; i++){		/* CMD Output */		bit = ( cmd >> (8-i) ) & 0x01 ;		at91_set_gpio_value(TS_DIN, bit);		udelay(20);						/* CLK High */		at91_set_gpio_value(TS_CLK, 1);		udelay(40);		/* CLK Low */		at91_set_gpio_value(TS_CLK, 0);		udelay(20);	}		/* Waiting for busy */	udelay(50);		/* Read DATA */	for(i=7; i>=0; i--){		/* CLK High */		at91_set_gpio_value(TS_CLK, 1);		udelay(40);		/* CLK Low */		at91_set_gpio_value(TS_CLK, 0);				/* Data in */				if( at91_get_gpio_value(TS_DOUT) != 0 )			read_data |= 1 << i;		udelay(40);	}		/* CS# High */	at91_set_gpio_value(TS_CS, 1);	udelay(50);	return read_data;}static void ads7843_ts_read_pos(struct ads7843_dev *ts, struct ts_event *event){	int i;	unsigned char cmd[2];	unsigned short data[2];		cmd[0] = MEASURE_8BIT_X;	cmd[1] = MEASURE_8BIT_Y;		for(i=0; i<2; i++){		data[i] = ads7843_transfer(cmd[i]);	}		event->x = data[0];	event->y = data[1];	event->pressure = 100;	//printk("ts read pos: x = %d, y = %d\n", event->x, event->y);}ssize_t ads7843_read(struct file *filp, char __user *buffer, size_t count,                loff_t *f_pos){	struct ads7843_dev *ts = filp->private_data;	char *ptr = buffer;	int err = 0;	while (count >= sizeof(struct ts_event)) {		err = -ERESTARTSYS;				if (ads7843_ts_evt_pending(ts)) {			struct ts_event *evt = ads7843_ts_evt_get(ts);			err = copy_to_user(ptr, evt, sizeof(struct ts_event));			ads7843_ts_evt_pull(ts);			if (err)				break;			ptr += sizeof(struct ts_event);			count -= sizeof(struct ts_event);			continue;		}	}	return ptr == buffer ? err : ptr - buffer;}int ads7843_ioctl(struct inode *inode, struct file *filp,                 unsigned int cmd, unsigned long arg){	return 0;}int ads7843_release(struct inode *inode, struct file *filp){	struct ads7843_dev *ts = filp->private_data;	down(&ts->sem);	if(--ts->use_count==0)	{			free_irq(AT91_PIN_PD0,ts);		kfree(ads7843_device);	}	up(&ts->sem);	return 0;}int ads7843_open(struct inode *inode, struct file *filp){		int ret = 0;	ret = ads7843_startup(ads7843_device);	if (ret == 0)		filp->private_data = ads7843_device;	DBG_ADS7843("open return %d",ret);	return ret;}ssize_t ads7843_write(struct file *filp, const char __user *buf, size_t count,                loff_t *f_pos){	return 0;}struct file_operations ads7843_fops = {	.owner =    THIS_MODULE,	.read =     ads7843_read,	.write =    ads7843_write,	.ioctl =    ads7843_ioctl,	.open =     ads7843_open,	.release =  ads7843_release,};void  ads7843_cleanup_module(void){	dev_t devno = MKDEV(ads7843_major, ads7843_minor);	printk("ads7843 module cleanup.\n");	cdev_del(&ads7843_device->cdev);	kfree(ads7843_device);	unregister_chrdev_region(devno, 1);	free_irq(AT91_PIN_PD0,0);	}int  ads7843_init_module(void){	int result,dev_no;	dev_t dev = 0;	/* ask for a dynamic major */	result = alloc_chrdev_region(&dev, ads7843_minor, 0,				"ads7843");	ads7843_major = MAJOR(dev);		if (result < 0) {		printk(KERN_WARNING "ADS7843: can't get major %d\n", ads7843_major);		return result;	}	/* mem alloc for device */	ads7843_device = kmalloc(sizeof(struct ads7843_dev), GFP_KERNEL);	if (!ads7843_device) {		result = -ENOMEM;		printk(KERN_WARNING "ads 7843 memory alloc failed.\n");		goto fail;  /* Make this more graceful */	}	memset(ads7843_device, 0, sizeof(struct ads7843_dev));	/* init mutex */	init_MUTEX(&(ads7843_device->sem));	/* reg device */	dev_no = MKDEV(ads7843_major, ads7843_minor);	cdev_init(&ads7843_device->cdev, &ads7843_fops);	ads7843_device->cdev.owner = THIS_MODULE;	ads7843_device->cdev.ops = &ads7843_fops;	result = cdev_add (&ads7843_device->cdev, dev_no, 1);	/* Fail gracefully if need be */	if (result){		printk(KERN_NOTICE "Error %d adding ads7843.\n", result);		goto fail;	}	printk("ads7843 module init major:%d.\n",ads7843_major);	return 0;fail:	ads7843_cleanup_module();	return result;}module_init(ads7843_init_module);module_exit(ads7843_cleanup_module);MODULE_AUTHOR("Zhenhui wang, wangzhenhui2002@hotmail.com");MODULE_LICENSE("GPL"); 

⌨️ 快捷键说明

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