/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/*************************************************************************/
/*                                                                       */
/*                                                                       */
/*************************************************************************/
/******************* START OF SPECIFICATIONS *****************************/
/*                                                                       */
/*  SOURCE FILE NAME: PENTL.C                                            */
/*                                                                       */
/*  DESCRIPTIVE NAME: Pen driver test program                            */
/*                                                                       */
/*                                                                       */
/*  STATUS:  Version 1.0                                                 */
/*                                                                       */
/*  NOTES: Exercises all IOCTL interfaces. Can be run as interactive     */
/*         program, or can pipe a file or commands into program.         */
/*                                                                       */
/*                                                                       */
/*  ENTRY POINTS:                                                        */
/*      See public statements                                            */
/*  EXTERNAL REFERENCES:                                                 */
/*      See extrn statements                                             */
/*                                                                       */
/******************* END  OF  SPECIFICATIONS *****************************/
#define INCL_DOSFILEMGR   /* File Manager values */
#define INCL_DOSDEVICES   /* Device values */
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "penei.h"
#include "penioctl.h"

#define FILE_SIZE   0L
#define EABUF 0L

#define TXL 80
#define NTXL 9
#define MAXPARMS 6


typedef struct _EMIUSD {
   ULONG length;
   char  emidrv[2][10];
} EMIUSD;
EMIUSD emiusd;

char    fileName[TXL]  = "\\dev\\PENDD$";
char *  EBC = "-error-> Unknown command";
char    sztext[TXL];
char    dquc[100];
char    p[MAXPARMS][TXL];
HFILE   FileHandle   = 0;
APIRET  rc           = 0;
LONG *  traceBuf;
LONG    traceBufSize = 0;

LONG    locUnit=1;
LONG    butUnit=2;
LONG    dspUnit=3;

int     inact=1;
int     echo=1;

int     showInt = 1;
int     showAbs = 1;
int     showData= 1;
int     showTick= 1;
int     showErr= 1;
int     showDD = 1;
int     showSys= 1;

int     pageInt = 1;
int     pageAbs = 0;
int     pageData= 0;
int     pageTick= 0;
int     pageErr= 0;
int     pageDD = 0;
int     pageSys = 0;

void doHelp(void);
void chkLevel(void);
void doSetShow(int showVal);
void doSetPage(int pageVal);
void doSetName(void);
void doDump(void);
void usage(void);
void doTrcCmd(void);
void doAssCmd(void);
void doLocCmd(void);
void doButCmd(void);
void doDspCmd(void);
void doUntCmd(void);
void doXXXCmd(void);
void doDrvCap(DDCAP * ddcap);
void doLocCap(LCAP * lcap);
void doButCap(BCAP * bcap);
void doDspCap(DCAP * dcap);
void doCCap(CCAP * ccap);
void initAD(void);

void doOPEN(ULONG drvNumber);
APIRET doIOCTL(ULONG category, ULONG function,
             PVOID pParams, LONG pcbParmLen,
             PVOID pData, LONG pcbDataLen);

/***************************************************************************\
*
*  VOID main (argc, argv)
*
*  DESCRIPTION:
*    Program mainline.
*
*  INPUTS:
*    argc       - number of parameters
*    argv       - pointer to start of parameter list
*
\***************************************************************************/

int main(int argc,char * argv[])
{
//   ULONG   rc;
   ULONG   i         = 0;
   ULONG   parmcnt   = 0;
   FILE *  kludge    = NULL;

   initAD();

   for (i=1;i<argc;i++) {
      if (argv[i][0]=='-') {
         switch (argv[i][1]) {
         case 'f':
            inact = 0;
            break;
         case 'q':
            echo  = 0;
            break;
         case 'd':
            strcpy(&(emiusd.emidrv[1][0]),argv[i+1]);
            printf("fileName=%s \n",emiusd.emidrv[1]);
            i++;
            break;
         case '?':
         default:
            usage();
            exit(0);
         } /* endswitch */
      } else {
         if (argv[i][0]=='?') {
            usage();
            exit(0);
         } /* endif */
      } /* endif */
   } /* endfor */

   doOPEN(1);
   chkLevel();

   kludge = NULL;
   if (inact) {printf(".");fflush(kludge);}
   while (gets(sztext)) {

      if (sztext[0] != 0) {
         for (i=0;i<MAXPARMS;p[i++][0]=0);
         parmcnt = (ULONG) sscanf(sztext,"%s %s %s %s %s %s",
                       p[0],p[1],p[2],p[3],p[4],p[5]);
      } else {
         printf(".%s %s %s %s %s %s\n", p[0],p[1],p[2],p[3],p[4],p[5]);
         fflush(kludge);
      } /* endif */

      if ((inact==0)&&(echo)) {
         printf(".%s %s %s %s %s %s\n", p[0],p[1],p[2],p[3],p[4],p[5]);
      }

      if (parmcnt == 0) exit(0);

      if ((p[0][0]=='h')&&(p[0][1]==0)) {
         doHelp();
      } else if (p[0][0]=='?') {
         doHelp();
      } else if ((p[0][0]=='q')&&(p[0][1]=='u')&&(p[0][2]=='i')&&(p[0][3]=='t')) {
         exit(0);
      } else {
         switch (p[0][0]) {
         case 'd':
            doSetShow(1);  //set display
            break;
         case 'h':
            doSetShow(0);  //set hide
            break;
         case 'p':
            doSetPage(1);  //set to page
            break;
         case 'c':
            doSetPage(0);  //set not to page
            break;
         case 'a':
            doAssCmd();    //do assignment commands
            break;
         case 'x':
            doXXXCmd();    //do special development stuff
            break;
         default:
            switch (p[0][1]) {
            case 't':
               doTrcCmd();   //trace command
               break;
            case 'l':
               doLocCmd();   //locator commands
               break;
            case 'b':
               doButCmd();   //button  commands
               break;
            case 'd':
               doDspCmd();   //display commands
               break;
            case 'u':
               doUntCmd();   //unit  commands
               break;
            default:
               printf("%s\n",EBC);
            } /* endswitch */
         } /* endswitch */
      } /* endif */

      if (inact) {printf(".");fflush(kludge);}

   } /* endwhile */
   return 0;
}

void doSetShow(int showVal)
{
   switch (p[0][1]) {
   case 'i':
      showInt = showVal;
      break;
   case 'a':
      showAbs = showVal;
      break;
   case 't':
      showTick = showVal;
      break;
   case 'd':
      showData = showVal;
      break;
   case 'e':
      showErr = showVal;
      break;
   case 'x':
      showDD  = showVal;
      break;
   case 's':
      showSys = showVal;
      break;
   default:
      printf("%s\n",EBC);
   } /* endswitch */
}


void doSetPage(int pageVal)
{
   switch (p[0][1]) {
   case 'i':
      pageInt = pageVal;
      break;
   case 'a':
      pageAbs = pageVal;
      break;
   case 't':
      pageTick = pageVal;
      break;
   case 'd':
      pageData = pageVal;
      break;
   case 'e':
      pageErr = pageVal;
      break;
   case 'x':
      pageDD  = pageVal;
      break;
   case 's':
      pageSys = pageVal;
      break;
   default:
      printf("%s\n",EBC);
   } /* endswitch */
}

void doTrcCmd(void)
{

   if (p[0][0]=='r') {
     if (p[0][2]=='t') {            // reset trace buffer
         rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_RTT,     // reset trace table
                 NULL,0,
                 NULL,0);
      } else {
         printf("%s\n",EBC);
      } /* endif */
   } else if (p[0][0]=='q') {
      if (p[0][2]=='t') {
        if (p[0][3]=='s') {     // query trace table size
            DQTTS dqtts;
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QTTS,
                    NULL,0,
                    &dqtts, sizeof(DQTTS));
            if (rc) return ;
            printf("size=%d \n",dqtts.size);
        } else {                // query trace table
            DQTTS dqtts;
            PQTT  pqtt;

            dqtts.size = 0;
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QTTS,     //query trace table size
                    NULL,0,
                    &dqtts, sizeof (DQTTS));
            if (rc) return ;
            if (dqtts.size==0) {
              printf("Trace buffer not allocated\n");
              return;
            }
            if (traceBufSize != dqtts.size) {
               if (traceBufSize) {
                  free(traceBuf);
               } /* endif */
               traceBufSize=(LONG) dqtts.size;
               if ((traceBuf = (LONG *)malloc((ULONG)traceBufSize * sizeof(LONG))) == NULL) {
                  printf ("malloc failed\n");
                  return;
               } /* endif */
            } /* endif */
            pqtt.size = (ULONG) traceBufSize;
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QTT,     //query trace table
                    &pqtt, sizeof(PQTT),
                    traceBuf, (LONG) (pqtt.size * sizeof(LONG)));
            if (rc) return ;
            doDump();
        } /* endif */
      } else {
         printf("%s\n",EBC);
      } /* endif */

   } else if (p[0][0]=='s') {

      switch (p[0][2]) {
      case 't':             //set trace table size
         {
            PSTTS pstts;
            pstts.size = (ULONG) atol(p[1]);
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_STTS,
                    &pstts, sizeof(PSTTS),
                    NULL,0);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else {
      printf("%s\n",EBC);
   } /* endif */

}

void doAssCmd(void)
{
  PQUC  pquc;
  char * pdquc    = NULL;
  ULONG drvNumber = 0;

  if (p[0][1] == 'n') {
      drvNumber = (ULONG) atol(p[1]);
      if (drvNumber < 3) {
         doOPEN(drvNumber);
         chkLevel();
      } else {
         printf("Driver number out of range\n");
      } /* endif */
  } else {
      pdquc = dquc;
      pquc.unit  = (ULONG) atol(p[1]);
      pquc.byteCount = 100;
      rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUC,
              &pquc, sizeof(PQUC),
              &dquc, 100);
      if (rc) return ;

      switch (p[0][1]) {
      case 'l':
         if ((((CCAP*)pdquc)->device_type)==DT_LOCATOR) {
            locUnit = (LONG) pquc.unit;
         } else {
            printf("wrong device type\n");
         }
         break;
      case 'd':
         if ((((CCAP*)pdquc)->device_type)==DT_DISPLAY) {
            dspUnit = (LONG) pquc.unit;
         } else {
            printf("wrong device type\n");
         }
         break;
      case 'b':
         if ((((CCAP*)pdquc)->device_type)==DT_BUTTON) {
            butUnit = (LONG) pquc.unit;
         } else {
            printf("wrong device type\n");
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   }
}

void doLocCmd(void)
{
   if (locUnit ==0) {
      printf("Drive does not have a locator device\n");
      return;
   } /* endif */
   if (p[0][0]=='s') {
      switch (p[0][2]) {
      case 'a':             //set locator unit
         {
            PQUC  pquc;
            char * pdquc;

            pdquc = dquc;
            pquc.unit  = (ULONG) atol(p[1]);
            pquc.byteCount = 100;
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUC,
                    &pquc, sizeof(PQUC),
                    &dquc, 100);
            if (rc) return ;
            if ((((CCAP*)pdquc)->device_type)==DT_LOCATOR) {
               locUnit = (LONG) pquc.unit;
            } else {
               printf("wrong device type\n");
            }
         }
         break;
      case 'o':             //set locator offset
         {
            PSLO pslo;
            pslo.unit = (ULONG) locUnit;
            pslo.command=PSLO_SET_X|PSLO_SET_Y;
            pslo.xOffset = atol(p[1]);
            pslo.yOffset = atol(p[2]);
            rc=doIOCTL(PEN_CAT_LOCATOR,PEN_FUNC_SLO,
                    &pslo, sizeof(PSLO),
                    NULL,0);
         }
         break;
      case 'p':             //set locator pass rate
         {
            PSLPR pslpr;
            pslpr.unit = (ULONG) locUnit;
            pslpr.passRate = (ULONG) atol(p[1]);
            rc=doIOCTL(PEN_CAT_LOCATOR,PEN_FUNC_SLPR,
                    &pslpr, sizeof(PSLPR),
                    NULL,0);
         }
         break;
      case 's':             //set locator sample rate
         {
            PSLSR pslsr;
            pslsr.unit = (ULONG) locUnit;
            pslsr.sampleRate = (ULONG) atol(p[1]);
            rc=doIOCTL(PEN_CAT_LOCATOR,PEN_FUNC_SLSR,
                    &pslsr, sizeof(PSLSR),
                    NULL,0);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else if (p[0][0]=='q') {
      switch (p[0][2]) {
      case 'v':             //query locator variables
         {
            PQLV pqlv;
            DQLV dqlv;
            pqlv.unit = (ULONG) locUnit;
            rc=doIOCTL(PEN_CAT_LOCATOR,PEN_FUNC_QLV,
                    &pqlv, sizeof(PQLV),
                    &dqlv, sizeof(DQLV));
            if (rc) return ;
            printf("xOffset=%d yOffset=%d sampleRate=%d passRate=%d\n",
            dqlv.xOffset, dqlv.yOffset, dqlv.sampleRate, dqlv.passRate);
         }
         break;
      case 'r':             //query locator raw coordinate
         {
            PQLRC pqlrc;
            DQLRC dqlrc;
            pqlrc.unit = (ULONG) locUnit;
            pqlrc.timeout = (ULONG) atol(p[1]);
            rc=doIOCTL(PEN_CAT_LOCATOR,PEN_FUNC_QLRC,
                    &pqlrc, sizeof(PQLRC),
                    &dqlrc, sizeof(DQLRC));
            if (rc) return ;
            printf("x=%d y=%d rc=%d\n",
            dqlrc.xRaw, dqlrc.yRaw, dqlrc.rc);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else {
      printf("%s\n",EBC);
   } /* endif */

}

void doButCmd(void)
{
   if (butUnit ==0) {
      printf("Drive does not have a button device\n");
      return;
   } /* endif */
   if (p[0][0]=='s') {
      switch (p[0][2]) {
      case 'a':             //set button assignment
         {
            PSBA psba;
            psba.unit = (ULONG) butUnit;
            psba.buttonIndex = (ULONG) atol(p[1]);
            psba.action  = (ULONG) atol(p[2]);
            psba.value   = (ULONG) atol(p[3]);
            rc=doIOCTL(PEN_CAT_BUTTON,PEN_FUNC_SBA,
                    &psba, sizeof(PSBA),
                    NULL,0);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else if (p[0][0]=='q') {
      switch (p[0][2]) {
      case 'a':             //query button assignment
         {
            PQBA pqba;
            DQBA dqba;
            pqba.unit = (ULONG) butUnit;
            pqba.buttonIndex = (ULONG) atol(p[1]);
            rc=doIOCTL(PEN_CAT_BUTTON,PEN_FUNC_QBA,
                    &pqba, sizeof(PQBA),
                    &dqba, sizeof(DQBA));
            if (rc) return ;
            printf("action=%d value=%d\n", dqba.action, dqba.value);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else {
      printf("%s\n",EBC);
   } /* endif */

}

void doDspCmd(void)
{
   if (dspUnit ==0) {
      printf("Drive does not have a display device\n");
      return;
   } /* endif */
   if (p[0][0]=='s') {
      switch (p[0][2]) {
      case 's':             //set display state
         {
            PSDS psds;
            psds.unit = (ULONG) dspUnit;
            psds.command = (ULONG) atol(p[1]);
            rc=doIOCTL(PEN_CAT_DISPLAY,PEN_FUNC_SDS,
                    &psds, sizeof(PSDS),
                    NULL,0);
         }
         break;
      case 'i':             //set display inactive period
         {
            PSDIP psdip;
            psdip.unit =    (ULONG) dspUnit;
            psdip.command = (ULONG) atol(p[1]);
            psdip.period =  (ULONG) atol(p[2]);
            rc=doIOCTL(PEN_CAT_DISPLAY,PEN_FUNC_SDIP,
                    &psdip, sizeof(PSDIP),
                    NULL,0);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else if (p[0][0]=='q') {
      switch (p[0][2]) {
      case 's':             //query display state
         {
            PQDS pqds;
            DQDS dqds;
            pqds.unit = (ULONG) dspUnit;
            rc=doIOCTL(PEN_CAT_DISPLAY,PEN_FUNC_QDS,
                    &pqds, sizeof(PQDS),
                    &dqds, sizeof(DQDS));
            if (rc) return ;
            printf("state=%d auto=%x period=%d \n",
            dqds.state,dqds.automatic,dqds.period);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else {
      printf("%s\n",EBC);
   } /* endif */

}

void doUntCmd(void)
{
   if (p[0][0]=='s') {
      switch (p[0][2]) {
      case 's':             //set unit specific data
         {
            PSUSD psusd;
            SLUSD slusd;

            psusd.unit  = (ULONG) atol(p[1]);
            psusd.byteCount=sizeof(SLUSD);

            slusd.length = sizeof(SLUSD);
            slusd.Xorigin        = (ULONG) atol(p[2]);
            slusd.XmeasuredExtent= (ULONG) atol(p[3]);
            slusd.Yorigin        = (ULONG) atol(p[4]);
            slusd.YmeasuredExtent= (ULONG) atol(p[5]);
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_SUSD,
                    &psusd, sizeof(PSUSD),
                    &slusd, sizeof(SLUSD));
         }
         break;
      case 'v':             //set unit variable
         {
            PSUV  psuv;

            psuv.unit  = (ULONG) atol(p[1]);
            psuv.index = (ULONG) atol(p[2]);
            psuv.value = atol(p[3]);
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_SUV,
                    &psuv, sizeof(PSUV),
                    NULL,0);
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else if (p[0][0]=='q') {
      switch (p[0][2]) {
      case 's':             //query unit specific data
         {
            PQUSD pqusd;
            SLUSD slusd;
            PQUC  pquc;
            char * pdquc;


            pqusd.unit  = (ULONG) atol(p[1]);
            pqusd.byteCount=sizeof(SLUSD);
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUSD,
                    &pqusd,sizeof(PQUSD),
                    &slusd,sizeof(SLUSD));
            if (rc) return ;

            pdquc = dquc;
            pquc.unit  = (ULONG) atol(p[1]);
            pquc.byteCount = 100;
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUC,
                    &pquc, sizeof(PQUC),
                    &dquc, 100);
            if (rc) return ;

            if   ( (((CCAP*)pdquc)->device_type==DT_LOCATOR) &&
                 ((pqusd.rc==QUSD_OK)||(pqusd.rc==QUSD_TRUNC)) &&
                 (pqusd.capabilities & QUSD_STANDARD) ) {
               printf("XoriginDefault=%d XoriginAdj=%d Xmeasured=%d\n",
               slusd.XoriginDefault,slusd.Xorigin, slusd.XmeasuredExtent);
               printf("YoriginDefault=%d YoriginAdj=%d Ymeasured=%d\n",
               slusd.YoriginDefault,slusd.Yorigin, slusd.YmeasuredExtent);
            } else{
               printf("locator standard specific data is not available\n");
            } /* endif */
         }
         break;
      case 'v':             //query unit variable
         {
            PQUV  pquv;
            DQUV  dquv;

            pquv.unit  = (ULONG) atol(p[1]);

            pquv.index = (ULONG) atol(p[2]);

            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUV,
                    &pquv, sizeof(PQUV),
                    &dquv, sizeof(DQUV));
            if (rc) return ;
            printf("value = %d hex=%x\n",dquv.value,dquv.value);
         }
         break;
      case 'c':             //query unit capabilities
         {
            PQUC  pquc;
            char * pdquc;

            pdquc = dquc;
            pquc.unit  = (ULONG) atol(p[1]);
            pquc.byteCount = 100;
            rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUC,
                    &pquc, sizeof(PQUC),
                    &dquc, 100);
            if (rc) return ;
            switch (((CCAP*)pdquc)->device_type) {
            case DT_DRIVER:
               doDrvCap(((DDCAP*)pdquc));
               break;
            case DT_LOCATOR:
               doLocCap(((LCAP*)pdquc));
               break;
            case DT_BUTTON:
               doButCap(((BCAP*)pdquc));
               break;
            case DT_DISPLAY:
               doDspCap(((DCAP*)pdquc));
               break;
            default:
               printf("unknown device type\n",dquc[0]);
            } /* endswitch */
         }
         break;
      default:
         printf("%s\n",EBC);
      } /* endswitch */
   } else {
      printf("%s\n",EBC);
   } /* endif */

}

void showbut(void)
{
printf("button commands\n");
printf("  sba    i a v set button assignment(Index,Action,Value\n");
printf("         a - 0=null 1=hotKey 2=Shift 3=Appl 4=AugKey 5=GestureMode\n");
printf("         v - 4=button1 16=button2 64=button3\n");
printf("             1=KBD HotKey Ctrl+Esc  2=KBD HotKey Alt+Esc  \n");
printf("                                                          \n");
printf("  qba    i     query button assignment\n");
}

void showdsp(void)
{
printf("display commands\n");
printf("  sds    s     set display state s={1=on,0=off}\n");
printf("  sdip   c p   set display inactive period p=seconds\n");
printf("               c = 1  (0x01) set period\n");
printf("                   2  (0x02) enable auto\n");
printf("                   4  (0x04) disable auto\n");
printf("                   8  (0x08) enable opaque\n");
printf("                  16  (0x10) disable opaque\n");
printf("                  32  (0x20) enable suppress\n");
printf("                  64  (0x40) disable suppress\n");
printf("  qds          query display state\n");
}

void showloc(void)
{
printf("locator commands\n");
printf("  slo    x y   set locator offset\n");
printf("  slpr   #     set locator pass rate\n");
printf("  slsr   #     set locator sample rate\n");
printf("  qlv          query locator variables\n");
printf("  qlrc         query locator raw coordinate\n");
}

void showgen(void)
{
printf("general commands\n");
printf("  al     u     assign locator unit\n");
printf("  ab     u     assign button  unit\n");
printf("  ad     u     assign display unit\n");
printf("  an     d     assign driver name(0=emi,d=pen driver number)\n");
printf("  d{i,t,a,d,e,x,s} display int,tick,abs,data,error,dev dep,sys\n");
printf("  h{i,t,a,d,e,x,s} hide int,tick,abs,data,error,dev dep,sys\n");
printf("  p{i,t,a,d,e,x,s} page at int,tick,abs,data,error,dev dep,sys\n");
printf("  c{i,t,a,d,e,x,s} no page at int,tick,abs,data,error,dev dep,sys\n");
printf("  ? {u,b,l,d,g}  help \n");
printf("  h {u,b,l,d,g}  help \n");
printf("  quit                 quit \n");
}

void showunt(void)
{
printf("unit commands\n");
printf("  susd u xo xm yo ym set unit specific data \n");
printf("  suv  u v #   set unit varible \n");
printf("  rtt          reset trace table \n");
printf("  stts u s     set trace table size\n");
printf("  qusd u       query unit specific data \n");
printf("  quv  u v     query unit varible \n");
printf("  quc  u       query unit capabilities \n");
printf("  qtt          query trace table\n");
printf("  qtts         query trace table size\n");
}

void doHelp(void)
{
   switch (p[1][0]) {
   case 'b':
      showbut();
      break;
   case 'd':
      showdsp();
      break;
   case 'l':
      showloc();
      break;
   case 'g':
      showgen();
      break;
   case 'u':
      showunt();
      break;
   default:
      showunt();
      showdsp();
      showbut();
      showloc();
      showgen();
   } /* endswitch */
}

void usage(void)
{
printf("USAGE:    -q -f  -d name  -? \n");
printf("  where:  -f        not interactive\n");
printf("          -q        don't echo cmds\n");
printf("          -d  name  set driver name \n");
printf("          -?        print help\n");
printf("\n");
}

void doOPEN(ULONG drvNumber)
{
   ULONG   Action;

   strcpy(&(fileName[5]),emiusd.emidrv[drvNumber]);

   /* Close if already open */
   if (FileHandle) {
      rc=DosClose(FileHandle);
      if (rc != 0)
      {
          printf("DOSCLOSE return code = %d\n", rc);
      }
   } /* endif */

   /* Get a nect handle to use with DOSDEVIOCTL */

   Action = 2;
   rc = DosOpen(fileName,                   /* File path name */
                &FileHandle,                /* File handle */
                &Action,                    /* Action taken */
                FILE_SIZE,                  /* File primary allocation */
                FILE_NORMAL,                /* File attribute */
                OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
                OPEN_SHARE_DENYNONE |       /* Open mode of the file */
                OPEN_ACCESS_READWRITE,
                EABUF);                     /* No extended attributes */

   if (rc != 0)
   {
       printf("Cannot open device driver\n");
       printf("DOSOPEN return code = %d\n", rc);
       FileHandle=0;
   }
}

APIRET doIOCTL(ULONG category, ULONG function,
             PVOID pParams, LONG pcbParmLen,
             PVOID pData, LONG pcbDataLen)
{
   ULONG   ParmLengthInOut;
   ULONG   DataLengthInOut;
//   APIRET  rc;

   ParmLengthInOut = (ULONG) pcbParmLen;
   DataLengthInOut = (ULONG) pcbDataLen;
   rc = DosDevIOCtl(FileHandle, category, function,
                    pParams, (ULONG) pcbParmLen,&ParmLengthInOut,
                    pData, (ULONG) pcbDataLen,&DataLengthInOut);
   if (rc != 0)
   {
       printf("IOCTL failed, return code = %d\n", (SHORT)rc);
   }
   return(rc);
}

void doDump(void)
{
   LONG i   = 0;

   if (traceBuf[0] == 0) {
      printf("Trace buffer is empty\n");
   } else {
      for (i=traceBuf[0]; i >= 1;i--) {
         switch (traceBuf[i] & TRACE_MASK_SUB) {
         case TRACE_INT:
            if (showInt) {
               if (pageInt ) printf("\n");
               printf("INT ");
            } /* endif */
            break;
         case TRACE_TICK:
            if (showTick) {
               if (pageTick) printf("\n");
               printf("(tick %d) ",traceBuf[i]&~TRACE_MASK);
            } /* endif */
            break;
         case TRACE_SYS:
            if (showSys) {
               if (pageSys) printf("\n");
               printf("(Sys %2.2x) ",traceBuf[i]&~TRACE_MASK);
            } /* endif */
            break;
         case TRACE_DATA:
            if (showData) {
               if ((pageData)&&
                  ((traceBuf[i]&TRACE_MASK)==TRACE_DATA_1)) printf("\n");
               printf("%2.2x ",traceBuf[i]&~TRACE_MASK);
            } /* endif */
            break;
         case TRACE_ERROR:
            if (showErr) {
               printf("ERROR %d ",traceBuf[i]&~TRACE_MASK);
            } /* endif */
            break;
         case TRACE_ABS:
            if (showAbs) {
               switch (traceBuf[i] & TRACE_MASK) {
               case TRACE_ABS_E:
                  if (pageAbs ) printf("\n");
                  printf("(abs %4.4x ",traceBuf[i]&~TRACE_MASK);
                  break;
               case TRACE_ABS_C:
                  if (pageAbs ) printf("\n");
                  printf("(eiq %4.4x ",traceBuf[i]&~TRACE_MASK);
                  break;
               case TRACE_ABS_D:
                  printf("%4.4x ",traceBuf[i]&~TRACE_MASK);
                  break;
               case TRACE_ABS_X:
                  printf("%d ",traceBuf[i]&~TRACE_MASK);
                  break;
               case TRACE_ABS_Y:
                  printf("%d ",traceBuf[i]&~TRACE_MASK);
                  break;
               case TRACE_ABS_Z:
                  printf("%d)",traceBuf[i]&~TRACE_MASK);
                  break;
               default:
                  printf("(invalid %x)",traceBuf[i]);
               } /* endswitch */
            } /* endif */
            break;
         case TRACE_DD:
            if (showDD ) {
               if ( (pageDD) &&
                    (((traceBuf[i]&0x0FF0000)>>16)==0) ) printf("\n");
               printf("DD%d=%x ",
               (traceBuf[i]&0x0FF0000)>>16,traceBuf[i]&0x0FFFF);
            } /* endif */
            break;
         default:
            printf("(invalid %x)",traceBuf[i]);
         } /* endswitch */
      } /* endfor */
      printf("\n");
   } /* endif */
}

void doDrvCap(DDCAP * ddcap)
{
   doCCap(((CCAP*)ddcap));
   printf("unit count=%d\n",ddcap->unitCount);
   printf("capabilites=%x\n",ddcap->capabilites);
   printf("driver major level=%d\n",ddcap->rev_major);
   printf("driver minor level=%d\n",ddcap->rev_minor);
   printf("IOCTL interface major level=%d\n",ddcap->ioc_major);
   printf("IOCTL interface minor level=%d\n",ddcap->ioc_minor);
   printf("Extended interface major level=%d\n",ddcap->eif_major);
   printf("Extended interfcae minor level=%d\n",ddcap->eif_minor);
   printf("DDS IDC interface major level=%d\n",ddcap->idc_major);
   printf("DDS IDC interfcae minor level=%d\n",ddcap->idc_minor);
}
void doLocCap(LCAP * lcap)
{
   doCCap(((CCAP*)lcap));
   printf("type=%x caps=%x num_mouse_but=%d barrel_num=%d barrel_mask=%x\n",
           lcap->type, lcap->caps, lcap->num_mouse_but,
           lcap->barrel_num, lcap->barrel_mask);
   printf("sample_rate=%d pass_rate=%d max_sample_rate=%d\n",
           lcap->sample_rate, lcap->pass_rate, lcap->max_sample_rate);
   printf("dev_x_extent=%d dev_y_extent=%d std_x_extent=%d std_y_extent=%d\n",
           lcap->dev_x_extent, lcap->dev_y_extent,lcap->std_x_extent, lcap->std_y_extent );
   printf("dev_z_p_extent=%d dev_z_h_extent=%d\n",
           lcap->dev_z_p_extent, lcap->dev_z_h_extent);
   printf("dev_x_res=%d dev_y_res=%d std_res=%d dev_timestampRes=%d\n",
           lcap->dev_x_res, lcap->dev_y_res, lcap->std_res,
           lcap->dev_timestampRes);
}
void doButCap(BCAP * bcap)
{
   doCCap(((CCAP*)bcap));
   printf("num=%d\n",bcap->num);
   printf("typeMask   =%4.4x\n",bcap->typeMask);
   printf("nullMask   =%4.4x\n",bcap->nullMask);
   printf("barrel     =%4.4x\n",bcap->barrel);
   printf("nonBarrel  =%4.4x\n",bcap->nonBarrel);
   printf("hotKeyMask =%4.4x\n",bcap->hotKeyMask);
   printf("shiftMask  =%4.4x\n",bcap->shiftMask);
   printf("appKeyMask =%4.4x\n",bcap->appKeyMask);
   printf("augKeyMask =%4.4x\n",bcap->augKeyMask);
   printf("gesKeyMask =%4.4x\n",bcap->gesKeyMask);
}
void doDspCap(DCAP * dcap)
{
   doCCap(((CCAP*)dcap));
   printf("type=%x\n",dcap->type);
   printf("autoflag=%d\n",dcap->auto_flag);
   printf("height=%d width=%d\n",dcap->height,dcap->width);
}
void doCCap(CCAP * ccap)
{
   char pbuf1[9];
   char pbuf2[SIZEOF_DEVICE_NAME+1];
   int  i;

   for (i=0; i<9; i++) {pbuf1[i]=0;}
   strncpy (pbuf1,ccap->driver_name,8);

   for (i=0; i< SIZEOF_DEVICE_NAME+1; i++) {pbuf2[i]=0;}
   strncpy (pbuf2,ccap->device_name, SIZEOF_DEVICE_NAME);



   printf("--- common capabilities -----------------------------------------\n");
   printf("driver_name=%s device_name=%s\n",pbuf1,pbuf2);
   printf("length=%d device_type=%d device_id=%d unit=%d\n",
   ccap->length,ccap->device_type,ccap->device_id,ccap->unit);
   printf("--- device type specific capabilities ---------------------------\n");
}

void chkLevel(void)
{
  PQUC  pquc;
  DDCAP ddcap;
  char * pdquc;

  pdquc = dquc;
  pquc.unit  = 0;
  pquc.byteCount = sizeof(DDCAP);
  rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUC,
          &pquc, sizeof(PQUC),
          &ddcap,sizeof(DDCAP));
  if (rc) {
     printf("ERROR reading driver capabilities\n");
     return ;
  }

  if (ddcap.ioc_major != PEN_IOCTL_LEV_MAJOR) {
      printf("WARNING IOCTL major level mismatch, driver = %d, mine = %d\n",
      ddcap.ioc_major,PEN_IOCTL_LEV_MAJOR);
  } /* endif */

  if (ddcap.ioc_minor != PEN_IOCTL_LEV_MINOR) {
      printf("WARNING IOCTL minor level mismatch, driver = %d, mine = %d\n",
      ddcap.ioc_minor,PEN_IOCTL_LEV_MINOR);
  } /* endif */

  if (ddcap.eif_major != PEN_EI_LEV_MAJOR) {
      printf("WARNING EI major level mismatch, driver = %d, mine = %d\n",
      ddcap.eif_major,PEN_EI_LEV_MAJOR);
  } /* endif */

  if (ddcap.eif_minor != PEN_EI_LEV_MINOR) {
      printf("WARNING EI  minor level mismatch, driver = %d, mine = %d\n",
      ddcap.eif_minor,PEN_EI_LEV_MINOR);
  } /* endif */


}

void initAD(void)
{
   PQUSD pqusd;

   strcpy(emiusd.emidrv[0],"EMI$");
   doOPEN(0);

   pqusd.unit  = 0;
   emiusd.length=pqusd.byteCount=sizeof(EMIUSD);
   rc=doIOCTL(PEN_CAT_DRIVER,PEN_FUNC_QUSD,
           &pqusd,sizeof(PQUSD),
           &emiusd,sizeof(EMIUSD));
   if (rc) return ;

}


void doXXXCmd(void)
{

}
