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