📄 main.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 + -