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

📄 skyeye_ts_drv.c

📁 一个模拟可种嵌入开发环境的模拟软件.能模拟ARM系列等.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 *
 * linux/drivers/char/skyeye_ts.c - Touch screen driver for touch screen simulated on skyeye.
*/

#include <linux/kernel.h>     /* We're doing kernel work */
#include <linux/module.h>     /* Specifically, a module */
#include <linux/interrupt.h>  /* We want interrupts */

#include <linux/miscdevice.h> /* for misc_register() and misc_deregister() */

#include <linux/fs.h>         /* for struct 'file_operations' */

#include <linux/timer.h>     /* for timeout interrupts */
#include <linux/param.h>     /* for HZ. HZ = 100 and the timer step is 1/100 */
#include <linux/sched.h>     /* for jiffies definition. jiffies is incremented
                              * once for each clock tick; thus it's incremented
			      * HZ times per secondes.*/
#include <linux/mm.h>        /* for verify_area */
#include <linux/slab.h>    /* for kmalloc */
#include <linux/init.h>

#include <asm/irq.h>         /* For IRQ_MACHSPEC */

#include <linux/version.h>

/*----------------------------------------------------------------------------*/



//#include "mc68328digi.h" //struct ts_pen_info was defined in this head file
#include "skyeye_ts_drv.h"
#include "ep7312_sys.h"
//#include "clps7110.h"

#define IRQ_FLG_STD   (0x8000)        /* internally used              */

/*----------------------------------------------------------------------------*/

/* Available info from pen position and status */

//struct ts_pen_info {
  //int x,y;    /* pen position                                      */
  //int dx,dy;  /* delta move from last position                     */
  //int event;  /* event from pen (DOWN,UP,CLICK,MOVE)               */
  //int state;  /* state of pen (DOWN,UP,ERROR)                      */
  //int ev_no;  /* no of the event                                   */
  //unsigned long ev_time;  /* time of the event (ms) since ts_open  */
//};


static const char* __file__ = __FILE__;

/*----------------------------------------------------------------------------*//*
 * Kernel compatibility.
 * Kernel > 2.2.3, include/linux/version.h contain a macro for KERNEL_VERSION
 */
#include <linux/version.h>
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c)  (((a) << 16) + ((b) << 8) + (c))
#endif

/*
 * Conditional compilation. LINUX_VERSION_CODE is the code of this version
 * (as per KERNEL_VERSION)
 */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
#include <asm/uaccess.h>    /* for put_user     */
#include <linux/poll.h>     /* for polling fnct */
#endif

/* 
 * Length of the data structure
 */
#define DATA_LENGTH       sizeof(struct ts_pen_info)

/*
 * Size of the buffer for the event queue
 */
#define TS_BUF_SIZE        32*DATA_LENGTH

/*
 * Minor number for the touch screen device. Major is 10 because of the misc 
 * type of the driver.
 */
//#define MC68328DIGI_MINOR    9
#define SKYEYE_TS_MINOR    9
#define SKYEYE_TS_MAJOR    10



/*
 * ADS7843 fields (BURR-BROWN Touch Screen Controller).
 */
#define ADS7843_START_BIT (1<<7)
#define ADS7843_A2        (1<<6)
#define ADS7843_A1        (1<<5)
#define ADS7843_A0        (1<<4)
#define ADS7843_MODE      (1<<3)  /* HIGH = 8, LOW = 12 bits conversion */
#define ADS7843_SER_DFR   (1<<2)  /* LOW = differential mode            */
#define ADS7843_PD1       (1<<1)  /* PD1,PD0 = 11  PENIRQ disable       */
#define ADS7843_PD0       (1<<0)  /* PD1,PD0 = 00  PENIRQ enable        */

/*
 * Conversion status.
 */
#define CONV_ERROR      -1   /* error during conversion flow        */
#define CONV_END         0   /* conversion ended (= pen is up)      */
#define CONV_LOOP        1   /* conversion continue (= pen is down) */

/*
 * Useful masks.
 */
#define PEN_IRQ_NUM	6
//#define PEN_IRQ_NUM	IRQ6_IRQ_NUM

//#define PENIRQ_DATA 	PDDATA
//#define PENIRQ_PUEN	PDPUEN
//#define PENIRQ_DIR	PDDIR
//#define PENIRQ_SEL	PDSEL
//#define ICR_PENPOL	ICR_POL6
//#define IMR_MPEN	IMR_MIRQ6

/*
 * Touch screen driver states.
 */
#define TS_DRV_ERROR       -1
#define TS_DRV_IDLE         0
#define TS_DRV_WAIT         1
#define TS_DRV_ASKX         2
#define TS_DRV_ASKY         3
#define TS_DRV_READX        4
#define TS_DRV_READY        5

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
//#define ENABLE_PEN_IRQ    { INTSR &= ~EINT2; }
//#define DISABLE_PEN_IRQ   { INTSR |= EINT2; }

#define ENABLE_PEN_IRQ    { INTSR |= EINT2; }
#define DISABLE_PEN_IRQ   { INTSR &= ~EINT2; }

/*----------------------------------------------------------------------------*/


/* predefinitions ------------------------------------------------------------*/

static void handle_pen_irq(int irq, void *dev_id, struct pt_regs *regs);

/*----------------------------------------------------------------------------*/
/* structure -----------------------------------------------------------------*/

struct ts_pen_position { int x,y; };

struct ts_queue {
  unsigned long head;
  unsigned long tail;
  wait_queue_head_t proc_list;
  struct fasync_struct *fasync;
  unsigned char buf[TS_BUF_SIZE];
};

/*----------------------------------------------------------------------------*/
/* Variables -----------------------------------------------------------------*/

/*
 * driver state variable.
 */
static int ts_drv_state;

/*
 * first tick initiated at ts_open.
 */
static struct timeval   first_tick;

/*
 * pen state.
 */
static int new_pen_state;

/*
 * event counter.
 */
static int ev_counter;

/*
 * counter to differentiate a click from a move.
 */
static int state_counter;

static struct timer_list         ts_wake_time;

/*
 * drv parameters.
 */
static struct ts_drv_params      current_params;
static int                       sample_ticks;
/*
 * pen info variables.
 */
static struct ts_pen_info        ts_pen;
static struct ts_pen_info        ts_pen_prev;
//static struct ts_pen_position    current_pos;
static struct ts_pen_info    current_pos;
static struct ts_pen_info 	*buff;

/*
 * driver management.
 */
static struct ts_queue *queue;
static int    device_open = 0;   /* number of open device to prevent concurrent
                                  * access to the same device
				  */


/*----------------------------------------------------------------------------*/
/* Init & release functions --------------------------------------------------*/

static void init_ts_state(void) {
  //DISABLE_SPIM_IRQ;      /* Disable SPIM interrupt */

  ts_drv_state = TS_DRV_IDLE;
  state_counter = 0;

  ENABLE_PEN_IRQ;        /* Enable interrupt IRQ5  */
}

static void init_ts_pen_values(void) {
  
}


/*
 * Set default values for the params of the driver.
 */
static void init_ts_settings(void) {
  
}

static void init_ts_hardware(void) {
}

static void init_ts_drv(void) {
  
}

static void release_ts_drv(void) {
 
}

/*----------------------------------------------------------------------------*/
/* xcopilot compatibility hacks ----------------------------------------------*/
#ifdef CONFIG_XCOPILOT_BUGS

/* xcopilot has the following bugs:
 *
 * - Disabling the penirq has no effect; we keep on getting irqs even when
 *   penirq is disabled; this is not too annoying: we just trash pen irq events
 *   that come when disabled.
 *
 * - SPIM interrupt is not simulated; this is not too annoying: we just read
 *   SPI data immediately and bypass a couple of states related to SPI irq.
 *
 * - We do not get mouse drag events; this is a known xcopilot bug.
 *   This is annoying: we miss all moves ! You should patch and recompile
 *   your xcopilot.
 *
 *   This has been reported as Debian bug #64367, and there is a patch there:
 *     http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=64367&repeatmerged=yes
 *   which is:
 *   +-----------------------------------------------------------------------+
 *   | --- display.c   Tue Aug 25 14:56:02 1998
 *   | +++ display2.c  Fri May 19 16:07:52 2000
 *   | @@ -439,7 +439,7 @@
 *   | static void HandleDigitizer(Widget w, XtPointer client_data, XEvent\
 *   | *event, Boolean *continue_to_dispatch)
 *   | {
 *   | -  Time start;
 *   | +  static Time start;
 *   | 
 *   | *continue_to_dispatch = True;
 *   +-----------------------------------------------------------------------+
 *   In short, add 'static' to the declaration of 'start' in HandleDigitizer()
 *   in display.c
 *
 *   With this patch, all works perfectly !
 *
 * - The pen state can be read only in IPR, not in port D; again, we're doing
 *   the workaround.
 *
 * With all these workarounds in this file, and with the patch on xcopilot,
 * things go perfectly smoothly.
 *
 */

/*
 * Ugly stuff to read the mouse position on xcopilot
 *
 * We get the position of the last mouse up/down only, we get no moves !!! :-(
 */
 
static void xcopilot_read_now(void) {
    PFDATA &= ~0xf; PFDATA |= 6;
    SPIMCONT |= SPIMCONT_XCH | SPIMCONT_IRQEN;
    current_pos.x = SPIMDATA;
    rescale_xpos(&current_pos.x);

    PFDATA &= ~0xf; PFDATA |= 9;
    SPIMCONT |= SPIMCONT_XCH | SPIMCONT_IRQEN;
    current_pos.y = SPIMDATA;
    rescale_ypos(&current_pos.y);

    swap_xy(&current_pos.x, &current_pos.y);
}
#endif


//****** by ywc 2004-04-09 ***************
static void skyeye_read_now(void){
	long * TS_Buf_start_addr;
 	
	TS_Buf_start_addr=0xff00b000;
	current_pos.x=TS_Buf_start_addr[0];
	current_pos.y=TS_Buf_start_addr[1];
	current_pos.dx=0;
	current_pos.dy=0;
	current_pos.event=TS_Buf_start_addr[4];
	current_pos.state=0;
	current_pos.ev_no=TS_Buf_start_addr[6];//1--new data come,0--no new data--set by ts_read
	current_pos.ev_time=0;
//	printk("&TS_Buf_start_addr[2]==%p\n",&TS_Buf_start_addr[2]);
//        printk("&TS_Buf_start_addr[3]==%p\n",&TS_Buf_start_addr[3]);
//	printk("ts driver: skyeye_read_now:"); 
//	printk("current_pos.x=%d,current_pos.y=%d\n\n",current_pos.x,current_pos.y);
}
//****** by ywc 2004-04-09 ***************


/*
 * Get one char from the queue buffer.
 * AND the head with 'TS_BUF_SIZE -1' to have the loopback
 */
static unsigned char get_char_from_queue(void) {
  unsigned int result;

  result = queue->buf[queue->tail];
  queue->tail = (queue->tail + 1) & (TS_BUF_SIZE - 1);
  return result;
}

/*
 * Write one event in the queue buffer.
 * Test if there is place for an event = the head cannot be just one event
 * length after the queue.
 */
static void put_in_queue(char *in, int len) {
  unsigned long head    = queue->head;
  unsigned long maxhead = (queue->tail - len) & (TS_BUF_SIZE - 1);
  int i;
  
  if(head != maxhead)              /* There is place for the event */
    for(i=0;i<len;i++) {
      queue->buf[head] = in[i];
      head++;
      head &= (TS_BUF_SIZE - 1);
    }
  //else printk("%0: Queue is full !!!!\n", __file__);
  queue->head = head;
}

/*
 * Test if queue is empty.
 */
static inline int queue_empty(void) {
  return queue->head == queue->tail;
}

/*
 * Test if the delta move of the pen is enough big to say that this is a really
 * move and not due to noise.
 */
static int is_moving(void) {
  int threshold;
  int dx, dy;
  
  threshold=((ts_pen_prev.event & EV_PEN_MOVE) > 0 ?
             current_params.follow_thrs : current_params.mv_thrs);
  dx = current_pos.x-ts_pen_prev.x;
  dy = current_pos.y-ts_pen_prev.y;
  if(dx < 0) dx = -dx; /* abs() */
  if(dy < 0) dy = -dy;
  return (dx > threshold ? 1 :
	  (dy > threshold ? 1 : 0));
}

static void copy_info(void) {
  ts_pen_prev.x = ts_pen.x;
  ts_pen_prev.y = ts_pen.y;
  ts_pen_prev.dx = ts_pen.dx;
  ts_pen_prev.dy = ts_pen.dy;
  ts_pen_prev.event = ts_pen.event;
  ts_pen_prev.state = ts_pen.state;
  ts_pen_prev.ev_no = ts_pen.ev_no;
  ts_pen_prev.ev_time = ts_pen.ev_time;
}

static void cause_event(int conv) {

  switch(conv) {

  case CONV_ERROR: /* error occure during conversion */
    ts_pen.state &= 0;            /* clear */
    ts_pen.state |= ST_PEN_UP;    /* recover a stable state for the drv.      */
    ts_pen.state |= ST_PEN_ERROR; /* tell that the state is due to an error   */
    ts_pen.event = EV_PEN_UP;     /* event = pen go to up */
    ts_pen.x = ts_pen_prev.x;     /* get previous coord as current to by-pass */
    ts_pen.y = ts_pen_prev.y;     /* possible errors                          */
    ts_pen.dx = 0;
    ts_pen.dy = 0;
    ts_pen.ev_no = ev_counter++;    /* get no of event   */
    //ts_pen.ev_time = set_ev_time(); /* get time of event */
    copy_info();                    /* remember info */
    if(current_params.event_queue_on)

⌨️ 快捷键说明

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