|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)tty_tb.c 7.5 (Berkeley) 5/9/89 ! 7: */ ! 8: ! 9: #include "tb.h" ! 10: #if NTB > 0 ! 11: ! 12: /* ! 13: * Line discipline for RS232 tablets; ! 14: * supplies binary coordinate data. ! 15: */ ! 16: #include "param.h" ! 17: #include "user.h" ! 18: #include "tablet.h" ! 19: #include "tty.h" ! 20: ! 21: /* ! 22: * Tablet configuration table. ! 23: */ ! 24: struct tbconf { ! 25: short tbc_recsize; /* input record size in bytes */ ! 26: short tbc_uiosize; /* size of data record returned user */ ! 27: int tbc_sync; /* mask for finding sync byte/bit */ ! 28: int (*tbc_decode)();/* decoding routine */ ! 29: char *tbc_run; /* enter run mode sequence */ ! 30: char *tbc_point; /* enter point mode sequence */ ! 31: char *tbc_stop; /* stop sequence */ ! 32: char *tbc_start; /* start/restart sequence */ ! 33: int tbc_flags; ! 34: #define TBF_POL 0x1 /* polhemus hack */ ! 35: #define TBF_INPROX 0x2 /* tablet has proximity info */ ! 36: }; ! 37: ! 38: static int tbdecode(), gtcodecode(), poldecode(); ! 39: static int tblresdecode(), tbhresdecode(); ! 40: ! 41: struct tbconf tbconf[TBTYPE] = { ! 42: { 0 }, ! 43: { 5, sizeof (struct tbpos), 0200, tbdecode, "6", "4" }, ! 44: { 5, sizeof (struct tbpos), 0200, tbdecode, "\1CN", "\1RT", "\2", "\4" }, ! 45: { 8, sizeof (struct gtcopos), 0200, gtcodecode }, ! 46: {17, sizeof (struct polpos), 0200, poldecode, 0, 0, "\21", "\5\22\2\23", ! 47: TBF_POL }, ! 48: { 5, sizeof (struct tbpos), 0100, tblresdecode, "\1CN", "\1PT", "\2", "\4", ! 49: TBF_INPROX }, ! 50: { 6, sizeof (struct tbpos), 0200, tbhresdecode, "\1CN", "\1PT", "\2", "\4", ! 51: TBF_INPROX }, ! 52: { 5, sizeof (struct tbpos), 0100, tblresdecode, "\1CL\33", "\1PT\33", 0, 0}, ! 53: { 6, sizeof (struct tbpos), 0200, tbhresdecode, "\1CL\33", "\1PT\33", 0, 0}, ! 54: }; ! 55: ! 56: /* ! 57: * Tablet state ! 58: */ ! 59: struct tb { ! 60: int tbflags; /* mode & type bits */ ! 61: #define TBMAXREC 17 /* max input record size */ ! 62: char cbuf[TBMAXREC]; /* input buffer */ ! 63: union { ! 64: struct tbpos tbpos; ! 65: struct gtcopos gtcopos; ! 66: struct polpos polpos; ! 67: } rets; /* processed state */ ! 68: #define NTBS 16 ! 69: } tb[NTBS]; ! 70: ! 71: /* ! 72: * Open as tablet discipline; called on discipline change. ! 73: */ ! 74: /*ARGSUSED*/ ! 75: tbopen(dev, tp) ! 76: dev_t dev; ! 77: register struct tty *tp; ! 78: { ! 79: register struct tb *tbp; ! 80: ! 81: if (tp->t_line == TABLDISC) ! 82: return (ENODEV); ! 83: ttywflush(tp); ! 84: for (tbp = tb; tbp < &tb[NTBS]; tbp++) ! 85: if (tbp->tbflags == 0) ! 86: break; ! 87: if (tbp >= &tb[NTBS]) ! 88: return (EBUSY); ! 89: tbp->tbflags = TBTIGER|TBPOINT; /* default */ ! 90: tp->t_cp = tbp->cbuf; ! 91: tp->t_inbuf = 0; ! 92: bzero((caddr_t)&tbp->rets, sizeof (tbp->rets)); ! 93: tp->T_LINEP = (caddr_t)tbp; ! 94: tp->t_flags |= LITOUT; ! 95: return (0); ! 96: } ! 97: ! 98: /* ! 99: * Line discipline change or last device close. ! 100: */ ! 101: tbclose(tp) ! 102: register struct tty *tp; ! 103: { ! 104: register int s; ! 105: int modebits = TBPOINT|TBSTOP; ! 106: ! 107: tbioctl(tp, BIOSMODE, &modebits, 0); ! 108: s = spltty(); ! 109: ((struct tb *)tp->T_LINEP)->tbflags = 0; ! 110: tp->t_cp = 0; ! 111: tp->t_inbuf = 0; ! 112: tp->t_rawq.c_cc = 0; /* clear queues -- paranoid */ ! 113: tp->t_canq.c_cc = 0; ! 114: tp->t_line = 0; /* paranoid: avoid races */ ! 115: splx(s); ! 116: } ! 117: ! 118: /* ! 119: * Read from a tablet line. ! 120: * Characters have been buffered in a buffer and decoded. ! 121: */ ! 122: tbread(tp, uio) ! 123: register struct tty *tp; ! 124: struct uio *uio; ! 125: { ! 126: register struct tb *tbp = (struct tb *)tp->T_LINEP; ! 127: register struct tbconf *tc = &tbconf[tbp->tbflags & TBTYPE]; ! 128: int ret; ! 129: ! 130: if ((tp->t_state&TS_CARR_ON) == 0) ! 131: return (EIO); ! 132: ret = uiomove(&tbp->rets, tc->tbc_uiosize, uio); ! 133: if (tc->tbc_flags&TBF_POL) ! 134: tbp->rets.polpos.p_key = ' '; ! 135: return (ret); ! 136: } ! 137: ! 138: /* ! 139: * Low level character input routine. ! 140: * Stuff the character in the buffer, and decode ! 141: * if all the chars are there. ! 142: * ! 143: * This routine could be expanded in-line in the receiver ! 144: * interrupt routine to make it run as fast as possible. ! 145: */ ! 146: tbinput(c, tp) ! 147: register int c; ! 148: register struct tty *tp; ! 149: { ! 150: register struct tb *tbp = (struct tb *)tp->T_LINEP; ! 151: register struct tbconf *tc = &tbconf[tbp->tbflags & TBTYPE]; ! 152: ! 153: if (tc->tbc_recsize == 0 || tc->tbc_decode == 0) /* paranoid? */ ! 154: return; ! 155: /* ! 156: * Locate sync bit/byte or reset input buffer. ! 157: */ ! 158: if (c&tc->tbc_sync || tp->t_inbuf == tc->tbc_recsize) { ! 159: tp->t_cp = tbp->cbuf; ! 160: tp->t_inbuf = 0; ! 161: } ! 162: *tp->t_cp++ = c&0177; ! 163: /* ! 164: * Call decode routine only if a full record has been collected. ! 165: */ ! 166: if (++tp->t_inbuf == tc->tbc_recsize) ! 167: (*tc->tbc_decode)(tc, tbp->cbuf, &tbp->rets); ! 168: } ! 169: ! 170: /* ! 171: * Decode GTCO 8 byte format (high res, tilt, and pressure). ! 172: */ ! 173: static ! 174: gtcodecode(tc, cp, tbpos) ! 175: struct tbconf *tc; ! 176: register char *cp; ! 177: register struct gtcopos *tbpos; ! 178: { ! 179: ! 180: tbpos->pressure = *cp >> 2; ! 181: tbpos->status = (tbpos->pressure > 16) | TBINPROX; /* half way down */ ! 182: tbpos->xpos = (*cp++ & 03) << 14; ! 183: tbpos->xpos |= *cp++ << 7; ! 184: tbpos->xpos |= *cp++; ! 185: tbpos->ypos = (*cp++ & 03) << 14; ! 186: tbpos->ypos |= *cp++ << 7; ! 187: tbpos->ypos |= *cp++; ! 188: tbpos->xtilt = *cp++; ! 189: tbpos->ytilt = *cp++; ! 190: tbpos->scount++; ! 191: } ! 192: ! 193: /* ! 194: * Decode old Hitachi 5 byte format (low res). ! 195: */ ! 196: static ! 197: tbdecode(tc, cp, tbpos) ! 198: struct tbconf *tc; ! 199: register char *cp; ! 200: register struct tbpos *tbpos; ! 201: { ! 202: register char byte; ! 203: ! 204: byte = *cp++; ! 205: tbpos->status = (byte&0100) ? TBINPROX : 0; ! 206: byte &= ~0100; ! 207: if (byte > 036) ! 208: tbpos->status |= 1 << ((byte-040)/2); ! 209: tbpos->xpos = *cp++ << 7; ! 210: tbpos->xpos |= *cp++; ! 211: if (tbpos->xpos < 256) /* tablet wraps around at 256 */ ! 212: tbpos->status &= ~TBINPROX; /* make it out of proximity */ ! 213: tbpos->ypos = *cp++ << 7; ! 214: tbpos->ypos |= *cp++; ! 215: tbpos->scount++; ! 216: } ! 217: ! 218: /* ! 219: * Decode new Hitach 5-byte format (low res). ! 220: */ ! 221: static ! 222: tblresdecode(tc, cp, tbpos) ! 223: struct tbconf *tc; ! 224: register char *cp; ! 225: register struct tbpos *tbpos; ! 226: { ! 227: ! 228: *cp &= ~0100; /* mask sync bit */ ! 229: tbpos->status = (*cp++ >> 2) | TBINPROX; ! 230: if (tc->tbc_flags&TBF_INPROX && tbpos->status&020) ! 231: tbpos->status &= ~(020|TBINPROX); ! 232: tbpos->xpos = *cp++; ! 233: tbpos->xpos |= *cp++ << 6; ! 234: tbpos->ypos = *cp++; ! 235: tbpos->ypos |= *cp++ << 6; ! 236: tbpos->scount++; ! 237: } ! 238: ! 239: /* ! 240: * Decode new Hitach 6-byte format (high res). ! 241: */ ! 242: static ! 243: tbhresdecode(tc, cp, tbpos) ! 244: struct tbconf *tc; ! 245: register char *cp; ! 246: register struct tbpos *tbpos; ! 247: { ! 248: char byte; ! 249: ! 250: byte = *cp++; ! 251: tbpos->xpos = (byte & 03) << 14; ! 252: tbpos->xpos |= *cp++ << 7; ! 253: tbpos->xpos |= *cp++; ! 254: tbpos->ypos = *cp++ << 14; ! 255: tbpos->ypos |= *cp++ << 7; ! 256: tbpos->ypos |= *cp++; ! 257: tbpos->status = (byte >> 2) | TBINPROX; ! 258: if (tc->tbc_flags&TBF_INPROX && tbpos->status&020) ! 259: tbpos->status &= ~(020|TBINPROX); ! 260: tbpos->scount++; ! 261: } ! 262: ! 263: /* ! 264: * Polhemus decode. ! 265: */ ! 266: static ! 267: poldecode(tc, cp, polpos) ! 268: struct tbconf *tc; ! 269: register char *cp; ! 270: register struct polpos *polpos; ! 271: { ! 272: ! 273: polpos->p_x = cp[4] | cp[3]<<7 | (cp[9] & 0x03) << 14; ! 274: polpos->p_y = cp[6] | cp[5]<<7 | (cp[9] & 0x0c) << 12; ! 275: polpos->p_z = cp[8] | cp[7]<<7 | (cp[9] & 0x30) << 10; ! 276: polpos->p_azi = cp[11] | cp[10]<<7 | (cp[16] & 0x03) << 14; ! 277: polpos->p_pit = cp[13] | cp[12]<<7 | (cp[16] & 0x0c) << 12; ! 278: polpos->p_rol = cp[15] | cp[14]<<7 | (cp[16] & 0x30) << 10; ! 279: polpos->p_stat = cp[1] | cp[0]<<7; ! 280: if (cp[2] != ' ') ! 281: polpos->p_key = cp[2]; ! 282: } ! 283: ! 284: /*ARGSUSED*/ ! 285: tbioctl(tp, cmd, data, flag) ! 286: struct tty *tp; ! 287: caddr_t data; ! 288: { ! 289: register struct tb *tbp = (struct tb *)tp->T_LINEP; ! 290: ! 291: switch (cmd) { ! 292: ! 293: case BIOGMODE: ! 294: *(int *)data = tbp->tbflags & TBMODE; ! 295: break; ! 296: ! 297: case BIOSTYPE: ! 298: if (tbconf[*(int *)data & TBTYPE].tbc_recsize == 0 || ! 299: tbconf[*(int *)data & TBTYPE].tbc_decode == 0) ! 300: return (EINVAL); ! 301: tbp->tbflags &= ~TBTYPE; ! 302: tbp->tbflags |= *(int *)data & TBTYPE; ! 303: /* fall thru... to set mode bits */ ! 304: ! 305: case BIOSMODE: { ! 306: register struct tbconf *tc; ! 307: ! 308: tbp->tbflags &= ~TBMODE; ! 309: tbp->tbflags |= *(int *)data & TBMODE; ! 310: tc = &tbconf[tbp->tbflags & TBTYPE]; ! 311: if (tbp->tbflags&TBSTOP) { ! 312: if (tc->tbc_stop) ! 313: ttyout(tc->tbc_stop, tp); ! 314: } else if (tc->tbc_start) ! 315: ttyout(tc->tbc_start, tp); ! 316: if (tbp->tbflags&TBPOINT) { ! 317: if (tc->tbc_point) ! 318: ttyout(tc->tbc_point, tp); ! 319: } else if (tc->tbc_run) ! 320: ttyout(tc->tbc_run, tp); ! 321: ttstart(tp); ! 322: break; ! 323: } ! 324: ! 325: case BIOGTYPE: ! 326: *(int *)data = tbp->tbflags & TBTYPE; ! 327: break; ! 328: ! 329: case TIOCSETD: ! 330: case TIOCGETD: ! 331: case TIOCGETP: ! 332: case TIOCGETC: ! 333: return (-1); /* pass thru... */ ! 334: ! 335: default: ! 336: return (ENOTTY); ! 337: } ! 338: return (0); ! 339: } ! 340: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.