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

📄 mou_harrier.c

📁 一个linux下的根文件系统的源码
💻 C
字号:
/* * Microwindows touch screen driver for NEC Harrier Demo Board. * * Copyright (c) 2000 Century Software Embedded Technologies * * Requires /dev/tpanel kernel device driver for the VRC4173 chip  */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <math.h>#include <sys/ioctl.h>#include <linux/tpanel.h>#include "device.h"#include "mou_tp.h"/* Very basic handling for the touch panel *//* Mostly borrowed from mou_ipaq.c which I believe was mostly *//* borrowed from mou_tp.c *//* Define this if you want to use the filter instead of the average method *//* #define USE_FILTER *//* Defines used throughout */#define TP_STATUS_HARDDATALOST 0x1000#define TP_STATUS_SOFTDATALOST 0x2000#define TP_STATUS_PENCONTACT   0x4000#define TP_STATUS_DATAVALID    0x8000/* Fix these when we know the right size */#define TP_MIN_X_SIZE          291#define TP_MIN_Y_SIZE          355#define TP_MAX_X_SIZE          3839#define TP_MAX_Y_SIZE          3711#define DATA_STATUS  0#define DATA_YPLUS   1#define DATA_YMINUS  2#define DATA_XPLUS   3#define DATA_XMINUS  4#define DATA_Z       5#ifdef USE_FILTER#define MOU_SAMPLE_RATE   1#else#define MOU_SAMPLE_RATE   10#endif#define MOU_READ_INTERVAL 5000  /* Data format (from kernel driver): */  /* unsigned short status */  /* unsigned short x+ (raw) */  /* unsigned short x- (raw) */  /* unsigned short y+ (raw) */  /* unsigned short y- (raw) */  /* unsigned short z (presssure, raw) */static int pd_fd = -1;int enable_pointing_coordinate_transform = 1;static TRANSFORMATION_COEFFICIENTS tc;#ifndef TESTextern SCREENDEVICE scrdev;#endif#ifdef TEST#undef EPRINTF#undef DPRINTF#define EPRINTF printf#define DPRINTF printf#endif int GetPointerCalibrationData(void){	/*	 * Read the calibration data from the calibration file.	 * Calibration file format is seven coefficients separated by spaces.	 */	/* Get pointer calibration data from this file */	const char cal_filename[] = "/etc/pointercal";	int items;	FILE* f = fopen(cal_filename, "r");	if ( f == NULL )	{		EPRINTF("Error %d opening pointer calibration file %s.\n",			errno, cal_filename);		EPRINTF("Please type \"/usr/bin/tpcal > %s\" to calibrate\n",			cal_filename);		return -1;	}	items = fscanf(f, "%d %d %d %d %d %d %d",		&tc.a, &tc.b, &tc.c, &tc.d, &tc.e, &tc.f, &tc.s);	if ( items != 7 )	{		EPRINTF("Improperly formatted pointer calibration file %s.\n",			cal_filename);		return -1;	}#if TEST		EPRINTF("a=%d b=%d c=%d d=%d e=%d f=%d s=%d\n",			tc.a, tc.b, tc.c, tc.d, tc.e, tc.f, tc.s);#endif	return 0;}inline MWPOINT DeviceToScreen(MWPOINT p){	/*	 * Transform device coordinates to screen coordinates.	 * Take a point p in device coordinates and return the corresponding	 * point in screen coodinates.	 * This can scale, translate, rotate and/or skew, based on the	 * coefficients calculated above based on the list of screen	 * vs. device coordinates.	 */	static MWPOINT prev;	/* set slop at 3/4 pixel */	const short slop = TRANSFORMATION_UNITS_PER_PIXEL * 3 / 4;	MWPOINT new, out;	/* transform */	new.x = (tc.a * p.x + tc.b * p.y + tc.c) / tc.s;	new.y = (tc.d * p.x + tc.e * p.y + tc.f) / tc.s;	/* hysteresis (thanks to John Siau) */	if ( abs(new.x - prev.x) >= slop )		out.x = (new.x | 0x3) ^ 0x3;	else		out.x = prev.x;	if ( abs(new.y - prev.y) >= slop )		out.y = (new.y | 0x3) ^ 0x3;	else		out.y = prev.y;	prev = out;	return out;}static int PD_Open(MOUSEDEVICE *pmd){  struct scanparam s;  int settle_upper_limit;  int result;    /* Open the device */  pd_fd = open("/dev/tpanel", O_NONBLOCK);    if (pd_fd < 0)    {      EPRINTF("Error %d opening touch panel\n", errno);      return -1;    }  s.interval = MOU_READ_INTERVAL;  /*   * Upper limit on settle time is approximately (scan_interval / 5) - 60   * (5 conversions and some fixed overhead)   * The opmtimal value is the lowest that doesn't cause significant   * distortion.   */  settle_upper_limit = (s.interval / 5) - 60;  s.settletime = settle_upper_limit * 50 / 100;  result = ioctl(pd_fd, TPSETSCANPARM, &s);  if ( result < 0 )    EPRINTF("Error %d, result %d setting scan parameters.\n",	    result, errno);    if (enable_pointing_coordinate_transform)    {       if (GetPointerCalibrationData() < 0)	{	  close(pd_fd);	  return -1;	}    }    /* We choose not to hide the cursor for now, others may want to */  #ifdef NOTUSED#ifndef TEST    /* Hide the cursor */  GdHideCursor(&scrdev);#endif#endif    return(pd_fd);}static void PD_Close(void){ 	/* Close the touch panel device. */	if (pd_fd >= 0)		close(pd_fd);	pd_fd = -1;}static int PD_GetButtonInfo(void){ 	/* get "mouse" buttons supported */	return MWBUTTON_L;}static void PD_GetDefaultAccel(int *pscale,int *pthresh){	/*	 * Get default mouse acceleration settings	 * This doesn't make sense for a touch panel.	 * Just return something inconspicuous for now.	 */	*pscale = 3;	*pthresh = 5;}#define MAX_DEVICE_READS 10static int read_tp(unsigned short *x, unsigned short *y, 		   unsigned short *z, int *b, unsigned short *status, unsigned char block){  unsigned char read_count = 0;  unsigned short tempx, tempy;  int bytes_read;  unsigned short data[6];    /* Uh, oh -- The driver is slow and fat, so we get lots of EAGAINS between   */  /* reads.  Thats never good.  So we loop here for some count before we bail  */  while(read_count < MAX_DEVICE_READS)    {      bytes_read = read(pd_fd, data, sizeof(data));        if (bytes_read != sizeof(data))	{	  if (errno != EAGAIN)	    {	      EPRINTF("Error reading touch panel.  errno = %d\n", errno);	      return(errno);	    }	  if (block)	    {	      if (read_count++ == MAX_DEVICE_READS)		return(EAGAIN);	      else		usleep(MOU_READ_INTERVAL / MAX_DEVICE_READS);	    }	  else	    return(EAGAIN);	}      else	break;    }  tempx = data[DATA_XPLUS];  tempy = data[DATA_YPLUS];  /* Sanity check */  /* This is based on measured values.  Occassionally, we get a bad read from the board */  /* This is to ensure that really wacked out reads don't get through.                  */  if ((data[DATA_STATUS] & TP_STATUS_DATAVALID) == TP_STATUS_DATAVALID)    {       if (enable_pointing_coordinate_transform)	 {	   if (tempx < TP_MIN_X_SIZE || tempx > TP_MAX_X_SIZE)	     {#ifdef TEST	       EPRINTF("Got an out of range X value.  X=%d,Y=%d,B=%d\n",		       tempx, tempy, 		       ((data[DATA_STATUS] & TP_STATUS_PENCONTACT) ? MWBUTTON_L : 0));#endif	       return(EAGAIN);	     }	   	   if (tempy < TP_MIN_Y_SIZE || tempy > TP_MAX_Y_SIZE)	     {#ifdef TEST	       EPRINTF("Got an out of range Y value.  X=%d,Y=%d,B=%d\n",		       tempx, tempy, 		       ((data[DATA_STATUS] & TP_STATUS_PENCONTACT) ? MWBUTTON_L : 0));#endif	       return(EAGAIN);	     }	 }       *x = tempx;       *y = tempy;       *z = data[DATA_Z];    }  else    {       *x = 0;      *y = 0;      *z = 0;    }  *b = ((data[DATA_STATUS] & TP_STATUS_PENCONTACT) ? MWBUTTON_L : 0);    *status = data[DATA_STATUS];  return(0);}static int PD_Read(MWCOORD *px, MWCOORD *py, MWCOORD *pz, int *pb){#ifdef USE_FILTER  /* Filter stuff borrowed from mou_tp.c */  const int iir_shift_bits = 3;  const int iir_sample_depth = (1 << iir_shift_bits);    static int iir_accum_x = 0;  static int iir_accum_y = 0;  static int iir_accum_z = 0;  static int iir_count = 0;#else  double cx, cy, cz;#endif  /* Other local variables */  MWPOINT transformed;  int err = 0;  unsigned short samples = 0;  unsigned short xpos = 0;  unsigned short ypos = 0;  unsigned short zpos = 0;  unsigned short status = 0;  *pb = 0;  *px = 0;  *py = 0;  *pz = 0;#ifndef USE_FILTER  cx = 0;  cy = 0;  cz = 0;#endif  if ((err = read_tp(&xpos, &ypos, &zpos, pb, &status, 0)))    {      if (err == EAGAIN)	return(0);      else	return(1);    }  /* Check the status of the button */  if ( (status & TP_STATUS_DATAVALID) != TP_STATUS_DATAVALID)    {      if (*pb)	return(0);      else	goto button_up;    }  while((status & TP_STATUS_DATAVALID) == TP_STATUS_DATAVALID)    {      int tempb = 0;      err = read_tp(&xpos, &ypos, &zpos, &tempb, &status, 1);       if (err == EAGAIN)	{	  if (!samples)	    continue; /* We need at least one reading! */	  else	    break; /* The device continues to not respond.  Bail */	}      else if (err)	return(-1);      /* If the data is invalid and the button is down, then bail */      /* Otherwise, record the button data */           if ( (status & TP_STATUS_DATAVALID) != TP_STATUS_DATAVALID)	{	  if (tempb)	    return(0); /* Button is down, but data is invalid */      	  else 	    {	      *pb = tempb; /* Record button up */	      goto button_up;	    }	}#ifdef USE_FILTER      /* Run the newly aquired data through a filter */      /* is filter ready? */      if ( iir_count == iir_sample_depth )	{	  /* make room for new sample */	  iir_accum_x -= iir_accum_x >> iir_shift_bits;	  iir_accum_y -= iir_accum_y >> iir_shift_bits;	  iir_accum_z -= iir_accum_z >> iir_shift_bits;	  	  /* feed new sample to filter */	  iir_accum_x += xpos;	  iir_accum_y += ypos;	  iir_accum_z += zpos;	}      else	{	  iir_accum_x += xpos;	  iir_accum_y += ypos;	  iir_accum_z += zpos;	  iir_count += 1;	}#else      cx += xpos;      cy += ypos;      cz += zpos;#endif      samples++;            /* Enough samples?? */      if (samples >= MOU_SAMPLE_RATE)	break;    }  if (!samples)    return(0);#ifdef USE_FILTER    /* We're not done gathering samples yet */  if (iir_count < iir_sample_depth)    return(0);  if (enable_pointing_coordinate_transform)    {	        /* transform x,y to screen coords */      transformed.x = iir_accum_x;      transformed.y = iir_accum_y;      transformed = DeviceToScreen(transformed);            *px = transformed.x >> 2;      *py = transformed.y >> 2;    }  else    {      *px = (MWCOORD) abs(iir_accum_x);      *py = (MWCOORD) abs(iir_accum_y);    }#else    if (enable_pointing_coordinate_transform)    {      transformed.x = (cx / samples);      transformed.y = (cy / samples);            transformed = DeviceToScreen(transformed);            *px = (MWCOORD) transformed.x >> 2;      *py = (MWCOORD) transformed.y >> 2;    }  else    {      *px = (MWCOORD) abs(cx / samples);      *py = (MWCOORD) abs(cy / samples);    }#endif   button_up:  if (! *pb)    {#ifdef USE_FILTER      /* reset the filter */      iir_count = 0;      iir_accum_x = 0;      iir_accum_y = 0;      iir_accum_z = 0;#endif      return(3);    }  else    return(2); /* XYZ and button data */}#ifndef TESTMOUSEDEVICE mousedev = {	PD_Open,	PD_Close,	PD_GetButtonInfo,	PD_GetDefaultAccel,	PD_Read,	NULL};#endif#ifdef TESTint main(int argc, char ** v){	int x, y, z;	int	b;	int result;		DPRINTF("Opening touch panel...\n");	if((result=PD_Open(0)) < 0)	  {	    	    DPRINTF("Error %d, result %d opening touch-panel\n", errno, result);	    exit(0);	  }	DPRINTF("Reading touch panel...\n");	while(1) 	  {	    result = PD_Read(&x, &y, &z, &b);	    	    if( result > 0) 	      {		DPRINTF("(%d,%d,%d) b = %d\n",x, y, z, b);			      }	  }}#endif

⌨️ 快捷键说明

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