home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!dtix!relay!afterlife!adm!news
- From: marks@aivax.rl.af.mil (David Marks)
- Newsgroups: comp.sys.sgi
- Subject: tablet driver
- Message-ID: <31572@adm.brl.mil>
- Date: 29 Jul 92 11:37:02 GMT
- Sender: news@adm.brl.mil
- Lines: 352
-
- I modified the old example graphics tablet driver which used to be included
- in 4Dgifts to work with a SummaGraphics tablet. Towards the end of the program
- the code initializes a serial port, then sends commands to the serial port to
- configure the tablet. This was done while 3.2 (or 3.3.2) was runnign, back
- when the WAS a tabletd running. Now its done as part of the X-Server.
- All I did was change the Hitatchi codes to the Summagraphics codes, which I
- got from the Summagraphics manual, and add some more flexible serial I/O
- code, and allowed one to change the MODE that the tablet uses (send while
- in proximity, send on contact, send on button press, etc...) And, try
- as I could, I just couldn't squeeze the state of 4 buttons into 3 bits...
-
-
-
- Dave Marks
- Rome Laboratory
- marks@ra.rl.af.mil
-
- -------------------------
- tabletd.c
- -------------------------
- /*
- * I modified this to work with a Summagraphics Summasketch
- * tablet. Tally-Ho!
- * David L. Marks - 1991
- */
-
- /*
- * 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
- */
-
-
- #include "gl.h"
- #include "device.h"
- #include <stdio.h>
- #include <fcntl.h>
- #include <termio.h>
- #include <signal.h>
-
- #define MAPTOSCREEN
-
-
- #define TABLETXMAX 2900
- #define TABLETYMAX 2900
-
- #ifdef RAWCOORDS
- #define COORDMAP(x) (x)
- #endif
-
- #ifdef MAPTOSCREEN
- #define COORDMAP(x) (((x)*XMAXSCREEN)/TABLETXMAX)
- #endif
-
- int l, m, r, f;
- int x, y;
- FILE *inf;
- struct termio term, sterm;
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- register unsigned char c;
-
- if(argc<2) {
- fprintf(stderr,"usage: tabletd </dev/tty?>\n");
- exit(1);
- }
- inf = fopen(argv[1],"r+");
- if(!inf) {
- fprintf(stderr,"tabletd: can't open %s\n",argv[1]);
- exit(1);
- }
- f = fileno(inf);
- x = 0;
- y = 0;
- init();
- while(1) {
- c = fgetc(inf);
- bitpad_softchar(c);
- }
- }
-
- int synced, state;
- int x, y, ox, oy, obut;
- int b0, b1, b2, b3;
- int but;
- /* The old driver interfaced to gl using a 4-bit code for the button status */
- /* The summasketch uses a 3-bit code (information loss??) for its four */
- /* buttons, so, lets map the 3-bit code to the four bit code */
- /* The only multi-button combinations I support are 1&4, 2&4, 1&2&4 */
- /* Note: it is tough to get a multi-button hit reliably. Try 2&4 and you */
- /* get 2 then 4 or vice versa. */
- int new_but[8]= {0x00, 0x01, 0x02, 0x04,
- 0x08, 0x09, 0x0A, 0x0B };
-
- #define SYNCHBIT 0x80
- #define LOW_3_BITS 0x07
-
- /*
- * bitpad_softchar -
- * This inteprets characters in bitpad I compatable format.
- */
-
- bitpad_softchar( onechar )
- register unsigned int onechar;
- {
- int xsign, ysign;
- int tbut;
-
- onechar &= 0xff;
- 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;
- state++;
-
- #define X_SIGN_SHIFT 4
- #define Y_SIGN_SHIFT 3
- /* but has the sign information for x and y */
- xsign = (but >>X_SIGN_SHIFT) & 0x01;
- /* one (1) is positive, zero (0) negative */
- if (!xsign)
- x *= -1;
- ysign = (but >>Y_SIGN_SHIFT) & 0x01;
- if (!ysign)
- y *= -1;
- if(x != ox) { /* low x */
- ox = x;
- gl_changedevice(BPADX,COORDMAP(x));
- }
- if(y != oy) {
- oy = y;
- gl_changedevice(BPADY,COORDMAP(y));
- }
- #ifdef DEBUG
- printf(" x = %d, y = %d, button = %x (hex)\n", x, y, but);
- #endif
- tbut = but;
- tbut &= LOW_3_BITS; /* take the low three bits */
- /* now translate the bits to what the SGI driver wants */
- but = new_but[tbut];
- 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);
- }
- }
- break;
- case (4):
- if ( (onechar & SYNCHBIT) == 0 ) {
- /* if the synch bit IS NOT on this char */
- synced = 0; /* then we ARE NOT synched */
- state = 0;
- break;
- }
- /* otherwise, we are in synch */
- but = (onechar & 0xff); /* save the whole status, not just buttons*/
-
- state = 0;
- break;
- } /* end switch */
- } else {
- if(onechar & SYNCHBIT) { /* if the synch bit is on this char */
- synced = 1; /* then we are synched */
- /* It is from this character that we get the button info */
- /* and things that the old driver didn't care about (apparently) */
- /* like proximity, tablet identifier, coordinate sign. */
- but = (onechar & 0xff); /* save the whole status, not just buttons*/
- }
- state = 0;
- }
- } /* end bitpad_softchar */
-
- init()
- {
-
- /* Primary Modes */
-
- /* Send reports continuously (and quickly !) whether or not button is pressed */
- #define STREAM_MODE 0x40
-
- /* Send reports continuously only when button is pressed (pencil mode?) */
- #define SWITCH_STREAM_MODE 0x41
-
- /* Send one (1) report only when a button is pressed */
- #define POINT_MODE 0x42
-
- /* Send one (1) report only when the host asks for one via the request report*/
- /* command. */
- #define REMOTE_REQUEST_MODE 0x44
-
-
- /* Modifiers (Secondary Modes) */
-
- /* The report contains only button, delta-x, delta-y info */
- /* THIS DRIVER DOES NOT SUPPORT THIS MODE RIGHT NOW!!! DON'T EVEN THINK */
- /* ABOUT "TRYING IT OUT", SINCE THIS MODE YIELDS 3-BYTE REPORTS, WHILE */
- /* NON-DELTA MODE YIELDS 5-BYTE REPORTS. Thank You... */
- #define DELTA_MODE 0x45
-
- /* This mode sets a threshold level that must be met before a report is */
- /* sent. This only makes sense when the primary mode is either continuous */
- /* or switch continuous. The tablet generates a report only after the stylus */
- /* has been moved the specified number of units. Setting the increment to */
- /* one has the nice property of generating reports only when the stylus is */
- /* moved. */
- #define INCREMENT_MODE 0x49
-
- /* After setting the secondary mode to INCREMENT_MODE, you must say what the */
- /* threshold level (increment) is. You can choose 0-32 (decimal, 0-20 hex)*/
- /* Add your chosen threshold level to the INCREMENT_BASE and send that */
- /* to the tablet. */
- #define INCREMENT_BASE 0x20
-
- /* used to get the tablet report when in REMOTE_REQUEST primary mode */
- #define REMOTE_TRIGGER_CMD 0x50
-
- /* Factor to reduce the rate of report transmission. At 9600 BPS, the tablet */
- /* generates about 120 reports/second, which may be too much. Send the */
- /* tablet one of these below to reduce the rate by a factor of 0, 2, 8 or 32 */
- #define MAX_RATE 0x51
- #define MAX_RATE_DIV_2 0x52
- #define MAX_RATE_DIV_8 0x53
- #define MAX_RATE_DIV_32 0x54
-
-
- /* user defineable parameters */
-
- /* Only matters if you use INCREMENT_MODE. Change this at will, but make sure */
- /* the value is 0 < x < 33 (decimal). */
- #define DESIRED_INCREMENT 1
-
- char tab_msg;
-
- 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_lflag = 0;
-
- /* If its not obvious, this is where you would change the baud rate */
- /* if you want something other than 9600 */
- term.c_cflag = B9600 | CS8 | CREAD ;
- 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);
- }
-
- /* put the tablet into the right modes */
-
- /* set the appropriate primary mode */
- /* I chose POINT_MODE because it sends a report only when a button is */
- /* pressed. */
- tab_msg = POINT_MODE;
- write(f, &tab_msg, 1);
-
- /* set the secondary mode, if desired. if not, comment out */
- /* tab_msg = INCREMENT_MODE; */
- /* write(f, &tab_msg, 1); */
-
-
- /* sets the increment value , only if the secondary mode is INCREMENT*/
- /* tab_msg = INCREMENT_BASE + DESIRED_INCREMENT; */
- /* write(f, &tab_msg, 1); */
-
-
- /* set the report rate */
- tab_msg = MAX_RATE_DIV_8;
- write(f, &tab_msg, 1);
-
- }
-
- ----------------------------
- Makefile
- ----------------------------
- SHELL = /bin/sh
- # the iristools/include is for rasterfile.h for iisc
- # The include directory under
- CFLAGS = -g -I/usr/include/gl -DDEBUG
- LDFLAGS = -lgl_s -lm
- ALL = tabletd
-
- all: $(ALL)
-
- clean:
- rm -f *.o $(ALL)
-
- tabletd : $$@.c
- $(CC) $(CFLAGS) -o $@ $@.c $(LDFLAGS)
-
-
- ---------------------------
-