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