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