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

📄 skyeye_ts_drv.c

📁 一个模拟可种嵌入开发环境的模拟软件.能模拟ARM系列等.
💻 C
📖 第 1 页 / 共 2 页
字号:
      put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */

    /* tell user space progs that a new state occure */
    new_pen_state = 1;
    /* signal asynchronous readers that data arrives */
    if(queue->fasync)
      kill_fasync(&queue->fasync, SIGIO, POLL_IN);
    wake_up_interruptible(&queue->proc_list);  /* tell user space progs */
    break;
    
  case CONV_LOOP:  /* pen is down, conversion continue */    
    ts_pen.state &= 0;          /* clear */
    ts_pen.state &= ST_PEN_DOWN;

    switch(state_counter) {       /* It could be a move   */
	    
    case 1:    /* the pen just went down, it's a new state */
      ts_pen.x = current_pos.x;
      ts_pen.y = current_pos.y;
      ts_pen.dx = 0;
      ts_pen.dy = 0;
      ts_pen.event = EV_PEN_DOWN;      /* event = pen go to down */
      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)
        put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */

      /* tell user space progs that a new state occure */
      new_pen_state = 1;
      /* signal asynchronous readers that data arrives */
      if(queue->fasync)
        kill_fasync(&queue->fasync, SIGIO, POLL_IN);
      wake_up_interruptible(&queue->proc_list);  /* tell user space progs */
      break;

    case 2:    /* the pen is down for at least 2 loop of the state machine */

      if(is_moving()) {
        ts_pen.event = EV_PEN_MOVE;
        ts_pen.x = current_pos.x;
        ts_pen.y = current_pos.y;
        ts_pen.dx = ts_pen.x - ts_pen_prev.x;
        ts_pen.dy = ts_pen.y - ts_pen_prev.y;
        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)
          put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */

        /*
	 * pen is moving, then it's anyway a good reason to tell it to
	 * user space progs
	 */
        new_pen_state = 1;
        /* signal asynchronous readers that data arrives */
        if(queue->fasync)
          kill_fasync(&queue->fasync, SIGIO, POLL_IN);
        wake_up_interruptible(&queue->proc_list);
      }
      else {
        if(ts_pen_prev.event == EV_PEN_MOVE)  /* if previous state was moving */
	  ts_pen.event = EV_PEN_MOVE;         /* -> keep it!                  */
        ts_pen.x = ts_pen_prev.x;       /* No coord passing to     */
        ts_pen.y = ts_pen_prev.y;       /* avoid Parkinson effects */
        ts_pen.dx = 0;
	ts_pen.dy = 0;  /* no wake-up interruptible because nothing new */
        copy_info();    /* remember info */
      }
      break;
    }
    break;

  case CONV_END:   /* pen is up, conversion ends */
    ts_pen.state &= 0;         /* clear */
    ts_pen.state |= ST_PEN_UP;
    ts_pen.event = EV_PEN_UP;
    ts_pen.x = current_pos.x;
    ts_pen.y = current_pos.y;
    ts_pen.dx = ts_pen.x - ts_pen_prev.x;
    ts_pen.dy = ts_pen.y - ts_pen_prev.y;
  //  ts_pen.ev_time = set_ev_time();  /* get time of event */
    ts_pen.ev_no = ev_counter++;     /* get no of event   */
    copy_info();                     /* remember info */
    if(current_params.event_queue_on)
      put_in_queue((char *)&ts_pen,DATA_LENGTH);  /* queue event */

    /* tell user space progs that a new state occure */
    new_pen_state = 1;
    /* signal asynchronous readers that data arrives */
    if(queue->fasync)
      kill_fasync(&queue->fasync, SIGIO, POLL_IN);
    wake_up_interruptible(&queue->proc_list);
    break;
  }
}


/*----------------------------------------------------------------------------*/
/* Interrupt functions -------------------------------------------------------*/

/*
 * pen irq.
 */
static void handle_pen_irq(int irq, void *dev_id, struct pt_regs *regs) {
  unsigned long flags;
  int bypass_initial_timer = 0;

  /* if unwanted interrupts come, trash them */ 
  if(!device_open)
    return;

  //PENIRQ_DATA &= ~PEN_MASK;
/* - 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.
 */
  // printk("enter the pen irq ,INTSR=%x",INTSR);
   if(!(INTSR&EINT2)) {
    return;
  }

  save_flags(flags);     /* disable interrupts */
  cli();
  
  skyeye_read_now(); //ywc 2004-04-11

  switch(ts_drv_state) {

  case TS_DRV_IDLE:  
 //   DISABLE_PEN_IRQ;
 //   ts_drv_state++;      /* update driver state */
//    if(current_params.deglitch_on)
//      set_timer_irq(&ts_wake_time,sample_ticks);
//    else
 //     bypass_initial_timer = 1;
    break;

  default: /* Error */
    /* PENIRQ is enable then just init the driver 
     * Its not necessary to pull down the busy signal
     */
 //   init_ts_state();
    break;
  } 
  DISABLE_PEN_IRQ;   
  restore_flags(flags);  /* Enable interrupts */
  

}

/*----------------------------------------------------------------------------*/
/* file_operations functions -------------------------------------------------*/

/*
 * Called whenever a process attempts to read the device it has already open.
 */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
static ssize_t ts_read (struct file *file,
                        char *buff0,       /* the buffer to fill with data */
			size_t len,      /* the length of the buffer.    */
			loff_t *offset) { /* Our offset in the file       */
#else
static int ts_read(struct inode *inode, struct file *file,
		   char *buff0,            /* the buffer to fill with data */
		   int len) {             /* the length of the buffer.    */
		                          /* NO WRITE beyond that !!!     */
#endif

  char *p_buffer;
  char c;
  int  i;
  int  err;
  int  havedata=0;
  // printk("!!!enter ts_read\n");
 /*
  while(!current_pos.state) {   //no new data come
    if(file->f_flags & O_NONBLOCK)
      return -EAGAIN;
    interruptible_sleep_on(&queue->proc_list);
  
#if (LINUX_VERSION_CODE >= 0x020100)
    if(signal_pending(current))
#else
    if(current->signal & ~current->blocked)  // a signal arrived 
#endif
      return -ERESTARTSYS;    //tell the fs layer to handle it  
    // otherwise loop 
 }
*/

  /* Force length to the one available */
  len = DATA_LENGTH;

  /* verify that the user space address to write is valid */
 
 err = verify_area(VERIFY_WRITE,buff0,len);
  if (err) {
    printk("verify_area error ,err=%d",err);
    return err;
  }
 
  /*
  for(i=0;i<len;i++){
  buff[i]=*((char *)&current_pos+i);
  }
  */
    //another copy way???
   // struct ts_pen_info * buff;
 if(current_pos.ev_no==1){
  buff=(struct ts_pen_info *)buff0;
  buff->x = current_pos.x;
  buff->y = current_pos.y;
  buff->dx = current_pos.dx;
  buff->dy = current_pos.dy;
  buff->event = current_pos.event;
  buff->state = current_pos.state;
  buff->ev_no = current_pos.ev_no;
  buff->ev_time = current_pos.ev_time;
  
//  printk("current_pos.x=%d,buff->x=%d\n",current_pos.x,buff->x);
//  printk("current_pos.y=%d,buff->y=%d\n",current_pos.y,buff->y);
  
  havedata=1;
  }

  current_pos.ev_no=0;// ywc 2004-04-12 data have been read ,set it to 0
//  printk("!!!leave ts_read\n");
  return havedata;

}

		    
/*
 * Called whenever a process attempts to open the device file.
 */
static int ts_open(struct inode *inode, struct file *file) {
     int err;
  /* To talk to only one device at a time */
  printk("!!!enter ts_open\n");
  if(device_open) return -EBUSY;

  /* IRQ registration have to be done before the hardware is instructed to
   * generate interruptions.
   */
  /* IRQ for pen */
  err = request_irq(PEN_IRQ_NUM, handle_pen_irq,
		    IRQ_FLG_STD,"touch_screen",NULL);
  if(err) {
    printk("%s: Error. Cannot attach IRQ %d to touch screen device\n",
	   __file__, PEN_IRQ_NUM);
    return err;
  }
  printk("%s: IRQ %d attached to touch screen\n",
	 __file__, PEN_IRQ_NUM);

  init_ts_drv();
  
  printk("skyeye touch screen driver: init hardware done..\n\n");

  /* Init the queue */
  queue = (struct ts_queue *) kmalloc(sizeof(*queue),GFP_KERNEL);
  memset(queue,0,sizeof(*queue));
  queue->head = queue->tail = 0;
  init_waitqueue_head(&queue->proc_list);

  /* Increment the usage count (number of opened references to the module)
   * to be sure the module couldn't be removed while the file is open.
   */
  MOD_INC_USE_COUNT;

  /* And my own counter too */
  device_open++;
  //ts_read(0,0,0,0);
  //file->f_op->read(1,1,1,1);
  
  return 0;  /* open succeed */
}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
static int ts_fasync(int inode, struct file *file, int mode) {
#else
static int ts_fasync(struct inode *inode, struct file *file, int mode) {
#endif
  
  int retval;
  
  retval = fasync_helper(inode,file,mode,&queue->fasync);
  if(retval < 0)
    return retval;
    
  return 0;
  
}

/*
 * Called whenever a process attempts to close the device file.
 */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
static int ts_release(struct inode *inode, struct file *file) {
#else
static void ts_release(struct inode *inode, struct file *file) {
#endif

  /* Remove this file from the asynchronously notified file's */
  ts_fasync(inode,file,0);

  /* Release hardware */
  release_ts_drv();

  /* Free the allocated memory for the queue */
  kfree(queue);

  /* IRQ have to be freed after the hardware is instructed not to interrupt
   * the processor any more.
   */
  //free_irq(SPI_IRQ_NUM,NULL);
  free_irq(PEN_IRQ_NUM,NULL);

  /* Decrement the usage count, otherwise once the file is open we'll never
   * get rid of the module.
   */
  MOD_DEC_USE_COUNT;

  /* And my own counter too */
  device_open--;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
  return 0;
#endif
}


static struct file_operations ts_fops = {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
  owner:          THIS_MODULE,
  read:           ts_read,
  //poll:           ts_poll,
  //ioctl:          ts_ioctl,
  open:           ts_open,
  release:        ts_release,
  fasync:         ts_fasync,
#else

  NULL,       /* lseek              */
  ts_read,    /* read               */
  NULL,       /* write              */
  NULL,       /* readdir            */
#  if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
  ts_poll,    /* poll               */
#  else
  ts_select,  /* select             */
#  endif
  ts_ioctl,   /* ioctl              */
  NULL,       /* mmap               */
  ts_open,    /* open               */
#  if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
  NULL,       /* flush              */
#  endif
  ts_release, /* release (close)    */
  NULL,       /* fsync              */
  ts_fasync   /* async notification */

#endif
};

/*
 * miscdevice structure for misc driver registration.
 */
static struct miscdevice mc68328_digi = {
//  MC68328DIGI_MINOR,"mc68328 digitizer",&ts_fops
  SKYEYE_TS_MINOR,"skyeye touch screen",&ts_fops
};

/*
 * Initialize the driver.
 */
static int __init mc68328digi_init(void) {
  int err;
  
  int ts;

  printk("%s: SkyEye touch screen driver initialize\n", __file__);

  /* Register the misc device driver */
  err = misc_register(&mc68328_digi);
 if(err<0)
    printk("%s: Error registering the device\n", __file__);  
 else
    printk("%s: Device register with name: %s and number: %d %d\n",
	   __file__, mc68328_digi.name, SKYEYE_TS_MAJOR, mc68328_digi.minor);

  /* Init prameters settings at boot time */
  init_ts_settings();
//*******************  test by ywc 2004-3-27 *****************
     /*
     * open up the touch-panel device.
     * Return the fd if successful, or negative if unsuccessful.
     */
/*  opened by application on ts_driver!
    ts = ts_open("/dev/ts", O_NONBLOCK | O_RDWR);
    if (ts < 0) {
        printk("Error opening touch panel\n");
        return ts;
    }
*/
//*******************  test by ywc 2004-3-27 *****************


  return err;     /* A non zero value means that init_module failed */
}

/*
 * Cleanup - undid whatever mc68328digi_init did.
 */
void mc68328digi_cleanup(void) {
  /* Unregister device driver */
  misc_deregister(&mc68328_digi);
}  

module_init(mc68328digi_init);
module_exit(mc68328digi_cleanup);

⌨️ 快捷键说明

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