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