[comp.sys.sgi] Tablet Daemon

blbates@AERO36.LARC.NASA.GOV (Brent Bates ViGYAN AAD/TAB) (05/29/91)

   I got the tablet daemon working with the Kurta tablet we have.  The main
thing that needed to be done was to be able to change all the serial port
parameters.  I also found a bug in the daemon too, and have corrected it.
Below is the modified and corrected IRIX 3.2 tablet daemon from
/usr/people/4Dgifts/examples/devices.  Hopefully, SGI will add these options
and corrections to the executable they ship, along with any enhancements they
may have.  If you have any questions, drop me a line.

------------------------------- Cut Here ---------------------------
/*
 *      tablet -
 *              This is the tablet reader for the Hitachi tablet.  The 
 *      Hitachi tablet is 11" x 11" and has 200 points per inch.
 *
 *      Define RAWCOORDS to get raw tablet coordinates.  In this case,
 *      tablet values will be between 0 and TABLETXMAX in X and between
 *      0 and TABLETYMAX in Y.  If the cursor is attached to the tablet,
 *      the lower left hand corner of the tablet maps into the screen
 *      area, since tablet values exceed XMAXSCREEN and YMAXSCREEN.
 *
 *      Define MAPTOSCREEN to get tablet coords that map the lower part
 *      of the tablet to screen coordinaes.  In this case tablet values 
 *      will be between 0 and XMAXSCREEN in X and between 0 and XMAXSCREEN 
 *      in Y.  If the cursor is attached to the tablet, the whole bottom
 *      area of the tablet maps into the screen area.
 *
 *      The (default) tablet daemon that is installed in /etc/gl/tabletd 
 *      is equivalent to this program with RAWCOORDS defined.  If you wish 
 *      to map the entire width of the tablet onto the screen, then 
 *      recompile this with MAPTOSCREEN defined.  Then, become superuser 
 *      and move /etc/gl/tabletd to /etc/gl/tabletd.default and move the
 *      new, recomplied version of this program into /etc/gl/tabletd.
 *      You can either reboot to run the new version, or as superuser,
 *      execute "tabletd /dev/tablet &" and the mapping will now reflect
 *      the fulll width of the Hitachi tablet.
 *
 *                                Paul Haeberli - 1986
 *
 *   Brent L. Bates, blbates@aero36.larc.nasa.gov:
 *                  Added all serial port options; baud rate, character size,
 *                                                 stop bits, and parity
 *                  Also corrected bug in status byte usage.  Status byte for
 *                        first data set was ignored and status byte for next
 *                        data set was used for last set of data, etc.
 *                                                            April 18, 1991
 */
#include <gl.h>
#include <device.h>
#include <stdio.h>
#include <fcntl.h>
#include <termio.h>
#include <signal.h>

#define RAWCOORDS

#define TABLETXMAX        2200
#define TABLETYMAX        2200

#ifdef RAWCOORDS
#define COORDMAP(x)        (x)
#endif

#ifdef MAPTOSCREEN
#define COORDMAP(x)        (((x)*XMAXSCREEN)/TABLETXMAX)
#endif

#define PARNONE  0
#define STOPONE  0

int l, m, r, f;
int x, y;
FILE *inf;
struct termio term, sterm;
tcflag_t controlmodes;

main(argc,argv)
int argc;
char *argv[];
{
   extern char *optarg;
   extern int optind;
   extern tcflag_t controlmodes;
   register unsigned char c;
   int option, usage=0;
   tcflag_t baudrate=B9600,charactersize=CS8,parity=PARNONE,stopbits=STOPONE;

   /* parse arguments */
   while ((option = getopt(argc, argv, "b:c:p:s:")) != -1) {
      switch (option) {
         /* -b Baud Rate */
         case 'b':
            if(!strcmp(optarg,"50")){
               baudrate=B50;
            } else if(!strcmp(optarg,"75")){
               baudrate=B75;
            } else if(!strcmp(optarg,"110")){
               baudrate=B110;
            } else if(!strcmp(optarg,"134")){
               baudrate=B134;
            } else if(!strcmp(optarg,"150")){
               baudrate=B150;
            } else if(!strcmp(optarg,"200")){
               baudrate=B200;
            } else if(!strcmp(optarg,"300")){
               baudrate=B300;
            } else if(!strcmp(optarg,"600")){
               baudrate=B600;
            } else if(!strcmp(optarg,"1200")){
               baudrate=B1200;
            } else if(!strcmp(optarg,"1800")){
               baudrate=B1800;
            } else if(!strcmp(optarg,"2400")){
               baudrate=B2400;
            } else if(!strcmp(optarg,"4800")){
               baudrate=B4800;
            } else if(!strcmp(optarg,"9600")){
               baudrate=B9600;
            } else if(!strcmp(optarg,"19200")){
               baudrate=B19200;
            } else if(!strcmp(optarg,"38400")){
               baudrate=B38400;
            } else if(!strcmp(optarg,"exta")){
               baudrate=EXTA;
            } else if(!strcmp(optarg,"extb")){
               baudrate=EXTB;
            } else {
               fprintf(stderr,"Valid Baud Rates: 50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,exta,extb\n");
               exit(1);
            }
         /* -c Character Size */
            break;
         case 'c':
            if(!strcmp("5",optarg)){
               charactersize=CS5;
            } else if(!strcmp("6",optarg)){
               charactersize=CS6;
            } else if(!strcmp("7",optarg)){
               charactersize=CS7;
            } else if(!strcmp("8",optarg)){
               charactersize=CS8;
            } else {
               fprintf(stderr,"Valid Character Sizes: 5, 6, 7, 8\n");
               exit(1);
            }
            break;
         /* -p Parity */
         case 'p':
            if(!strcmp("none",optarg)) {
               parity=PARNONE;
            } else if(!strcmp("even",optarg)) {
               parity=PARENB;
            } else if(!strcmp("odd",optarg)) {
               parity=PARENB|PARODD;
            } else {
               fprintf(stderr,"Valid Parity Options: none, even, odd\n");
               exit(1);
            }
            break;
         /* -s Stop Bits */
         case 's':
            if(!strcmp("1",optarg)){
               stopbits=STOPONE;
            } else if(!strcmp("2",optarg)){
               stopbits=CSTOPB;
            } else {
               fprintf(stderr,"Valid Stop Bits: 1 and 2\n");
               exit(1);
            }
            break;
         default:
            usage++;
      }
   }
   if(strncmp("/dev/tty",argv[argc-1],8)) usage++;
   if(usage) {
      fprintf(stderr,"usage: %s [-b baud rate] [-d character size] [-p parity] [-s stop bits] </dev/ttyf?>\n", argv[0]);
      exit(1);
   }
   controlmodes=baudrate|charactersize|parity|stopbits;
   inf = fopen(argv[argc-1],"r+");
   if(!inf) {
      fprintf(stderr,"tabletd: can't open %s\n",argv[argc-1]);
      exit(1);
   }
   f = fileno(inf);
   x = 0;
   y = 0;
   init();
   while(1) {
      c = fgetc(inf);
      bitpad_softchar(c);
   }
}

Boolean synced=FALSE;
int state=0;
int x, y, ox, oy, obut=0;
int b0=0,b1=0,b2=0,b3=0;

#define SYNCHBIT        0x40

/*
 *        bitpad_softchar -
 *                This inteprets characters in bitpad I compatable format.
 */
bitpad_softchar( onechar )
register unsigned int onechar;
{
   static short but;

   onechar &= 0x7f;	/* Mask Off Parity Bit */
   if(synced) {
      switch(state) {
         case 0: x = onechar & 0x3f;
            state++;
            break;
         case 1: x |= (onechar & 0x3f)<<6;
            state++;
            break;
         case 2: y = onechar & 0x3f;
            state++;
            break;
         case 3: y |= (onechar & 0x3f)<<6;
            if(x != ox) {
               ox=x;
               gl_changedevice(BPADX,COORDMAP(x));      
            }
            if(y != oy) {
               oy=y;
               gl_changedevice(BPADY,COORDMAP(y));      
            }
            if(but != obut) {
               obut = but;
               if((but&1) != b0) {
                  b0 = but&1 ;
                  gl_changedevice(BPAD0,b0);
               }
               but >>= 1;
               if((but&1) != b1) {
                  b1 = but&1 ;
                  gl_changedevice(BPAD1,b1);
               }
               but >>= 1;
               if((but&1) != b2) {
                  b2 = but&1;
                  gl_changedevice(BPAD2,b2);
               }
               but >>= 1;
               if((but&1) != b3) {
                  b3 = but&1;
                  gl_changedevice(BPAD3,b3);
               }
            }
            state++;
            break;
         case 4:
            if(onechar & SYNCHBIT){
               but=(onechar & 0x3f)>>2;	/* Mask Off Excess Bits and Shift*/
               state=0;
            } else {
               synced=FALSE;	/* Out of Synch */
               state=0;
            }
            break;
      }
   } else {
      if(onechar & SYNCHBIT){
         but=(onechar & 0x3f)>>2;	/* Mask Off Excess Bits and Shift*/
         synced=TRUE;	/* All Synch'ed Up */
      }
      state=0;
   }
} 

init()
{
   extern tcflag_t controlmodes;

   if (ioctl(f, TCGETA, &term) == -1) {
      fprintf(stderr,"tabletd: ioctl(TCGETA) failed\n");
      perror("init");
      return(0);
   }
   sterm = term;

   /* change the modes */
   term.c_iflag = IGNBRK | IGNPAR;
   term.c_oflag = 0;
   term.c_cflag = controlmodes|CREAD;
   term.c_lflag = 0;
   term.c_cc[VMIN] = 1;
   term.c_cc[VTIME] = 0;

   if (ioctl(f, TCSETA, &term) == -1) {
      fprintf(stderr,"tabletd: ioctl(TCSETA) failed\n");
      perror("init");
      return(0);
   }
   gl_changedevice(BPAD0,0);
   gl_changedevice(BPAD1,0);
   gl_changedevice(BPAD2,0);
   gl_changedevice(BPAD3,0);
}

  Brent L. Bates				Phone:(804) 864-2854
  NASA-Langley Research Center			  FAX:(804) 864-6792
  M.S. 361
  Hampton, Virginia  23665-5225
  E-mail: blbates@aero36.larc.nasa.gov or blbates@aero8.larc.nasa.gov