1*7632Ssam /* tty_tb.c 4.2 82/08/01 */ 27297Ssam 37297Ssam #include "tb.h" 47297Ssam #if NTB > 0 57297Ssam 67297Ssam #include "../h/param.h" 77297Ssam #include "../h/systm.h" 87297Ssam #include "../h/dir.h" 97297Ssam #include "../h/user.h" 107297Ssam #include "../h/tty.h" 117297Ssam #include "../h/proc.h" 127297Ssam #include "../h/inode.h" 137297Ssam #include "../h/file.h" 147297Ssam #include "../h/conf.h" 157297Ssam #include "../h/buf.h" 167297Ssam 177297Ssam /* 187297Ssam * Line discipline for RS232 tablets. 197297Ssam * 207297Ssam * This supplies binary coordinate data to a user level program 217297Ssam * with a minimum of fuss. 227297Ssam * 237297Ssam * This discipline requires that tty device drivers call 247297Ssam * the line specific l_ioctl routine from their ioctl routines, 257297Ssam * assigning the result to cmd so that we can refuse most tty specific 267297Ssam * ioctls which are unsafe because we have ambushed the 277297Ssam * teletype input queues and other data, overlaying them with 287297Ssam * the following information: the tty queue header, t_un.T_CTLQ, 297297Ssam * is overlaid with a MTABCHAR character buffer -- the raw input 307297Ssam * chars. The local characters (t_rocount on) are overlaid with 317297Ssam * the current coordinate position. 327297Ssam */ 337297Ssam 347297Ssam #define MTABCHAR 5 357297Ssam #define MNTABCHAR 6 367297Ssam struct tbposition { 377297Ssam int xpos; 387297Ssam int ypos; 397297Ssam short int status; 407297Ssam short int scount; 417297Ssam }; 427297Ssam 437297Ssam /* 447297Ssam * Open as tablet discipline. Called when discipline changed 457297Ssam * with ioctl, and changes the interpretation of the information 467297Ssam * in the tty structure. 477297Ssam */ 487297Ssam /*ARGSUSED*/ 497297Ssam tbopen(dev, tp) 50*7632Ssam dev_t dev; 51*7632Ssam register struct tty *tp; 527297Ssam { 537297Ssam register struct tbposition *tbp; 547297Ssam 557297Ssam if (u.u_error) 567297Ssam return; /* paranoia */ 577297Ssam if (tp->t_line == TABLDISC || tp->t_line == NTABLDISC) { 587297Ssam u.u_error = EBUSY; 597297Ssam return; 607297Ssam } 617297Ssam wflushtty(tp); 627297Ssam tp->t_cp = (char *) &tp->t_un.T_CTLQ; /* overlay control queue */ 637297Ssam tp->t_inbuf = 0; 647297Ssam tbp = (struct tbposition *) &tp->t_rocount; 657297Ssam tbp->xpos = tbp->ypos = tbp->status = tbp->scount = 0; 667297Ssam } 677297Ssam 687297Ssam /* 697297Ssam * Break down... called when discipline changed or from device 707297Ssam * close routine. 717297Ssam */ 727297Ssam tbclose(tp) 737297Ssam register struct tty *tp; 747297Ssam { 757297Ssam register s; 767297Ssam 777297Ssam s = spl5(); 787297Ssam tp->t_cp = 0; 797297Ssam tp->t_inbuf = 0; 807297Ssam tp->t_rawq.c_cc = 0; /* clear queues -- paranoid */ 817297Ssam tp->t_canq.c_cc = 0; 827297Ssam tp->t_un.T_CTLQ.c_cc = 0; /* clear overlaid queue status */ 837297Ssam tp->t_un.T_CTLQ.c_cf = tp->t_un.T_CTLQ.c_cl = NULL; 847297Ssam tp->t_line = 0; /* paranoid: avoid races */ 857297Ssam splx(s); 867297Ssam } 877297Ssam 887297Ssam /* 897297Ssam * Read from a tablet line. 907297Ssam * Characters have been buffered in a buffer and 917297Ssam * decoded. The coordinates are now sluffed back to the user. 927297Ssam */ 937297Ssam tbread(tp) 947297Ssam register struct tty *tp; 957297Ssam { 967297Ssam register int i; 977297Ssam register s; 987297Ssam struct tbposition tbposition; 997297Ssam 1007297Ssam if ((tp->t_state&TS_CARR_ON)==0) 1017297Ssam return (-1); 1027297Ssam if (copyout(&tp->t_rocount, u.u_base, (unsigned)(sizeof tbposition))) { 1037297Ssam u.u_error = EFAULT; 1047297Ssam return (-1); 1057297Ssam } 1067297Ssam u.u_count -= sizeof tbposition; 1077297Ssam u.u_base += sizeof tbposition; 1087297Ssam u.u_offset += sizeof tbposition; 1097297Ssam return (0); 1107297Ssam } 1117297Ssam 1127297Ssam /* 1137297Ssam * Low level character input routine. 1147297Ssam * Stuff the character in the buffer, and decode the it 1157297Ssam * if all the chars are there. 1167297Ssam * 1177297Ssam * This routine could be expanded in-line in the receiver 1187297Ssam * interrupt routine of the dh-11 to make it run as fast as possible. 1197297Ssam */ 1207297Ssam int LASTTABC; 1217297Ssam tbinput(c, tp) 1227297Ssam register c; 1237297Ssam register struct tty *tp; 1247297Ssam { 1257297Ssam 1267297Ssam if(tp->t_line == TABLDISC) { 1277297Ssam if((c&0200) || (tp->t_inbuf == MTABCHAR)) { 1287297Ssam tp->t_cp = (char *) &tp->t_un.T_CTLQ; 1297297Ssam tp->t_inbuf = 0; 1307297Ssam } 1317297Ssam *tp->t_cp++ = c&0177; 1327297Ssam if(++tp->t_inbuf == MTABCHAR) 1337297Ssam tbdecode((char *) &tp->t_un.T_CTLQ, 1347297Ssam (struct tbposition *) &tp->t_rocount); 1357297Ssam } else if(tp->t_line == NTABLDISC) { 1367297Ssam if((c&0200) || (tp->t_inbuf == MNTABCHAR)) { 1377297Ssam tp->t_cp = (char *) &tp->t_un.T_CTLQ; 1387297Ssam tp->t_inbuf = 0; 1397297Ssam } 1407297Ssam *tp->t_cp++ = c&0177; 1417297Ssam if(++tp->t_inbuf == MNTABCHAR) 1427297Ssam tbndecode((char *) &tp->t_un.T_CTLQ, 1437297Ssam (struct tbposition *) &tp->t_rocount); 1447297Ssam } 1457297Ssam } 1467297Ssam 1477297Ssam /* 1487297Ssam * Decode tablet coordinates from ascii to binary. 1497297Ssam * (gtco 6 character format) 1507297Ssam */ 1517297Ssam tbndecode(cp, tbposition) 1527297Ssam register char *cp; 1537297Ssam register struct tbposition *tbposition; 1547297Ssam { 1557297Ssam 1567297Ssam tbposition->status = *cp>>2; /* this needs to be decoded */ 1577297Ssam tbposition->xpos = ((*cp++)&03)<<14; 1587297Ssam tbposition->xpos |= (*cp++)<<7; 1597297Ssam tbposition->xpos |= (*cp++); 1607297Ssam tbposition->ypos = ((*cp++)&03)<<14; 1617297Ssam tbposition->ypos |= (*cp++)<<7; 1627297Ssam tbposition->ypos |= (*cp++); 1637297Ssam tbposition->scount++; 1647297Ssam } 1657297Ssam 1667297Ssam /* 1677297Ssam * Decode tablet coordinates from ascii to binary. 1687297Ssam * (hitachi 5 character format) 1697297Ssam */ 1707297Ssam tbdecode(cp, tbposition) 1717297Ssam register char *cp; 1727297Ssam register struct tbposition *tbposition; 1737297Ssam { 1747297Ssam register int status; 1757297Ssam register char byte; 1767297Ssam 1777297Ssam byte = *cp++; 1787297Ssam status = (byte&0100) ? 0100000 : 0; 1797297Ssam byte &= ~0100; 1807297Ssam if(byte > 036) 1817297Ssam status |= 1<<((byte-040)/2); 1827297Ssam tbposition->xpos = (*cp++)<<7; 1837297Ssam tbposition->xpos |= (*cp++); 1847297Ssam if(tbposition->xpos < 256) /* tablet wraps around at 256 */ 1857297Ssam status &= 077777; /* make it out of proximity */ 1867297Ssam tbposition->ypos = (*cp++)<<7; 1877297Ssam tbposition->ypos |= (*cp++); 1887297Ssam tbposition->status = status; 1897297Ssam tbposition->scount++; 1907297Ssam } 1917297Ssam 1927297Ssam /* 1937297Ssam * This routine is called whenever a ioctl is about to be performed 1947297Ssam * and gets a chance to reject the ioctl. We reject all teletype 1957297Ssam * oriented ioctl's except those which set the discipline, and 1967297Ssam * those which get parameters (gtty and get special characters). 1977297Ssam */ 1987297Ssam /*ARGSUSED*/ 199*7632Ssam tbioctl(tp, cmd, data, flag) 200*7632Ssam struct tty *tp; 201*7632Ssam caddr_t data; 2027297Ssam { 2037297Ssam 2047297Ssam if ((cmd>>8) != 't') 2057297Ssam return (cmd); 2067297Ssam switch (cmd) { 2077297Ssam 2087297Ssam case TIOCSETD: 2097297Ssam case TIOCGETD: 2107297Ssam case TIOCGETP: 2117297Ssam case TIOCGETC: 2127297Ssam return (cmd); 2137297Ssam } 2147297Ssam u.u_error = ENOTTY; 2157297Ssam return (0); 2167297Ssam } 2177297Ssam #endif 218