|
|
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.