xref: /csrg-svn/sys/kern/tty_tb.c (revision 7732)
1 /*	tty_tb.c	4.3	82/08/13	*/
2 
3 #include "tb.h"
4 #if NTB > 0
5 
6 #include "../h/param.h"
7 #include "../h/systm.h"
8 #include "../h/dir.h"
9 #include "../h/user.h"
10 #include "../h/tty.h"
11 #include "../h/proc.h"
12 #include "../h/inode.h"
13 #include "../h/file.h"
14 #include "../h/conf.h"
15 #include "../h/buf.h"
16 #include "../h/uio.h"
17 
18 /*
19  * Line discipline for RS232 tablets.
20  *
21  * This supplies binary coordinate data to a user level program
22  * with a minimum of fuss.
23  *
24  * This discipline requires that tty device drivers call
25  * the line specific l_ioctl routine from their ioctl routines,
26  * assigning the result to cmd so that we can refuse most tty specific
27  * ioctls which are unsafe because we have ambushed the
28  * teletype input queues and other data, overlaying them with
29  * the following information: the tty queue header, t_un.T_CTLQ,
30  * is overlaid with a MTABCHAR character buffer -- the raw input
31  * chars. The local characters (t_rocount on) are overlaid with
32  * the current coordinate position.
33  */
34 
35 #define MTABCHAR 5
36 #define MNTABCHAR 6
37 struct tbposition {
38 	int xpos;
39 	int ypos;
40 	short int status;
41 	short int scount;
42 };
43 
44 /*
45  * Open as tablet discipline.  Called when discipline changed
46  * with ioctl, and changes the interpretation of the information
47  * in the tty structure.
48  */
49 /*ARGSUSED*/
50 tbopen(dev, tp)
51 	dev_t dev;
52 	register struct tty *tp;
53 {
54 	register struct tbposition *tbp;
55 
56 	if (u.u_error)
57 		return;		/* paranoia */
58 	if (tp->t_line == TABLDISC || tp->t_line == NTABLDISC) {
59 		u.u_error = EBUSY;
60 		return;
61 	}
62 	wflushtty(tp);
63 	tp->t_cp = (char *) &tp->t_un.T_CTLQ;	/* overlay control queue */
64 	tp->t_inbuf = 0;
65 	tbp = (struct tbposition *) &tp->t_rocount;
66 	tbp->xpos = tbp->ypos = tbp->status = tbp->scount = 0;
67 }
68 
69 /*
70  * Break down... called when discipline changed or from device
71  * close routine.
72  */
73 tbclose(tp)
74 register struct tty *tp;
75 {
76 	register s;
77 
78 	s = spl5();
79 	tp->t_cp = 0;
80 	tp->t_inbuf = 0;
81 	tp->t_rawq.c_cc = 0;		/* clear queues -- paranoid */
82 	tp->t_canq.c_cc = 0;
83 	tp->t_un.T_CTLQ.c_cc = 0;	/* clear overlaid queue status */
84 	tp->t_un.T_CTLQ.c_cf = tp->t_un.T_CTLQ.c_cl = NULL;
85 	tp->t_line = 0;		/* paranoid: avoid races */
86 	splx(s);
87 }
88 
89 /*
90  * Read from a tablet line.
91  * Characters have been buffered in a buffer and
92  * decoded. The coordinates are now sluffed back to the user.
93  */
94 tbread(tp, uio)
95 	register struct tty *tp;
96 	struct uio *uio;
97 {
98 	register int i;
99 	register s;
100 	struct tbposition tbposition;
101 
102 	if ((tp->t_state&TS_CARR_ON)==0)
103 		return (-1);
104 	u.u_error = copyuout(uio, &tp->t_rocount, sizeof tbposition);
105 	if (u.u_error)
106 		return (-1);
107 	return (0);
108 }
109 
110 /*
111  * Low level character input routine.
112  * Stuff the character in the buffer, and decode the it
113  * if all the chars are there.
114  *
115  * This routine could be expanded in-line in the receiver
116  * interrupt routine of the dh-11 to make it run as fast as possible.
117  */
118 int LASTTABC;
119 tbinput(c, tp)
120 register c;
121 register struct tty *tp;
122 {
123 
124 	if(tp->t_line == TABLDISC) {
125 		if((c&0200) || (tp->t_inbuf == MTABCHAR)) {
126 			tp->t_cp = (char *) &tp->t_un.T_CTLQ;
127 			tp->t_inbuf = 0;
128 		}
129 		*tp->t_cp++ = c&0177;
130 		if(++tp->t_inbuf == MTABCHAR)
131 			tbdecode((char *) &tp->t_un.T_CTLQ,
132 					(struct tbposition *) &tp->t_rocount);
133 	} else if(tp->t_line == NTABLDISC) {
134 		if((c&0200) || (tp->t_inbuf == MNTABCHAR)) {
135 			tp->t_cp = (char *) &tp->t_un.T_CTLQ;
136 			tp->t_inbuf = 0;
137 		}
138 		*tp->t_cp++ = c&0177;
139 		if(++tp->t_inbuf == MNTABCHAR)
140 			tbndecode((char *) &tp->t_un.T_CTLQ,
141 					(struct tbposition *) &tp->t_rocount);
142 	}
143 }
144 
145 /*
146  * Decode tablet coordinates from ascii to binary.
147  *	(gtco 6 character format)
148  */
149 tbndecode(cp, tbposition)
150 	register char *cp;
151 	register struct tbposition *tbposition;
152 {
153 
154 	tbposition->status = *cp>>2;	/* this needs to be decoded */
155 	tbposition->xpos = ((*cp++)&03)<<14;
156 	tbposition->xpos |= (*cp++)<<7;
157 	tbposition->xpos |= (*cp++);
158 	tbposition->ypos = ((*cp++)&03)<<14;
159 	tbposition->ypos |= (*cp++)<<7;
160 	tbposition->ypos |= (*cp++);
161 	tbposition->scount++;
162 }
163 
164 /*
165  * Decode tablet coordinates from ascii to binary.
166  *	(hitachi 5 character format)
167  */
168 tbdecode(cp, tbposition)
169 	register char *cp;
170 	register struct tbposition *tbposition;
171 {
172 	register int status;
173 	register char byte;
174 
175 	byte = *cp++;
176 	status = (byte&0100) ? 0100000 : 0;
177 	byte &= ~0100;
178 	if(byte > 036)
179 		status |= 1<<((byte-040)/2);
180 	tbposition->xpos = (*cp++)<<7;
181 	tbposition->xpos |= (*cp++);
182 	if(tbposition->xpos < 256)	/* tablet wraps around at 256 */
183 		status &= 077777;	/* make it out of proximity */
184 	tbposition->ypos = (*cp++)<<7;
185 	tbposition->ypos |= (*cp++);
186 	tbposition->status  = status;
187 	tbposition->scount++;
188 }
189 
190 /*
191  * This routine is called whenever a ioctl is about to be performed
192  * and gets a chance to reject the ioctl.  We reject all teletype
193  * oriented ioctl's except those which set the discipline, and
194  * those which get parameters (gtty and get special characters).
195  */
196 /*ARGSUSED*/
197 tbioctl(tp, cmd, data, flag)
198 	struct tty *tp;
199 	caddr_t data;
200 {
201 
202 	if ((cmd>>8) != 't')
203 		return (cmd);
204 	switch (cmd) {
205 
206 	case TIOCSETD:
207 	case TIOCGETD:
208 	case TIOCGETP:
209 	case TIOCGETC:
210 		return (cmd);
211 	}
212 	u.u_error = ENOTTY;
213 	return (0);
214 }
215 #endif
216