/* $Id: fpitcal.c,v 1.1 2003/02/10 04:11:19 mrolig Exp $ */

/* fpitcal.c by Mac Betts <mac@chattanooga.net> */
/*
 * Copyright 2002 by Mac Betts <mac@chattanooga.net>
 *                                                                            
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is  hereby granted without fee, provided that
 * the  above copyright   notice appear  in   all  copies and  that both  that
 * copyright  notice   and   this  permission   notice  appear  in  supporting
 * documentation, and that   the  name of Mac Betts not  be  used  in
 * advertising or publicity pertaining to distribution of the software without
 * specific,  written      prior  permission.  Mac Betts  makes  no
 * representations about the suitability of this software for any purpose. It
 * is provided "as is" without express or implied warranty.                   
 *                                                                            
 * MAC BETTS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT  SHALL MAC BETTS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA  OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS  ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * This software hosted by John Apfelbaum on linuxslate.com
 * Please visit linuxslate.com for more information and updates.
 * Software hosted on linuxslate.com is provided without warranty of any sort.
 * Most, if not all is test version software and *probably will* produce
 * unpredictable and or undesirable results.
 *
 */
 
/* BUGS:
 * 	* I'm too lazy to use getopt tonight (for verbose).  I'll do that
 * 		another day.
 * 	* If I get my Stylistic 2300 exactly calibrated for the bottom left
 * 		and top right corners of the screen, the top left and bottom
 * 		right are off.  Is this a bug in the hardware, or the driver
 * 		(or user)?  Can the driver compensate for it if it's a
 * 		hardware problem?
 * 	* Really should draw nice spots on the screen to touch instead; this
 * 		is a little too easy to screw up. I've never programmed Linux
 * 		framebuffers, but I guess that's the way to handle it for
 * 		Linux.  What about the BSDs?  Would curses make sense?
 * 	* Seems the driver code ought to use a nicely readable struct like I
 * 		did.  I'm too lazy to dissect it tonight, though.
 * 	* The driver I downloaded only reported one mouse button.  Why?
 * 		Should I submit a patch or something?
 * 	* Emulate3Buttons doesn't work for some reason.
 * 	* How do I access the touch screen while using devfs?
 * 	* These things are too cool for me.  I think I'm jealous of them.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

/*
 * Comment copied-n-pasted from xf86Fpit.c (see linuxslate.com)
 *
 * Format of 5 bytes data packet for Fpit Tablets
     Byte 1
       bit 7  Phasing bit always 1
       bit 6  Switch status change
       bit 5  Proximity
       bit 4  Always 0
       bit 3  Test data
       bit 2  Sw3 (2nd side sw) 
       bit 1  Sw2 (1st side sw) 
       bit 0  Sw1 (Pen tip sw) 

     Byte 2
       bit 7  Always 0
       bits 6-0 = X6 - X0

     Byte 3
       bit 7  Always 0
       bits 6-0 = X13 - X7

     Byte 4
       bit 7  Always 0
       bits 6-0 = Y6 - Y0

     Byte 5
       bit 7  Always 0
       bits 6-0 = Y13 - Y7
*/

#define fpit_bytes 5
typedef struct fpitdata_s {
	/* Byte 1 */
	unsigned sw1:1;
	unsigned sw2:1;
	unsigned sw3:1;
	unsigned test_data:1;
	unsigned zero:1;
	unsigned proximity:1;
	unsigned switch_status_change:1;
	unsigned one:1;
	/* Byte 1 */
	unsigned lowx:7;
	unsigned zero1:1;
	/* Byte 2 */
	unsigned highx:7;
	unsigned zero2:1;
	/* Byte 3 */
	unsigned lowy:7;
	unsigned zero3:1;
	/* Byte 4 */
	unsigned highy:7;
	unsigned zero4:1;
} fpitdata_t;

int main (int argc, char * argv[]) {
	int fd;
	int b;
	fpitdata_t d;
	unsigned x, y, maxx=0, minx=-1, maxy=0, miny=-1;
	unsigned verbose = 0;

	fprintf (stderr, "Touch each of the bottom left and the top right corners of your screen with\n the stylus, and then press both buttons (touch the screen with the stylus\n while pressing the button on the stylus).\n\n");
	fflush (stderr);
	if ((fd = open ("/dev/ttyS0", O_RDONLY)) == -1) {
		perror ("opening");
		exit (-1);
	}
	while (1) {
		b = read (fd, &d, fpit_bytes);
		if (b == -1)
			perror ("reading");
		else if (b == fpit_bytes) {
			x = (d.highx << 7) | d.lowx;
			y = (d.highy << 7) | d.lowy;
			maxx = x > maxx ? x : maxx;
			minx = x < minx ? x : minx;
			maxy = y > maxy ? y : maxy;
			miny = y < miny ? y : miny;
			if (verbose)
				fprintf (stderr, "one:%d ssc:%d prox:%d zero:%d td:%d sw3:%d sw2:%d sw1:%d (%4d,%4d)\n", d.one, d.switch_status_change, d.proximity, d.zero, d.test_data, d.sw3, d.sw2, d.sw1, x, y);
			if (d.sw1 & d.sw2) {	/* Or &&?  Is this more efficient? */
				fprintf (stderr, "You may copy-n-paste or redirect the following lines to the InputDevice\n section of your XF86Config file dealing with your touchscreen.  If you\n redirect, don't forget to use append mode (>>), and either way make sure you\n put it into the right section.\n\n");
				fflush (stderr);
				printf ("\tOption\t\t\"MaximumXPosition\"\t\"%d\"\n", maxx);
				printf ("\tOption\t\t\"MinimumXPosition\"\t\"%d\"\n", minx);
				printf ("\tOption\t\t\"MaximumYPosition\"\t\"%d\"\n", maxy);
				printf ("\tOption\t\t\"MinimumYPosition\"\t\"%d\"\n", miny);
				break;
			}
			fflush (stdout);
		} else {
			fprintf (stderr, "er. partial read fails sanity check: %d != %d\n", b, fpit_bytes);
			break;
		}
	}
	return 0;
}

