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