VM-RedHat 9.0
Board: fl2440, linux-2.6.12
Arm-Linux-GCC: 3.4.1
Line 1 in the Code. If drag is not supported, you can obtain the stroke coordinates, but the icons on the LCD do not respond. I do not know why.
# Include <Linux/config. h> # include <Linux/module. h> # include <Linux/moduleparam. h> # include <Linux/kernel. h> # include <Linux/sched. h> # include <Linux/init. h> # include <Linux/device. h> # include <Linux/miscdevice. h> # include <Linux/delay. h> # include <Linux/poll. h> # include <Linux/spinlock. h> # include <Linux/interrupt. h> # include <Linux/delay. h> # include <Linux/devfs_fs_kernel.h> # include <ASM/hardware/clock. h> # Inc Lude <ASM/hardware. h> # include <ASM/Io. h> # include <ASM/ARCH/regs-gpio.h> // ym_sen output drive enabling, xp_sen, yp_sen output drive disabling // s3c2410_adctsc_xy_pst (3) -- manual measurement in the X and Y directions, waiting for interruption mode // x = 0. Set adctsc [8] to 0, that is, to detect the disconnection signal falling from the pen tip # define wait4int (x) <8) | \ Users | users | s3c2410_adctsc_xp_sen | \ s3c2410_adctsc_xy_pst (3)/* adctsc register bits */# define s3c2410_adctsc_ym_sen (1 <7) # define S3C2410 _ Adctsc_yp_sen (1 <6) # define s3c2410_adctsc_xm_sen (1 <5) # define s3c2410_adctsc_xp_sen (1 <4) # define condition (1 <3) # define s3c2410_adctsc_auto_pst (1 <2) # define s3c2410_adctsc_xy_pst (x) & 0x3) <0) /* adccon register bits */# define partition (1 <15) # define s3c2410_adccon_prscen (1 <14) # define s3c2410_adccon_prscvl (x) & 0xff) <6) # define s3c2410_adccon_prscvlmask (0xff <6) # define s3c2410_adccon_selmux (x) & 0x7) <3) # define s3c2410_adccon_muxmask (0x7 <3) # define s3c2410_adccon_stdbm (1 <2) # define s3c2410_adccon_read_start (1 <1) # define partition (1 <0) # define s3c2410_adccon_startmask (0x3 <0) # ifdef s3c2410_adccon # UNDEF s3c2410_adccon # endif # ifdef s3c2410_adctsc # UNDEF s3c2410_adctsc # endif # ifdef s3c2410_adcdly # UNDEF s3c2410_adcdly # endif # ifdef s3c2410 _ Dcdat0 # UNDEF handler # endif # ifdef handler # UNDEF handler # endif # ifdef s3c2410_pa_adc # UNDEF s3c2410_pa_adc # endif # define s3c2410_pa_adc (0x58000000) Static void _ iomem * base_addr; # define s3c2410_adccon (base_addr + (0x00) # define s3c2410_adctsc (base_addr + (0x04) # define s3c2410_adcdly (base_addr + (0x08 )) # define s3c2410_adcdat0 (base_addr + (0x0c) # define s3c2410_adcdat1 (base_addr + (0x10) # ifdef config_pm # include <Linux/PM. h> # endif // drag is supported. // If drag is not supported, the pen stroke coordinates can be obtained, but the icons on the LCD do not respond. // You can see that the read interface is called, and the icon does not respond. # Define release // # definedebug # ifdef debug # define dprintkprintk # else # define dprintk # endiftypedef struct {unsigned short pressure; unsigned short X; unsigned short Y; unsigned short pad ;} ts_ret; typedef struct {int XScale; int xtrans; int yscale; int ytrans; int xyswap;} ts_cal; # define pen_up 0 # define pen_down1 # define pen_fleeting2 # define max_ts_buf16/* How many do we want to buffer */# UNDEF Use_async # define device_name "s3c2410-ts" # define tsraw_minor1typedef 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; # ifdef use_asyncstruct fasync_struct * AQ; # endif # ifdef config_pmstruct pm_dev * pm_dev; # endif} ts_dev; static ts_dev TSD Ev; # 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); # ifdef hook_for_drag # define ts_timer_delay (Hz/100)/* 10 MS */static struct timer_list ts_timer; # endif // pick-up regs Val from 2.4.18 & 2440 // ym_sen output drive enabled, XP pull enabled, normal ADC conversion, detect pen tip drop interrupt signal, waiting for interruption mode # define wait_down_int () _ raw_write L (0x000000d3, s3c2410_adctsc) // ym_sen output drive enabling, XP pull-up enabling, normal ADC conversion, detection pen tip lifting interrupt signal, waiting for interrupt mode # define wait_up_int () _ raw_writel (0x000001d3, s3c2410_adctsc) // xm_sen, xp_sen output drive enabled, XP pull disabled, normal ADC conversion, X Direction Measurement Mode # define mode_x_axis () _ raw_writel (0x00000069, s3c2410_adctsc) // equivalent to _ raw_writel (0x00000068, s3c2410_adctsc), that is, // xm_sen, yp_sen enabling, XP pulling prohibited, normal ADC conversion, no operation mode # define mode_x_axis_n () _ raw_writel (xp_extvlt | xm_gnd | yp_ain | ym _ Hiz | \ xp_pull_up_dis | xp_pst (nop_mode), s3c2410_adctsc) // ym_sen, yp_sen enabled, XP disabled, normal ADC conversion, y Direction Measurement Mode # define mode_y_axis () _ raw_writel (0x0000009a, s3c2410_adctsc) // _ raw_writel (0x00007ffa, s3c2410_adccon); -- A/D converter pre-divider enabling, pre-division value 0xff, simulate that the input channel sel_mux is XP and works in normal mode, enabling read start operations // _ raw_readl (s3c2410_adcdat0); -- read the value of adcdat # define start_adc_x () do {__ raw_writel (0x00007ffa, s3c2410_adccon); \__ raw_readl (s3c2410_adcd At0);} while (0) // how is the configuration the same as start_adc_x? Should it be 0x00007fea? # Define start_adc_y () Do {__ raw_writel (0x00007ffa, s3c2410_adccon); \__ raw_readl (s3c2410_adcdat1);} while (0) // prohibit read start operations, that is, read_start position 0 # define disable_ts_adc () _ raw_writel (_ raw_readl (s3c2410_adccon) & 0 xfffffffd, s3c2410_adccon) Static int adc_state = 0; static int X, Y; /* Touch Screen coorinates */# ifdef hook_for_drag # definert_bt_emu_tm (HZ> 1) + (HZ> 2) // 0.75 S // static 2010ts_r_x [5]; // static 2010ts_r _ Y [5]; // static services_r_idx; // static services_r_beg; static u32 dn_start; # endifstatic void tsevent_raw (void) {dprintk ("@ tvevent_raw () @ \ n"); If (tsdev. penstatus = pen_down) {// 2010i, J; # ifdef hook_for_drag latency = jiffies + ts_timer_delay; add_timer (& ts_timer); # Signature = x; buf_head.y = y; # ifdef hook_for_drag buf_head.pressure = (jiffies-dn_start)> = rt_bt_emu_tm)? Pen_fleeting: pen_down; # else buf_head.pressure = pen_down; # endif}/* If (tsdev. penstatus = pen_down) */else {# ifdef hook_for_drag del_timer (& ts_timer); # endifbuf_head.x = x; buf_head.y = y; buf_head.pressure = pen_up;} ts. head = incbuf (tsdev. head, max_ts_buf); dprintk ("@ wake_up_interruptible () in tvevent_raw () @ \ n "); wake_up_interruptible (& (tsdev. WQ); # ifdef use_asyncif (tsdev. AQ) Kill _ Fasync (& (tsdev. AQ), sigio, poll_in); # endif # ifdef config_pmpm_access (tsdev. pm_dev); # endif} 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, S Ize_t count, loff_t * PPOs) {ts_ret; retry: If (tsdev. Head! = Tsdev. tail) {int count; Count = tsread (& ts_ret); If (count) {printk ("@ ts_ret.x: % HD, ts_ret.y: % HD @ \ n ", ts_ret.x, ts_ret.y); 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);} # ifdef use_asyncstatic int S3C2410 _ Ts_fasync (int fd, struct file * filp, int mode) {return fasync_helper (FD, filp, mode, & (tsdev. AQ) ;}# endifstatic 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 start_ts_adc (void) {adc_state = 0; mode_x_axis (); start_adc_x ();} static inline void s3c2410_get_xy (void) {If (adc_state = 0) {adc_state = 1; disable_ts_adc (); y = _ raw_readl (s3c2410_adcdat1) & 0x3ff; // X: f04 Y: f0e DH by PHT. mode_y_axis (); start_adc_y ();} else if (adc_state = 1) {adc_state = 0; disable_ts_adc (); X = _ raw_readl (s3c2410_adcdat0) & 0x3ff; // y: F 04 x: f0e DH by PHT. printk ("@ pen down: X: % d, Y: % d \ n", x, y); wait_up_int (); tsdev. penstatus = pen_down; tsevent () ;}} static irqreturn_t s3c2410_isr_adc (int irq, void * dev_id, struct pt_regs * REG) {dprintk ("@ s3c2410_isr_adc () @ \ n"); spin_lock_irq (& (tsdev. lock); If (tsdev. penstatus = pen_up) {dprintk ("@ s3c2410_isr_adc 1 @ \ n"); s3c2410_get_xy () ;}# ifdef hook_for_drage LSE {dprintk ("@ s3c2410_isr_adc 2 \ n"); s3c2410_get_xy () ;}# endifspin_unlock_irq (& (tsdev. lock); Return irq_handled;} static irqreturn_t s3c2410_isr_tc (int irq, void * dev_id, struct pt_regs * REG) {dprintk ("@ s3c2410_isr_tc () \ n "); spin_lock_irq (& (tsdev. lock); If (tsdev. penstatus = pen_up) {dprintk ("@ s3c2410_isr_tc 1 \ n"); # ifdef hook_for_drag dn_start = jiffies; // Add By gzliu # endif start_ts_adc ();} else {tsdev. penstatus = pen_up; dprintk ("@ s3c2410_isr_tc 2 \ n "); printk ("@ pen up: X: % d, Y: % d @ \ n", x, y ); wait_down_int (); tsevent ();} spin_unlock_irq (& (tsdev. lock); Return irq_handled;} # ifdef hook_for_dragstatic void ts_timer_handler (unsigned long data) {spin_lock_irq (& (tsdev. lock); If (tsdev. penstatus = pen_down) {start_ts_adc ();} s Pin_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; # endiftsevent = tsevent_raw; outputs (& (tsdev. WQ); // mod_inc_use_count; return 0;} static int s3c2410_ts_release (struct inode * inode, struct file * filp) {# I Fdef evaluate (& ts_timer); # endif // success; return 0;} static struct file_operations s3c2410_fops = {owner: this_module, open: s3c2410_ts_open, read: s3c2410_ts_read, release: success, # ifdef identifier: s3c2410_ts_fasync, # endifpoll: identifier,}; void tsevent_dummy (void) {}# ifdef config_pmstatic int identifier (struct pm_dev * pm_dev, pm_request_t req, void * Data) {Switch (req) {Case pm_suspend: tsevent = tsevent_dummy; break; Case pm_resume: tsevent = tsevent_raw; wait_down_int (); break;} return 0 ;} # endifstatic struct CLK * adc_clock; static int _ init s3c2410ts_probe (struct device * Dev) {int ret; tsevent = tsevent_dummy; dprintk ("@ s3c2410ts_probe @ \ n"); ret = register_chrdev (0, device_name, & s3c2410_fops); If (Ret <0) {printk (device_name "Can't get major number \ n"); return ret;} tsmajor = ret; adc_clock = clk_get (null, "ADC"); If (! Adc_clock) {printk (kern_err "failed to get ADC clock source \ n"); Return-enoent;} clk_use (adc_clock); clk_enable (adc_clock); base_addr = ioremap (callback, 0x20) ;__ raw_writel (wait4int (0), s3c2410_adctsc) ;__ raw_writel (30000, latency); // 30000 -- 20000ret = request_irq (irq_adc, s3c2410_isr_adc, temperature, device_name, s3c2410_isr_adc); If (RET) goto adc_failed; ret = request_irq (irq_tc, s3c241 0_isr_tc, sa_interrupt, device_name, s3c2410_isr_tc); If (RET) goto tc_failed;/* Wait for touch screen interrupts */wait_down_int "); values (mkdev (tsmajor, tsraw_minor), s_ifchr | s_irugo | s_iwusr, "touchscreen/% s", "0raw"); # endif # ifdef values = pm_register (values, pm_user_input, s3c2410_ts_pm_callback); # endifreturn 0; tc_fai Led: {printk (kern_err "TC failed !!!!!!!!!!!!! \ N "); free_irq (irq_adc, s3c2410_isr_adc);} adc_failed: {printk (kern_err" ADC failed !!!!!!!!!!!!! \ N "); return ret ;}} static struct device_driver s3c2410ts_driver = {. name = device_name ,. bus = & platform_bus_type ,. probe = s3c2410ts_probe, # ifdef config_pm.suspend = s3c2410ts_suspend ,. resume = s3c2410ts_resume, # endif}; static int _ init s3c2410ts_init (void) {int ret; printk ("@ s3c2410ts Init () @ \ n "); ret = driver_register (& s3c2410ts_driver); If (RET) {printk (" register % s driver failed, return code is % d \ n ", device_name, RET);} else {printk (" @ register % s driver success, return code is % d @ \ n ", device_name, RET);} return ret;} static void _ exit s3c2410ts_exit (void) {# ifdef config_devfs_fsdevfs_remove ("touchscreen/% d", 0); devfs_remove ("touchscreen"); # outputs (tsmajor, device_name); # ifdef config_pmpm_unregister (tsdev. pm_dev); # convert (irq_adc, short); free_irq (irq_tc, short); driver_unregister (& s3c2410ts_driver);} module_init (s3c2410ts_init); module_exit (s3c2410ts_exit );