/*
*	Link string    cc -o quantumtest_sun -lX11 -lXi quantumtest_sun.c
*/

#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <X11/extensions/XInput.h>
#include <wacom.h>

char *transType[4] =
{
   "puck   ",
   "stylus ",
   "eraser ",
   "unknown"
};


int    		get_devices(void);
static XDevice 	*open_device(XID id);
static int 	x_error_handler(Display *disp, XErrorEvent *error);
static void 	get_tablet_params(void);

static XID 	tablet_id = 0;
static int 	display_x;
static int 	display_y;
static Display 	*display;
static int 	screen_number;
static unsigned char last_xerror;
static XDevice 	*mouse_device = 0;
static XDevice 	*tablet_device = 0;
static int 	x_error_handler_print_error = 1;

	
int main(int argc, char *argv[], char *envp[])
{
    display = XOpenDisplay(NULL);
    if (display == NULL) 
    {
        fprintf(stderr,"Could not open display\n");
        exit(1);
    }

    screen_number = DefaultScreen(display);
    printf("Screen Number = %d\n", screen_number);
    (void)XSetErrorHandler(x_error_handler);

    if (get_devices())
        exit(1);

    get_tablet_params();

    if (tablet_device)
        XCloseDevice(display, tablet_device);

    exit(0);
}

static void get_tablet_params(void)
{
    XDeviceState    *device_state;
    XValuatorState  *val_state;
    XInputClass     *input_class = NULL;
    int		num_classes;
    int		dataArray[WACOM_NUM_VALUATORS];
    int		oldDataArray[WACOM_NUM_VALUATORS];
    int		notEqualFlag;
    int		index;
    int		maxValuators;
    static int	firstPass = 1;


    if (tablet_device == (XDevice *)0)
    if ((tablet_device = open_device(tablet_id)) == (XDevice *)0)
        return;
 
    /* initialize the data array */
    for (index = 0; index < WACOM_NUM_VALUATORS; index++)
    {
        dataArray[index] = 0;
        oldDataArray[index] = 0;
    }

    // get static values
    device_state = XQueryDeviceState(display, tablet_device);
    input_class = device_state->data;
    num_classes = device_state->num_classes;

    if (num_classes > 0) 
    {
        for (j=0; j<num_classes; j++)
        {
            if (Dflag)
		{
                printf ("\t\t\tInput class %d\n", input_class->class);
		    printf ("\t\t\t\tLength is %d\n", input_class->length);
		}
		switch (input_class->class)
		{
		    case KeyClass:
		       K = (XKeyInfoPtr) input_class;
		       if (Dflag)
   		       {
		           printf ("\t\t\t\tNum_keys is %d\n",K->num_keys);
  			     printf ("\t\t\t\tMin_keycode is %d\n",K->min_keycode);
			     printf ("\t\t\t\tMax_keycode is %d\n",K->max_keycode);
		       }
		    break;
		    case ButtonClass:
			 b = (XButtonInfoPtr) input_class;
			 if (Dflag)
			 {
			    printf ("\t\t\t\tNum_buttons is %d\n",b->num_buttons);

			 }
			 break;
		    case ValuatorClass:
			 v = (XValuatorInfoPtr) input_class;
			 a = (XAxisInfoPtr) ((char *) v + sizeof (XValuatorInfo));
			 if (Dflag)
			 {

			    printf ("\t\t\t\tNum_axes is %d\n\n",v->num_axes);
			 }
		    break;
		    default:
			 printf ("\t\t\t\t\tunknown class\n");
		}
		input_class = (XInputClass *) ((char *) any + any->length);
        }

        printf ("Please bring your transducer onto the tablet for\

				 testing\n \nPress \"Ctrl C\" to exit\n");
        while(1) 

	  {
           device_state = XQueryDeviceState(display, tablet_device);

	     input_class = device_state->data;
	     num_classes = device_state->num_classes;

	     while (num_classes--) 
	     {
		   if (input_class->class == ValuatorClass) 
		   {
			val_state = (XValuatorState *)input_class;
			maxValuators = (int) val_state->num_valuators;
			for (index = 0; index < maxValuators; index++)
			{
			   dataArray[index] = val_state->valuators[index];
			}
			notEqualFlag = 0;
			if( firstPass )
			{
			   for (index = 0; index < maxValuators; index++)
			   {
			      oldDataArray[index] = dataArray[index];
			   }
			   firstPass = 0;
			}
			else
			{
			   for (index = 0; index < maxValuators; index++)
			   {
				if (dataArray[index] != oldDataArray[index]) 
				{
				   notEqualFlag = 1;
				   index = maxValuators;
				}
			   }
			}
			if (notEqualFlag)
			{
			   printf ("\n");
			   if (((dataArray[WAC_TRANSDUCER_I] ) !=
						oldDataArray[WAC_TRANSDUCER_I] ) &&
						(dataArray[WAC_TRANSDUCER_I] &
						WAC_TRANSDUCER_PROX_MSK))
			   { 
				printf ("Enter Prox Primary   %s\tID=%x\tSerial No.=%x\n",
					transType[dataArray[WAC_TRANSDUCER_I]&WAC_TRANSDUCER_MSK],
					WAC_TRANSDUCER_ID(dataArray[WAC_TRANSDUCER_I]),
					dataArray[WAC_SERIAL_NUM_I]);
			   }
			   else if (((dataArray[WAC_2TRANSDUCER_I] ) !=
					oldDataArray[WAC_2TRANSDUCER_I] ) &&
					(dataArray[WAC_2TRANSDUCER_I] &
					WAC_TRANSDUCER_PROX_MSK))
			   { 
				printf ("Enter Prox Secondary %s\tID=%x\tSerial No.=%x\n",
					transType[dataArray[WAC_2TRANSDUCER_I] &
					WAC_TRANSDUCER_MSK],
					WAC_TRANSDUCER_ID(dataArray[WAC_2TRANSDUCER_I]),
					dataArray[WAC_2SERIAL_NUM_I]);
			   }
			   printf("VAL  X  %05d  ", dataArray[WAC_XCOORD_I]);
			   printf("Y  %05d  ", dataArray[WAC_YCOORD_I]);
			   printf("P  %04d  ", dataArray[WAC_PRESSURE_I]);
			   printf("B  %04x  ", dataArray[WAC_BUTTON_I]);
			   printf("Tx  %4d  ", dataArray[WAC_XTILT_I]);
			   printf("Ty  %4d  ", dataArray[WAC_YTILT_I]);
			   printf("Z  %05d  ", dataArray[WAC_ZCOORD_I]);
			   printf("Tan  %04d  ", dataArray[WAC_TAN_PRESSURE_I]);
			   printf("R  %4d\n", dataArray[WAC_ROTATION_I]);

			   printf("     X2 %05d  ", dataArray[WAC_2XCOORD_I]);
			   printf("Y2 %05d  ", dataArray[WAC_2YCOORD_I]);
			   printf("P2 %04d  ", (short int)((dataArray[WAC_PRESSURE_I]
			 		& WAC_SECOND_MSK) >> WAC_SECOND_OFFSET));
			   printf("B2 %04x  ", dataArray[WAC_2BUTTON_I]);
			   printf("Tx2 %4d  ", (short int)((dataArray[WAC_XTILT_I]
			 		& WAC_SECOND_MSK) >> WAC_SECOND_OFFSET));
			   printf("Ty2 %4d  ", (short int)((dataArray[WAC_YTILT_I]
					& WAC_SECOND_MSK) >> WAC_SECOND_OFFSET));
			   printf("Z2 %05d  ", (short int)((dataArray[WAC_ZCOORD_I]
					& WAC_SECOND_MSK) >> WAC_SECOND_OFFSET));
			   printf("Tan2 %04d  ", (short int)((dataArray[WAC_TAN_PRESSURE_I]
					& WAC_SECOND_MSK) >> WAC_SECOND_OFFSET));
			   printf("R2 %4d\n", (short int)((dataArray[WAC_ROTATION_I]
					& WAC_SECOND_MSK) >> WAC_SECOND_OFFSET));

			   if ( dataArray[WAC_TRANSDUCER_I] !=
					oldDataArray[WAC_TRANSDUCER_I] ) 
			   {
				/*    Menu item info     */
				if (dataArray[WAC_TRANSDUCER_I] & WAC_MENU_ID)
				{
				   printf ( "Menu pressed ");
				}
				/* Print exiting info   */
				else if ( !(dataArray[WAC_TRANSDUCER_I] &
							WAC_TRANSDUCER_PROX_MSK) )
				{ 
				   printf ("Exit Prox Primary %s\tID=%x\tSerial No.=%x\n",
						transType[dataArray[WAC_TRANSDUCER_I] &
						WAC_TRANSDUCER_MSK],
						WAC_TRANSDUCER_ID(dataArray[WAC_TRANSDUCER_I]),
						dataArray[WAC_SERIAL_NUM_I]);
				}
			   }
			   else if (((dataArray[WAC_2TRANSDUCER_I] ) !=
					oldDataArray[WAC_2TRANSDUCER_I]) &&
					!(dataArray[WAC_2TRANSDUCER_I] &
					WAC_TRANSDUCER_PROX_MSK))
			   { 
			      printf ("Exit  Prox Secondary %s\tID=%x\tSerial No.=%x\n",
					transType[dataArray[WAC_2TRANSDUCER_I] &
					WAC_TRANSDUCER_MSK],
					WAC_TANSDUCER_ID(dataArray[WAC_2TRANSDUCER_I]),
						dataArray[WAC_2SERIAL_NUM_I]);
			   }
			   /*    Menu item number     */
			   if ( (dataArray[WAC_BUTTON_I] != oldDataArray[WAC_BUTTON_I])&&
					(dataArray[WAC_BUTTON_I] & WAC_MENU_ITEM_MSK) )
			   { 
				printf ( "Item Number = %d\n", 

						WAC_MENU_BUTTONS(dataArray[WAC_BUTTON_I]) );
			   }
			   for (index = 0; index < maxValuators; index++)
			   {
				oldDataArray[index] = dataArray[index];
			   }
			}
		}
	      input_class=(XInputClass *)((char *)input_class + input_class->length);

        }
    } /* end of while (1)  */
}
	

static XDevice * open_device(XID id)
{
	XDevice		*device;

	last_xerror = 0;
	device = XOpenDevice(display, id);

	if (last_xerror)
		device = (XDevice *)0;	

	return(device);
}

static int get_devices(void)
{
	XDeviceInfo	*devices;
	Atom		tablet_atom;
	Atom		mouse_atom;
	int 		i, ndevices;

	devices = XListInputDevices(display, &ndevices);

	tablet_atom = XInternAtom(display, "TABLET", True);
	for(i = 0; i < ndevices; i++) 
	{
		if (tablet_atom == devices[i].type) 
		{
			tablet_id = (XID)devices[i].id;
			break;
		}
	}

	x_error_handler_print_error = 0;

	/* try to open each device */
	tablet_device = open_device(tablet_id);

	x_error_handler_print_error = 1;

	return(0);
}

static int x_error_handler(Display *disp, XErrorEvent *error)
{
	char buffer[256];

	if (x_error_handler_print_error) 
	{
		XGetErrorText(disp, error->error_code, buffer, sizeof(buffer));
		fprintf(stderr,"x_error: %s\n",buffer);
	}

        last_xerror = error->error_code; 
}
