text: ﻿/*
   *  tslib/plugins/pthres.c
   *
   *  Copyright (C) 2003 Texas Instruments, Inc.
   *
   *  Based on:
   *    tslib/plugins/linear.c
   *    Copyright (C) 2001 Russell King.
   *
   * This file is placed under the LGPL.  Please see the file
   * COPYING for more details.
   *
   * Ensure a release is always pressure 0, and that a press is always >=1.
   */
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <errno.h>
  #include <limits.h>
  
  #include "config.h"
  #include "tslib.h"
  #include "tslib-filter.h"
  
  struct tslib_pthres {
  	struct tslib_module_info module;
  	unsigned int	pmin;
  	unsigned int	pmax;
  };
  
  static int
  pthres_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
  {
  	struct tslib_pthres *p = (struct tslib_pthres *)info;
  	int ret;
  	static int xsave = 0, ysave = 0;
  	static int press = 0;
  
  	ret = info->next->ops->read(info->next, samp, nr);
  	if (ret >= 0) {
  		int nr = 0, i;
  		struct ts_sample *s;
  
  		for (s = samp, i = 0; i < ret; i++, s++) {
  			if (s->pressure < p->pmin) {
  				if (press != 0) {
  					/* release */
  					press = 0;
  					s->pressure = 0;
  					s->x = xsave;
  					s->y = ysave;
  				} else {
  					/* release with no press, outside bounds, dropping */
  					int left = ret - nr - 1;
  					if (left > 0) {
  						memmove(s, s + 1, left * sizeof(struct ts_sample));
  						s--;
  						continue;
  					}
  					break;
  				}
  			} else {
  				if (s->pressure > p->pmax) {
  					/* pressure outside bounds, dropping */
  					int left = ret - nr - 1;
  					if (left > 0) {
  						memmove(s, s + 1, left * sizeof(struct ts_sample));
  						s--;
  						continue;
  					}
  					break;
  				}
  				/* press */
  				press = 1;
  				xsave = s->x;
  				ysave = s->y;
  			}
  			nr++;
  		}
  		return nr;
  	}
  	return ret;
  }
  
  static int pthres_fini(struct tslib_module_info *info)
  {
  	free(info);
  	return 0;
  }
  
  static const struct tslib_ops pthres_ops =
  {
  	pthres_read,
  	pthres_fini,
  };
  
  static int threshold_vars(struct tslib_module_info *inf, char *str, void *data)
  {
  	struct tslib_pthres *p = (struct tslib_pthres *)inf;
  	unsigned long v;
  	int err = errno;
  
  	v = strtoul(str, NULL, 0);
  
  	if (v == ULONG_MAX && errno == ERANGE)
  		return -1;
  
  	errno = err;
  	switch ((int)data) {
  	case 0:
  		p->pmin = v;
  		break;
  
  	case 1:
  		p->pmax = v;
  		break;
  
  	default:
  		return -1;
  	}
  	return 0;
  }
  
  
  static const struct tslib_vars pthres_vars[] =
  {
  	{ "pmin",	(void *)0, threshold_vars },
  	{ "pmax",	(void *)1, threshold_vars }
  };
  
  #define NR_VARS (sizeof(pthres_vars) / sizeof(pthres_vars[0]))
  
  TSAPI struct tslib_module_info *pthres_mod_init(struct tsdev *dev, const char *params)
  {
  
  	struct tslib_pthres *p;
  
  	p = malloc(sizeof(struct tslib_pthres));
  	if (p == NULL)
  		return NULL;
  
  	p->module.ops = &pthres_ops;
  
  	p->pmin = 1;
  	p->pmax = INT_MAX;
  
  	/*
  	 * Parse the parameters.
  	 */
  	if (tslib_parse_vars(&p->module, pthres_vars, NR_VARS, params)) {
  		free(p);
  		return NULL;
  	}
  
  	return &p->module;
  }
  
  #ifndef TSLIB_STATIC_PTHRES_MODULE
  	TSLIB_MODULE_INIT(pthres_mod_init);
  #endif
  