📄 test.c
字号:
/* * s3c2410-ts.c * * touchScreen driver for SAMSUNG S3C2410 * * Author: Janghoon Lyu <nandy@mizi.com> * Date : $Date: 2002/06/04 07:11:00 $ * * $Revision: 1.1.2.6 $ * * Based on pt036001b-ts.c * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. * * History: * * 2002-05-27: Janghoon Lyu <nandy@mizi.com> * - Add HOOK_FOR_DRAG * - PM 内靛啊 甸绢啊 乐变 窍瘤父 抛胶飘 登瘤 臼疽澜. * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <linux/delay.h>#include <asm/hardware.h>//#include <asm/arch/spi.h>/* debug macros */#undef DEBUG#define DEBUG#ifdef DEBUG#define DPRINTK( x... ) printk("s3c2410-ts: " ##x)#else#define DPRINTK( x... )#endif#define PEN_UP 0 #define PEN_DOWN 1#define PEN_FLEETING 2#define MAX_TS_BUF 16 /* how many do we want to buffer */#undef USE_ASYNC 1#define DEVICE_NAME "s3c2410-ts"#define TSRAW_MINOR 1typedef struct { unsigned int penStatus; /* PEN_UP, PEN_DOWN, PEN_SAMPLE */ TS_RET buf[MAX_TS_BUF]; /* protect against overrun */ unsigned int head, tail; /* head and tail for queued events */ wait_queue_head_t wq; spinlock_t lock;} TS_DEV;static TS_DEV tsdev;#undef IRQ_TC#define IRQ_TC IRQ_EINT5 //IRQ_EINT5#define ADS7843_PIN_CS (1<<12) //GPG12#define ADS7843_PIN_PEN (1<<5) //GPF5#define TS_OPEN_INT() enable_irq(IRQ_TC)#define TS_CLOSE_INT() disable_irq(IRQ_TC)#define GPIO_TC_SPIMISO (GPIO_MODE_ALT0 | GPIO_PULLUP_DIS | GPIO_E11)#define GPIO_TC_SPIMOSI (GPIO_MODE_ALT0 | GPIO_PULLUP_DIS | GPIO_E12)#define GPIO_TC_SPICLK (GPIO_MODE_ALT0 | GPIO_PULLUP_DIS | GPIO_E13)#define GPIO_TC_INTR (GPIO_MODE_ALT0 | GPIO_PULLUP_EN | GPIO_F5)#define GPIO_TC_OUT (GPIO_MODE_OUT | GPIO_PULLUP_EN | GPIO_F5)#ifdef GPIO_XMON#undef GPIO_XMON#endif#define GPIO_XMON (GPIO_MODE_OUT | GPIO_PULLUP_EN | GPIO_G12)#define ADS7843_CTRL_START 0x80#define ADS7843_GET_X 0x50#define ADS7843_GET_Y 0x10#define ADS7843_CTRL_12MODE 0x0#define ADS7843_CTRL_8MODE 0x8#define ADS7843_CTRL_SER 0x4#define ADS7843_CTRL_DFR 0x0#define ADS7843_CTRL_DISPWD 0x3 // Disable power down#define ADS7843_CTRL_ENPWD 0x0 // enable power down#define ADS7843_CMD_X (ADS7843_CTRL_START|ADS7843_GET_X|ADS7843_CTRL_12MODE|ADS7843_CTRL_DFR|ADS7843_CTRL_ENPWD)#define ADS7843_CMD_Y (ADS7843_CTRL_START|ADS7843_GET_Y|ADS7843_CTRL_12MODE|ADS7843_CTRL_DFR|ADS7843_CTRL_ENPWD)#define ADS7843_CMD_START ADS7843_CMD_X#define BUF_HEAD (tsdev.buf[tsdev.head])#define BUF_TAIL (tsdev.buf[tsdev.tail])#define INCBUF(x,mod) ((++(x)) & ((mod) - 1))static int tsMajor = 0;static void (*tsEvent)(void);#define HOOK_FOR_DRAG#ifdef HOOK_FOR_DRAG#define TS_TIMER_DELAY (HZ/100) /* 10 ms */#define TS_TIMER_DELAY1 (HZ/200) /* 5 ms*/static struct timer_list ts_timer;#endifstatic int adc_state = 0;static int x, y; /* touch screen coorinates */static void printRegisters(void){ printk ("GPFCON:%x\tGPFUP:%x\tGPFDAT:%x\n", GPFCON, GPFUP, GPFDAT ); printk ("GPGCON:%x\tGPGUP:%x\tGPGDAT:%x\n", GPGCON, GPGUP, GPGDAT ); printk ("INTMOD:%x\tINTMSK:%x\tINTPND:%x\tSRCPND:%x\n", INTMOD, INTMSK, INTPND, SRCPND); printk ("EXTINT0:%x\tEINTMASK:%x\tEINTPEND:%x\n", EXTINT0, EINTMASK, EINTPEND );}static void printGPE (void){ printk ("GPECON:%x\tGPEUP:%x\tGPEDAT:%x\n", GPECON, GPEUP, GPEDAT );}static void printSPI (void){ printk ("SPPRE0:%d\tSPCON0:%x\tSPSTA0:%x\n", SPPRE0, SPCON0, SPSTA0 ); printk ("SPTDAT0:%x\tSPRDAT0:%x\n", SPTDAT0, SPRDAT0 ); printk ("SPPIN0:%x\n", SPPIN0);}inline static void enable_7843(void){ GPGDAT &= ~ADS7843_PIN_CS;}inline static void disable_7843(void){ GPGDAT |= ADS7843_PIN_CS;}inline static void SPISend ( unsigned char val, int channel ){ if ( channel == 0 ){ while (!(SPSTA0 & 1)); SPTDAT0 = val; }else if ( channel == 1 ){ while (!(SPSTA1 & 1)); SPTDAT1 = val; }else return;}inline static char SPIRecv ( int channel ){ char retv; if (channel == 0){ // SPISend (0xff, 0); while (!(SPSTA0 & 1)); return SPRDAT0; }else if (channel == 1) { // SPISend (0xff, 0); while (!(SPSTA1 & 1)); return SPRDAT1; }else return -1;}inline static void set7843toIRQmode(void){ enable_7843 (); printk ("aaaaaaaaaaa\n"); SPISend (ADS7843_CMD_X, 0); printk ("bbbbbbbbbbbb\n"); SPIRecv (0); printk ("cccccccccccc\n"); SPIRecv (0); printk ("ddddddddddd\n" ); disable_7843 (); printk ("eeeeeeeeeee\n");}static void setSPImode (){ printSPI(); SPPIN0 = 2; SPPRE0 = 33; SPCON0 = SPCON_SMOD_POLL | SPCON_ENSCK | SPCON_MSTR | SPCON_CPOL_HIGH | SPCON_CPHA_FMTA; printSPI();}static void tsEvent_raw(void){ if (tsdev.penStatus == PEN_DOWN) { BUF_HEAD.x = x; BUF_HEAD.y = y; BUF_HEAD.pressure = PEN_DOWN; } else { BUF_HEAD.x = 0; BUF_HEAD.y = 0; BUF_HEAD.pressure = PEN_UP; } tsdev.head = INCBUF(tsdev.head, MAX_TS_BUF); wake_up_interruptible(&(tsdev.wq));}static int tsRead(TS_RET * ts_ret){ spin_lock_irq(&(tsdev.lock)); ts_ret->x = BUF_TAIL.x; ts_ret->y = BUF_TAIL.y; ts_ret->pressure = BUF_TAIL.pressure; tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF); spin_unlock_irq(&(tsdev.lock)); return sizeof(TS_RET);}static ssize_t s3c2410_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){ TS_RET ts_ret; retry: if (tsdev.head != tsdev.tail) { int count; count = tsRead(&ts_ret); if (count) copy_to_user(buffer, (char *)&ts_ret, count); return count; } else { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; interruptible_sleep_on(&(tsdev.wq)); if (signal_pending(current)) return -ERESTARTSYS; goto retry; } return sizeof(TS_RET);}static unsigned int s3c2410_ts_poll(struct file *filp, struct poll_table_struct *wait){ poll_wait(filp, &(tsdev.wq), wait); return (tsdev.head == tsdev.tail) ? 0 : (POLLIN | POLLRDNORM); }static inline void s3c2410_get_XY(void){ unsigned int temp; int flags; local_irq_save(flags); enable_7843(); SPISend(ADS7843_CMD_X, 0); SPISend(0, 0); temp=SPIRecv(0); SPISend(ADS7843_CMD_X, 0); temp<<=8; temp|=SPIRecv(0); x=(temp>>4); SPISend(0, 0); temp=SPIRecv(0); SPISend(ADS7843_CMD_Y, 0); temp<<=8; temp|=SPIRecv(0); x+=(temp>>4); x>>=1; //x=x/2; SPISend(0, 0); temp=SPIRecv(0); SPISend(ADS7843_CMD_Y, 0); temp<<=8; temp|=SPIRecv(0); y=(temp>>4); SPISend(0, 0); temp=SPIRecv(0); SPISend(0, 0); temp<<=8; temp|=SPIRecv(0); y+=(temp>>4); y>>=1; //y=y/2; disable_7843 (); local_irq_restore(flags); //tsdev.penStatus = PEN_DOWN; if(tsdev.penStatus == PEN_DOWN) DPRINTK("PEN DOWN: x: %d, y: %d\n", x, y); else DPRINTK("PEN FLEETING: x: %d, y: %d\n", x, y); tsEvent();#if 0 if (adc_state == 0) { adc_state = 1; disable_ts_adc(); y = (ADCDAT0 & 0x3ff); mode_y_axis(); start_adc_y(); } else if (adc_state == 1) { adc_state = 0; disable_ts_adc(); x = (ADCDAT1 & 0x3ff); tsdev.penStatus = PEN_DOWN; DPRINTK("PEN DOWN: x: %08d, y: %08d\n", x, y); wait_up_int(); tsEvent(); }#endif}static void s3c2410_isr_tc(int irq, void *dev_id, struct pt_regs *reg){ printk ("Touch Screen Interrupt occured\n"); spin_lock_irq(&(tsdev.lock)); printk ("ISR 1\n"); if (tsdev.penStatus == PEN_UP) { int i; TS_CLOSE_INT(); udelay(1); if (( GPFDAT & ADS7843_PIN_PEN) == 0 ) { printk ("low\n"); tsdev.penStatus = PEN_DOWN;#ifdef HOOK_FOR_DRAG ts_timer.expires = jiffies + TS_TIMER_DELAY1; add_timer (&ts_timer);#endif }else{ printk ("High\n"); TS_OPEN_INT(); } } spin_unlock_irq(&(tsdev.lock)); printk ("ISR 2\n");}#ifdef HOOK_FOR_DRAGstatic void ts_timer_handler(unsigned long data){ spin_lock_irq(&(tsdev.lock)); if((GPFDAT & ADS7843_PIN_PEN) == 0 ){ s3c2410_get_XY (); tsdev.penStatus = PEN_FLEETING;#ifdef HOOK_FOR_DRAG ts_timer.expires = jiffies + TS_TIMER_DELAY; add_timer(&ts_timer);#endif }else{ tsdev.penStatus = PEN_UP; del_timer (&ts_timer); DPRINTK ("PEN UP:x:%d,y:%d\n", x, y); tsEvent (); TS_OPEN_INT (); } spin_unlock_irq(&(tsdev.lock));}#endifstatic int s3c2410_ts_open(struct inode *inode, struct file *filp){ tsdev.head = tsdev.tail = 0; tsdev.penStatus = PEN_UP;#ifdef HOOK_FOR_DRAG init_timer(&ts_timer); ts_timer.function = ts_timer_handler;#endif tsEvent = tsEvent_raw; init_waitqueue_head(&(tsdev.wq)); TS_OPEN_INT (); MOD_INC_USE_COUNT; printk ( "ts opened\n"); return 0;}static int s3c2410_ts_release(struct inode *inode, struct file *filp){#ifdef HOOK_FOR_DRAG del_timer(&ts_timer);#endif TS_CLOSE_INT (); MOD_DEC_USE_COUNT; printk ( "ts closed\n"); return 0;}static struct file_operations s3c2410_fops = { owner: THIS_MODULE, open: s3c2410_ts_open, read: s3c2410_ts_read, release: s3c2410_ts_release,#ifdef USE_ASYNC fasync: s3c2410_ts_fasync,#endif poll: s3c2410_ts_poll,};void tsEvent_dummy(void) {}#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_ts_dir, devfs_tsraw;#endifstatic int __init s3c2410_ts_init(void){ int ret; int flags; int delay; unsigned short tmp; local_irq_save (flags); printGPE(); set_gpio_ctrl (GPIO_TC_SPIMISO); set_gpio_ctrl (GPIO_TC_SPIMOSI); set_gpio_ctrl (GPIO_TC_SPICLK); printGPE(); printk( "11111111111111\n"); setSPImode(); printk( "22222222222222\n"); set7843toIRQmode(); printk( "3333333333333\n" ); ret =set_external_irq( IRQ_TC, EXT_LOWLEVEL, /*low level request*/ GPIO_PULLUP_DIS/*poll up*/ ); if (ret) return ret; local_irq_restore (flags); tsEvent = tsEvent_dummy; ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops); if (ret < 0) { printk(DEVICE_NAME " can't get major number\n"); return ret; } tsMajor = ret; /* Enable touch interrupt */ ret = request_irq(IRQ_TC, s3c2410_isr_tc,SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_tc); if (ret) { return ret; } TS_CLOSE_INT();#ifdef CONFIG_DEVFS_FS devfs_ts_dir = devfs_mk_dir(NULL, "touchscreen", NULL); devfs_tsraw = devfs_register(devfs_ts_dir, "0raw", DEVFS_FL_DEFAULT, tsMajor, TSRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR, &s3c2410_fops, NULL);#endif printk (DEVICE_NAME"\tinitialized\n"); return 0;}static void __exit s3c2410_ts_exit(void){#ifdef CONFIG_DEVFS_FS devfs_unregister(devfs_tsraw); devfs_unregister(devfs_ts_dir);#endif unregister_chrdev(tsMajor, DEVICE_NAME); free_irq(IRQ_TC, s3c2410_isr_tc);}module_init(s3c2410_ts_init);module_exit(s3c2410_ts_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -