xref: /csrg-svn/sys/kern/tty_tb.c (revision 17097)
1 /*	tty_tb.c	6.3	84/08/29	*/
2 
3 #include "tb.h"
4 #if NTB > 0
5 
6 #include "param.h"
7 #include "systm.h"
8 #include "dir.h"
9 #include "user.h"
10 #include "ioctl.h"
11 #include "tty.h"
12 #include "proc.h"
13 #include "inode.h"
14 #include "file.h"
15 #include "conf.h"
16 #include "buf.h"
17 #include "uio.h"
18 
19 /*
20  * Line discipline for RS232 tablets.
21  * Supplies binary coordinate data.
22  *
23  * MAKE TABLET TYPE AN ioctl TO AVOID HAVING ONE DISCIPLINE PER TABLET TYPE.
24  */
25 
26 #define NTBS		(16)
27 #define MALLTABCHAR	(8)
28 #define MTABCHAR 	(5)
29 #define MNTABCHAR	(6)
30 
31 struct tb {
32 	short used;
33 	char cbuf[MALLTABCHAR];
34 	struct tbpos {
35 		int	xpos;
36 		int	ypos;
37 		short	status;
38 		short	scount;
39 	} tbpos;
40 } tb[NTBS];
41 
42 /*
43  * Open as tablet discipline.  Called when discipline changed
44  * with ioctl, and changes the interpretation of the information
45  * in the tty structure.
46  */
47 /*ARGSUSED*/
48 tbopen(dev, tp)
49 	dev_t dev;
50 	register struct tty *tp;
51 {
52 	register struct tb *tbp;
53 
54 	if (tp->t_line == TABLDISC || tp->t_line == NTABLDISC)
55 		return (ENODEV);
56 	ttywflush(tp);
57 	for (tbp = tb; tbp < &tb[NTBS]; tbp++)
58 		if (!tbp->used)
59 			break;
60 	if (tbp >= &tb[NTBS])
61 		return (EBUSY);
62 	tbp->used++;
63 	tp->t_cp = tbp->cbuf;
64 	tp->t_inbuf = 0;
65 	tbp->tbpos.xpos = tbp->tbpos.ypos = 0;
66 	tbp->tbpos.status = tbp->tbpos.scount = 0;
67 	tp->T_LINEP = (caddr_t) tbp;
68 	return (0);
69 }
70 
71 /*
72  * Break down... called when discipline changed or from device
73  * close routine.
74  */
75 tbclose(tp)
76 	register struct tty *tp;
77 {
78 	register int s = spl5();
79 
80 	((struct tb *) tp->T_LINEP)->used = 0;
81 	tp->t_cp = 0;
82 	tp->t_inbuf = 0;
83 	tp->t_rawq.c_cc = 0;		/* clear queues -- paranoid */
84 	tp->t_canq.c_cc = 0;
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 	struct tbpos *tbpos;
99 
100 	if ((tp->t_state&TS_CARR_ON)==0)
101 		return (EIO);
102 	tbpos = &(((struct tb *) (tp->T_LINEP))->tbpos);
103 	return (uiomove(tbpos, sizeof *tbpos, UIO_READ, uio));
104 }
105 
106 /*
107  * Low level character input routine.
108  * Stuff the character in the buffer, and decode the it
109  * if all the chars are there.
110  *
111  * This routine could be expanded in-line in the receiver
112  * interrupt routine of the dh-11 to make it run as fast as possible.
113  */
114 int	LASTTABC;
115 
116 tbinput(c, tp)
117 	register int c;
118 	register struct tty *tp;
119 {
120 	register struct tb *tbp = (struct tb *) tp->T_LINEP;
121 
122 	if (tp->t_line == TABLDISC) {
123 		if ((c&0200) || (tp->t_inbuf == MTABCHAR)) {
124 			tp->t_cp = tbp->cbuf;
125 			tp->t_inbuf = 0;
126 		}
127 		*tp->t_cp++ = c&0177;
128 		if (++tp->t_inbuf == MTABCHAR)
129 			tbdecode(tbp->cbuf, &tbp->tbpos);
130 	} else if (tp->t_line == NTABLDISC) {
131 		if ((c&0200) || (tp->t_inbuf == MNTABCHAR)) {
132 			tp->t_cp = tbp->cbuf;
133 			tp->t_inbuf = 0;
134 		}
135 		*tp->t_cp++ = c&0177;
136 		if (++tp->t_inbuf == MNTABCHAR)
137 			tbndecode(tbp->cbuf, &tbp->tbpos);
138 	}
139 }
140 
141 /*
142  * Decode tablet coordinates from ascii to binary.
143  *	(gtco 6 character format)
144  */
145 tbndecode(cp, tbpos)
146 	register char *cp;
147 	register struct tbpos *tbpos;
148 {
149 
150 	tbpos->status = *cp>>2;	/* this needs to be decoded */
151 	tbpos->xpos = ((*cp++)&03)<<14;
152 	tbpos->xpos |= (*cp++)<<7;
153 	tbpos->xpos |= (*cp++);
154 	tbpos->ypos = ((*cp++)&03)<<14;
155 	tbpos->ypos |= (*cp++)<<7;
156 	tbpos->ypos |= (*cp++);
157 	tbpos->scount++;
158 }
159 
160 /*
161  * Decode tablet coordinates from ascii to binary.
162  *	(hitachi 5 character format)
163  */
164 tbdecode(cp, tbpos)
165 	register char *cp;
166 	register struct tbpos *tbpos;
167 {
168 	register int status;
169 	register char byte;
170 
171 	byte = *cp++;
172 	status = (byte&0100) ? 0100000 : 0;
173 	byte &= ~0100;
174 	if (byte > 036)
175 		status |= 1<<((byte-040)/2);
176 	tbpos->xpos = (*cp++)<<7;
177 	tbpos->xpos |= (*cp++);
178 	if (tbpos->xpos < 256)		/* tablet wraps around at 256 */
179 		status &= 077777;	/* make it out of proximity */
180 	tbpos->ypos = (*cp++)<<7;
181 	tbpos->ypos |= (*cp++);
182 	tbpos->status  = status;
183 	tbpos->scount++;
184 }
185 
186 /*
187  * This routine is called whenever a ioctl is about to be performed
188  * and gets a chance to reject the ioctl.  We reject all teletype
189  * oriented ioctl's except those which set the discipline, and
190  * those which get parameters (gtty and get special characters).
191  */
192 /*ARGSUSED*/
193 tbioctl(tp, cmd, data, flag)
194 	struct tty *tp;
195 	caddr_t data;
196 {
197 
198 	if ((cmd>>8) != 't')
199 		return (cmd);
200 	switch (cmd) {
201 
202 	case TIOCSETD:
203 	case TIOCGETD:
204 	case TIOCGETP:
205 	case TIOCGETC:
206 		return (cmd);
207 	}
208 	u.u_error = ENOTTY;
209 	return (0);
210 }
211 #endif
212