xref: /csrg-svn/sys/kern/tty_tb.c (revision 14596)
1 /*	tty_tb.c	4.9	83/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/ioctl.h"
11 #include "../h/tty.h"
12 #include "../h/proc.h"
13 #include "../h/inode.h"
14 #include "../h/file.h"
15 #include "../h/conf.h"
16 #include "../h/buf.h"
17 #include "../h/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 	tp->t_cp = 0;
81 	tp->t_inbuf = 0;
82 	tp->t_rawq.c_cc = 0;		/* clear queues -- paranoid */
83 	tp->t_canq.c_cc = 0;
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, uio)
94 	register struct tty *tp;
95 	struct uio *uio;
96 {
97 	register int i;
98 	register s;
99 	struct tbpos *tbpos;
100 
101 	if ((tp->t_state&TS_CARR_ON)==0)
102 		return (EIO);
103 	tbpos = &(((struct tb *) (tp->T_LINEP))->tbpos);
104 	return (uiomove(tbpos, sizeof *tbpos, UIO_READ, uio));
105 }
106 
107 /*
108  * Low level character input routine.
109  * Stuff the character in the buffer, and decode the it
110  * if all the chars are there.
111  *
112  * This routine could be expanded in-line in the receiver
113  * interrupt routine of the dh-11 to make it run as fast as possible.
114  */
115 int	LASTTABC;
116 
117 tbinput(c, tp)
118 	register int c;
119 	register struct tty *tp;
120 {
121 	register struct tb *tbp = (struct tb *) tp->T_LINEP;
122 
123 	if (tp->t_line == TABLDISC) {
124 		if ((c&0200) || (tp->t_inbuf == MTABCHAR)) {
125 			tp->t_cp = tbp->cbuf;
126 			tp->t_inbuf = 0;
127 		}
128 		*tp->t_cp++ = c&0177;
129 		if (++tp->t_inbuf == MTABCHAR)
130 			tbdecode(tbp->cbuf, &tbp->tbpos);
131 	} else if (tp->t_line == NTABLDISC) {
132 		if ((c&0200) || (tp->t_inbuf == MNTABCHAR)) {
133 			tp->t_cp = tbp->cbuf;
134 			tp->t_inbuf = 0;
135 		}
136 		*tp->t_cp++ = c&0177;
137 		if (++tp->t_inbuf == MNTABCHAR)
138 			tbndecode(tbp->cbuf, &tbp->tbpos);
139 	}
140 }
141 
142 /*
143  * Decode tablet coordinates from ascii to binary.
144  *	(gtco 6 character format)
145  */
146 tbndecode(cp, tbpos)
147 	register char *cp;
148 	register struct tbpos *tbpos;
149 {
150 
151 	tbpos->status = *cp>>2;	/* this needs to be decoded */
152 	tbpos->xpos = ((*cp++)&03)<<14;
153 	tbpos->xpos |= (*cp++)<<7;
154 	tbpos->xpos |= (*cp++);
155 	tbpos->ypos = ((*cp++)&03)<<14;
156 	tbpos->ypos |= (*cp++)<<7;
157 	tbpos->ypos |= (*cp++);
158 	tbpos->scount++;
159 }
160 
161 /*
162  * Decode tablet coordinates from ascii to binary.
163  *	(hitachi 5 character format)
164  */
165 tbdecode(cp, tbpos)
166 	register char *cp;
167 	register struct tbpos *tbpos;
168 {
169 	register int status;
170 	register char byte;
171 
172 	byte = *cp++;
173 	status = (byte&0100) ? 0100000 : 0;
174 	byte &= ~0100;
175 	if (byte > 036)
176 		status |= 1<<((byte-040)/2);
177 	tbpos->xpos = (*cp++)<<7;
178 	tbpos->xpos |= (*cp++);
179 	if (tbpos->xpos < 256)		/* tablet wraps around at 256 */
180 		status &= 077777;	/* make it out of proximity */
181 	tbpos->ypos = (*cp++)<<7;
182 	tbpos->ypos |= (*cp++);
183 	tbpos->status  = status;
184 	tbpos->scount++;
185 }
186 
187 /*
188  * This routine is called whenever a ioctl is about to be performed
189  * and gets a chance to reject the ioctl.  We reject all teletype
190  * oriented ioctl's except those which set the discipline, and
191  * those which get parameters (gtty and get special characters).
192  */
193 /*ARGSUSED*/
194 tbioctl(tp, cmd, data, flag)
195 	struct tty *tp;
196 	caddr_t data;
197 {
198 
199 	if ((cmd>>8) != 't')
200 		return (cmd);
201 	switch (cmd) {
202 
203 	case TIOCSETD:
204 	case TIOCGETD:
205 	case TIOCGETP:
206 	case TIOCGETC:
207 		return (cmd);
208 	}
209 	u.u_error = ENOTTY;
210 	return (0);
211 }
212 #endif
213