xref: /csrg-svn/sys/kern/tty_tb.c (revision 15044)
1*15044Smckusick /*	tty_tb.c	6.2	83/09/22	*/
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"
109562Ssam #include "../h/ioctl.h"
117297Ssam #include "../h/tty.h"
127297Ssam #include "../h/proc.h"
137297Ssam #include "../h/inode.h"
147297Ssam #include "../h/file.h"
157297Ssam #include "../h/conf.h"
167297Ssam #include "../h/buf.h"
177732Sroot #include "../h/uio.h"
187297Ssam 
197297Ssam /*
207297Ssam  * Line discipline for RS232 tablets.
218522Sroot  * Supplies binary coordinate data.
227297Ssam  *
238522Sroot  * MAKE TABLET TYPE AN ioctl TO AVOID HAVING ONE DISCIPLINE PER TABLET TYPE.
247297Ssam  */
257297Ssam 
2614596Ssam #define NTBS		(16)
2714596Ssam #define MALLTABCHAR	(8)
2814596Ssam #define MTABCHAR 	(5)
2914596Ssam #define MNTABCHAR	(6)
308522Sroot 
3114596Ssam struct tb {
3214596Ssam 	short used;
3314596Ssam 	char cbuf[MALLTABCHAR];
3414596Ssam 	struct tbpos {
3514596Ssam 		int	xpos;
3614596Ssam 		int	ypos;
3714596Ssam 		short	status;
3814596Ssam 		short	scount;
3914596Ssam 	} tbpos;
4014596Ssam } tb[NTBS];
417297Ssam 
427297Ssam /*
437297Ssam  * Open as tablet discipline.  Called when discipline changed
447297Ssam  * with ioctl, and changes the interpretation of the information
457297Ssam  * in the tty structure.
467297Ssam  */
477297Ssam /*ARGSUSED*/
487297Ssam tbopen(dev, tp)
497632Ssam 	dev_t dev;
507632Ssam 	register struct tty *tp;
517297Ssam {
5214596Ssam 	register struct tb *tbp;
537297Ssam 
5414596Ssam 	if (tp->t_line == TABLDISC || tp->t_line == NTABLDISC)
5514596Ssam 		return (ENODEV);
5614596Ssam 	ttywflush(tp);
5714596Ssam 	for (tbp = tb; tbp < &tb[NTBS]; tbp++)
5814596Ssam 		if (!tbp->used)
5914596Ssam 			break;
6014596Ssam 	if (tbp >= &tb[NTBS])
618557Sroot 		return (EBUSY);
6214596Ssam 	tbp->used++;
6314596Ssam 	tp->t_cp = tbp->cbuf;
647297Ssam 	tp->t_inbuf = 0;
6514596Ssam 	tbp->tbpos.xpos = tbp->tbpos.ypos = 0;
6614596Ssam 	tbp->tbpos.status = tbp->tbpos.scount = 0;
6714596Ssam 	tp->T_LINEP = (caddr_t) tbp;
688557Sroot 	return (0);
697297Ssam }
707297Ssam 
717297Ssam /*
727297Ssam  * Break down... called when discipline changed or from device
737297Ssam  * close routine.
747297Ssam  */
757297Ssam tbclose(tp)
768557Sroot 	register struct tty *tp;
777297Ssam {
788557Sroot 	register int s = spl5();
797297Ssam 
80*15044Smckusick 	((struct tb *) tp->T_LINEP)->used = 0;
817297Ssam 	tp->t_cp = 0;
827297Ssam 	tp->t_inbuf = 0;
837297Ssam 	tp->t_rawq.c_cc = 0;		/* clear queues -- paranoid */
847297Ssam 	tp->t_canq.c_cc = 0;
85*15044Smckusick 	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  */
947732Sroot tbread(tp, uio)
957732Sroot 	register struct tty *tp;
967732Sroot 	struct uio *uio;
977297Ssam {
9814596Ssam 	struct tbpos *tbpos;
997297Ssam 
1007297Ssam 	if ((tp->t_state&TS_CARR_ON)==0)
1018522Sroot 		return (EIO);
10214596Ssam 	tbpos = &(((struct tb *) (tp->T_LINEP))->tbpos);
10314596Ssam 	return (uiomove(tbpos, sizeof *tbpos, UIO_READ, uio));
1047297Ssam }
1057297Ssam 
1067297Ssam /*
1077297Ssam  * Low level character input routine.
1087297Ssam  * Stuff the character in the buffer, and decode the it
1097297Ssam  * if all the chars are there.
1107297Ssam  *
1117297Ssam  * This routine could be expanded in-line in the receiver
1127297Ssam  * interrupt routine of the dh-11 to make it run as fast as possible.
1137297Ssam  */
1148522Sroot int	LASTTABC;
1158522Sroot 
1167297Ssam tbinput(c, tp)
1178522Sroot 	register int c;
1188522Sroot 	register struct tty *tp;
1197297Ssam {
12014596Ssam 	register struct tb *tbp = (struct tb *) tp->T_LINEP;
1217297Ssam 
1228522Sroot 	if (tp->t_line == TABLDISC) {
1238522Sroot 		if ((c&0200) || (tp->t_inbuf == MTABCHAR)) {
12414596Ssam 			tp->t_cp = tbp->cbuf;
1257297Ssam 			tp->t_inbuf = 0;
1267297Ssam 		}
1277297Ssam 		*tp->t_cp++ = c&0177;
1288522Sroot 		if (++tp->t_inbuf == MTABCHAR)
12914596Ssam 			tbdecode(tbp->cbuf, &tbp->tbpos);
1308522Sroot 	} else if (tp->t_line == NTABLDISC) {
1318522Sroot 		if ((c&0200) || (tp->t_inbuf == MNTABCHAR)) {
13214596Ssam 			tp->t_cp = tbp->cbuf;
1337297Ssam 			tp->t_inbuf = 0;
1347297Ssam 		}
1357297Ssam 		*tp->t_cp++ = c&0177;
1368522Sroot 		if (++tp->t_inbuf == MNTABCHAR)
13714596Ssam 			tbndecode(tbp->cbuf, &tbp->tbpos);
1387297Ssam 	}
1397297Ssam }
1407297Ssam 
1417297Ssam /*
1427297Ssam  * Decode tablet coordinates from ascii to binary.
1437297Ssam  *	(gtco 6 character format)
1447297Ssam  */
14514596Ssam tbndecode(cp, tbpos)
1467297Ssam 	register char *cp;
14714596Ssam 	register struct tbpos *tbpos;
1487297Ssam {
1497297Ssam 
15014596Ssam 	tbpos->status = *cp>>2;	/* this needs to be decoded */
15114596Ssam 	tbpos->xpos = ((*cp++)&03)<<14;
15214596Ssam 	tbpos->xpos |= (*cp++)<<7;
15314596Ssam 	tbpos->xpos |= (*cp++);
15414596Ssam 	tbpos->ypos = ((*cp++)&03)<<14;
15514596Ssam 	tbpos->ypos |= (*cp++)<<7;
15614596Ssam 	tbpos->ypos |= (*cp++);
15714596Ssam 	tbpos->scount++;
1587297Ssam }
1597297Ssam 
1607297Ssam /*
1617297Ssam  * Decode tablet coordinates from ascii to binary.
1627297Ssam  *	(hitachi 5 character format)
1637297Ssam  */
16414596Ssam tbdecode(cp, tbpos)
1657297Ssam 	register char *cp;
16614596Ssam 	register struct tbpos *tbpos;
1677297Ssam {
1687297Ssam 	register int status;
1697297Ssam 	register char byte;
1707297Ssam 
1717297Ssam 	byte = *cp++;
1727297Ssam 	status = (byte&0100) ? 0100000 : 0;
1737297Ssam 	byte &= ~0100;
1748522Sroot 	if (byte > 036)
1757297Ssam 		status |= 1<<((byte-040)/2);
17614596Ssam 	tbpos->xpos = (*cp++)<<7;
17714596Ssam 	tbpos->xpos |= (*cp++);
17814596Ssam 	if (tbpos->xpos < 256)		/* tablet wraps around at 256 */
1797297Ssam 		status &= 077777;	/* make it out of proximity */
18014596Ssam 	tbpos->ypos = (*cp++)<<7;
18114596Ssam 	tbpos->ypos |= (*cp++);
18214596Ssam 	tbpos->status  = status;
18314596Ssam 	tbpos->scount++;
1847297Ssam }
1857297Ssam 
1867297Ssam /*
1877297Ssam  * This routine is called whenever a ioctl is about to be performed
1887297Ssam  * and gets a chance to reject the ioctl.  We reject all teletype
1897297Ssam  * oriented ioctl's except those which set the discipline, and
1907297Ssam  * those which get parameters (gtty and get special characters).
1917297Ssam  */
1927297Ssam /*ARGSUSED*/
1937632Ssam tbioctl(tp, cmd, data, flag)
1947632Ssam 	struct tty *tp;
1957632Ssam 	caddr_t data;
1967297Ssam {
1977297Ssam 
1987297Ssam 	if ((cmd>>8) != 't')
1997297Ssam 		return (cmd);
2007297Ssam 	switch (cmd) {
2017297Ssam 
2027297Ssam 	case TIOCSETD:
2037297Ssam 	case TIOCGETD:
2047297Ssam 	case TIOCGETP:
2057297Ssam 	case TIOCGETC:
2067297Ssam 		return (cmd);
2077297Ssam 	}
2087297Ssam 	u.u_error = ENOTTY;
2097297Ssam 	return (0);
2107297Ssam }
2117297Ssam #endif
212