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