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