/* 
 * Copyright (c) 1999  Machine Vision Holdings Incorporated
 * Author: David Woodhouse <David.Woodhouse@mvhi.com>
 *
 * Template driver used: Copyright (c) 1998  Metro Link Incorporated
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Except as contained in this notice, the name of the Metro Link shall not be
 * used in advertising or otherwise to promote the sale, use or other dealings
 * in this Software without prior written authorization from Metro Link.
 *
 */
/* $XFree86: xc/programs/Xserver/hw/xfree86/input/penmount/xf86PM.h,v 1.2 1999/08/22 05:57:37 dawes Exp $ */

#ifndef _PENMOUNT_H_
#define _PENMOUNT_H_

/**********************************************
          File Path
 **********************************************/
#define HALF_DUPLEX_READ    "/tmp/penmount_cmd" /* pipe */
#define HALF_DUPLEX_WRITE   "/tmp/penmount_dat" /* pipe */
#define CALIBRATION_DATA    "/etc/penmount.dat" /* data */

/******************************************************************************
 *        Definitions
 *****************************************************************************/
#define PM_SUPPORT_CHIPS  6
#define PM_PACKET_SIZE    6       /* 5 -> 6 */
#define PM_BUFFER_SIZE    1024

#define PM_DEF_PMODE      1
#define PM_DEF_MIN_X      0
#define PM_DEF_MAX_X      1024
#define PM_DEF_MIN_Y      0
#define PM_DEF_MAX_Y      1024

#define PM_DEF_MAX_12X    4096
#define PM_DEF_MAX_12Y    4096

#define X_PENMOUNT        " PenMount: "

const char *PM_INFO       = {"(II)" X_PENMOUNT}; /* Informational message */
const char *PM_ERROR      = {"(EE)" X_PENMOUNT}; /* Error message */

/******************************************************************************
 *        enumeration
 *****************************************************************************/
typedef enum {

    CHIP_UNKNOWN = 0,
    PM8910,
    PM9100,
    PM9512,
    PM9000,
    PM7000,
    PM6000USB,
    PM6000COM,
    PM5000

} PenMountChip;

typedef enum {

    PM_Byte0,
    PM_Byte1,
    PM_Byte2, 
    PM_Byte3, 
    PM_Byte4,
    PM_Byte5,

    PM_Res0, 
    PM_Res1, 
    PM_Res2,
    PM_Res3,
    PM_Res4,
    PM_Res5
    
} PenMountState;

/******************************************************************************
 *        Private Record
 *****************************************************************************/
typedef struct _PenMountPrivateRec {

    int     pmode;
    int     min_x;          /* Minimum x reported by calibration */
    int     max_x;          /* Maximum x                         */
    int     min_y;          /* Minimum y reported by calibration */
    int     max_y;          /* Maximum y                         */
    int     old_x;          /* Prior x                           */
    int     old_y;          /* Prior y                           */
    int     old_button;     /* Prior button                      */
    Bool    button_down;    /* is the "button" currently down    */
    int     button_number;  /* which button to report            */
    int     reporting_mode; /* TS_Raw or TS_Scaled               */

    int     screen_num;     /* Screen associated with the device */
    int     screen_width;   /* Width of the associated X screen  */
    int     screen_height;  /* Height of the screen              */
    int     proximity;
    int     swap_xy;

    XISBuffer       *buffer;
    unsigned char   packet[PM_PACKET_SIZE];   /* packet being/just read */
    PenMountState   lex_mode;

    int     chip;
    char    pen_down;
    char    queryHw;
    int     beep;           /* 0 = no beep, 1 = beep enabled          */
    int     press_vol;      /* volume of beep (press event)           */
    int     press_pitch;    /* pitch of beep (press event)            */
    int     press_dur;      /* length of beep in 10ms (press event)   */
    int     rel_vol;        /* volume of beep (release event)         */
    int     rel_pitch;      /* pitch of beep (release event)          */
    int     rel_dur;        /* length of beep in 10ms (release event) */
    int     CalibrationMode;
    int     packet_size;
    int     ad_bit;
}
PenMountPrivateRec, *PenMountPrivatePtr;


typedef struct
{
	unsigned char version[PM_PACKET_SIZE];
	unsigned char disable[PM_PACKET_SIZE];
	unsigned char enable[PM_PACKET_SIZE];	
	unsigned char echo[PM_PACKET_SIZE];
	unsigned char resetX1[PM_PACKET_SIZE];
	unsigned char resetY1[PM_PACKET_SIZE];
	unsigned char resetX2[PM_PACKET_SIZE];
	unsigned char resetY2[PM_PACKET_SIZE];
	unsigned char width[PM_PACKET_SIZE];
	unsigned char height[PM_PACKET_SIZE];
	
} PenMount_Commands;

#if 0
static  PenMount_Commands commands[PM_SUPPORT_CHIPS] =
{
 	{	/* Unknown */
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00} 		
 	},
 	{	/* PM8910 */
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00} 		
 	},
 	{	/* PM9100 */
 	 {0xf2,0x00,0x00,0x00,0x00},
 	 {0xf0,0x00,0x00,0x00,0x00},
 	 {0xf1,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00} 		
 	},
	{	/* PM9512 */
	 {'D','G',0x0b,0x00,0x00},
	 {'D','G',0x0a,0x00,0x00},
 	 {'D','G',0x0a,0x01,0x00},
 	 {'D','G',0x02,0x80,0x00},
 	 {'D','G',0x02,0x40,0x03},
 	 {'D','G',0x02,0x50,0x03},
 	 {'D','G',0x02,0x60,0xfc},
 	 {'D','G',0x02,0x70,0xfc},
 	 {'D','G',0x02,0x03,0xfa},     /* 0x3fc-3+1 */
 	 {'D','G',0x02,0x13,0xfa}      /* 0x3fc-3+1 */
 	},
 	{	/* PM9000 */
 	 {0xf2,0x00,0x00,0x00,0x00},
 	 {0xf0,0x00,0x00,0x00,0x00},
 	 {0xf1,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00}
 	},
 	{	/* PM6000 */
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00},
 	 {0x00,0x00,0x00,0x00,0x00} 		
 	}
};

#endif



/******************************************************************************
 *        Declarations
 *****************************************************************************/
static InputInfoPtr PenMountPreInit(InputDriverPtr drv, IDevPtr dev, int flags);

static Bool DeviceControl (DeviceIntPtr, int);
static void ReadInput (InputInfoPtr);
static int  ControlProc (InputInfoPtr, xDeviceCtl *);
static void CloseProc (InputInfoPtr);
static int  SwitchMode (ClientPtr, DeviceIntPtr, int);
static Bool ConvertProc (InputInfoPtr, int, int, int, int, int, int, int, int, int *, int *);

/*
static Bool QueryHardware (PenMountPrivatePtr);
static Bool PenMountSendCommand (PenMountPrivatePtr priv, unsigned char *cmd);
 */
static Bool PenMountGetPacket (PenMountPrivatePtr priv);
/*
static Bool PenMountSendPacket (PenMountPrivatePtr priv, unsigned char *buf, int len);
static Bool PenMountSendPacket (PenMountPrivatePtr priv, unsigned char *buf);
static Bool PenMountWaitReply (PenMountPrivatePtr priv);
 */

static void PenMountPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl);
static void LoadUserCalibration(PenMountPrivatePtr priv);
static void TearDownProc(pointer p);
static void PenMountBeep(PenMountPrivatePtr priv, int press);

#endif /* _PENMOUNT_H_ */
