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