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