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