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