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