xref: /csrg-svn/sys/kern/tty_tb.c (revision 7632)
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