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