This source file includes following definitions.
- wait_until_sent
- unset_locked_termios
- set_termios
- get_termio
- inq_canon
- n_tty_ioctl
1
2
3
4
5
6
7
8
9
10
11 #include <linux/types.h>
12 #include <linux/termios.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/config.h>
16 #include <linux/kernel.h>
17 #include <linux/major.h>
18 #include <linux/tty.h>
19 #include <linux/fcntl.h>
20 #include <linux/string.h>
21
22 #include <asm/io.h>
23 #include <asm/bitops.h>
24 #include <asm/segment.h>
25 #include <asm/system.h>
26
27 #undef DEBUG
28 #ifdef DEBUG
29 # define PRINTK(x) printk (x)
30 #else
31 # define PRINTK(x)
32 #endif
33
34
35
36
37 #define TERMIOS_FLUSH 1
38 #define TERMIOS_WAIT 2
39 #define TERMIOS_TERMIO 4
40
41 void wait_until_sent(struct tty_struct * tty, int timeout)
42 {
43 struct wait_queue wait = { current, NULL };
44
45 if (!tty->driver.chars_in_buffer ||
46 !tty->driver.chars_in_buffer(tty))
47 return;
48 add_wait_queue(&tty->write_wait, &wait);
49 current->counter = 0;
50 if (timeout)
51 current->timeout = timeout + jiffies;
52 else
53 current->timeout = (unsigned) -1;
54 do {
55 current->state = TASK_INTERRUPTIBLE;
56 if (current->signal & ~current->blocked)
57 break;
58 if (!tty->driver.chars_in_buffer(tty))
59 break;
60 schedule();
61 } while (current->timeout);
62 current->state = TASK_RUNNING;
63 remove_wait_queue(&tty->write_wait, &wait);
64 }
65
66 static void unset_locked_termios(struct termios *termios,
67 struct termios *old,
68 struct termios *locked)
69 {
70 int i;
71
72 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
73
74 if (!locked) {
75 printk("Warning?!? termios_locked is NULL.\n");
76 return;
77 }
78
79 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
80 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
81 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
82 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
83 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
84 for (i=0; i < NCCS; i++)
85 termios->c_cc[i] = locked->c_cc[i] ?
86 old->c_cc[i] : termios->c_cc[i];
87 }
88
89 static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
90 {
91 struct termio tmp_termio;
92 struct termios tmp_termios;
93 struct termios old_termios = *tty->termios;
94 int retval, canon_change;
95
96 retval = tty_check_change(tty);
97 if (retval)
98 return retval;
99
100 if (opt & TERMIOS_TERMIO) {
101 retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termio));
102 if (retval)
103 return retval;
104 tmp_termios = *tty->termios;
105 memcpy_fromfs(&tmp_termio, (struct termio *) arg,
106 sizeof (struct termio));
107
108 #define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y))
109 SET_LOW_BITS(tmp_termios.c_iflag, tmp_termio.c_iflag);
110 SET_LOW_BITS(tmp_termios.c_oflag, tmp_termio.c_oflag);
111 SET_LOW_BITS(tmp_termios.c_cflag, tmp_termio.c_cflag);
112 SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag);
113 memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);
114 #undef SET_LOW_BITS
115 } else {
116 retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios));
117 if (retval)
118 return retval;
119 memcpy_fromfs(&tmp_termios, (struct termios *) arg,
120 sizeof (struct termios));
121 }
122
123 if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
124 tty->ldisc.flush_buffer(tty);
125
126 if (opt & TERMIOS_WAIT)
127 wait_until_sent(tty, 0);
128
129 cli();
130 *tty->termios = tmp_termios;
131 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
132 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
133 if (canon_change) {
134 memset(&tty->read_flags, 0, sizeof tty->read_flags);
135 tty->canon_head = tty->read_tail;
136 tty->canon_data = 0;
137 tty->erasing = 0;
138 }
139 sti();
140 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
141
142 wake_up_interruptible(&tty->read_wait);
143
144
145
146 if (tty->link && tty->link->packet) {
147 int old_flow = ((old_termios.c_iflag & IXON) &&
148 (old_termios.c_cc[VSTOP] == '\023') &&
149 (old_termios.c_cc[VSTART] == '\021'));
150 int new_flow = (I_IXON(tty) &&
151 STOP_CHAR(tty) == '\023' &&
152 START_CHAR(tty) == '\021');
153 if (old_flow != new_flow) {
154 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
155 if (new_flow)
156 tty->ctrl_status |= TIOCPKT_DOSTOP;
157 else
158 tty->ctrl_status |= TIOCPKT_NOSTOP;
159 wake_up_interruptible(&tty->link->read_wait);
160 }
161 }
162
163 if (tty->driver.set_termios)
164 (*tty->driver.set_termios)(tty, &old_termios);
165
166 if (tty->ldisc.set_termios)
167 (*tty->ldisc.set_termios)(tty, &old_termios);
168
169 return 0;
170 }
171
172 static int get_termio(struct tty_struct * tty, struct termio * termio)
173 {
174 int i;
175 struct termio tmp_termio;
176
177 i = verify_area(VERIFY_WRITE, termio, sizeof (struct termio));
178 if (i)
179 return i;
180 tmp_termio.c_iflag = tty->termios->c_iflag;
181 tmp_termio.c_oflag = tty->termios->c_oflag;
182 tmp_termio.c_cflag = tty->termios->c_cflag;
183 tmp_termio.c_lflag = tty->termios->c_lflag;
184 tmp_termio.c_line = tty->termios->c_line;
185 for(i=0 ; i < NCC ; i++)
186 tmp_termio.c_cc[i] = tty->termios->c_cc[i];
187 memcpy_tofs(termio, &tmp_termio, sizeof (struct termio));
188 return 0;
189 }
190
191 static unsigned long inq_canon(struct tty_struct * tty)
192 {
193 int nr, head, tail;
194
195 if (!tty->canon_data || !tty->read_buf)
196 return 0;
197 head = tty->canon_head;
198 tail = tty->read_tail;
199 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
200
201 while (head != tail) {
202 if (test_bit(tail, &tty->read_flags) &&
203 tty->read_buf[tail] == __DISABLED_CHAR)
204 nr--;
205 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
206 }
207 return nr;
208 }
209
210 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
211 unsigned int cmd, unsigned long arg)
212 {
213 struct tty_struct * real_tty;
214 int retval;
215 int opt = 0;
216
217 if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
218 tty->driver.subtype == PTY_TYPE_MASTER)
219 real_tty = tty->link;
220 else
221 real_tty = tty;
222
223 switch (cmd) {
224 case TCGETS:
225 retval = verify_area(VERIFY_WRITE, (void *) arg,
226 sizeof (struct termios));
227 if (retval)
228 return retval;
229 memcpy_tofs((struct termios *) arg,
230 real_tty->termios,
231 sizeof (struct termios));
232 return 0;
233 case TCSETSF:
234 opt |= TERMIOS_FLUSH;
235 case TCSETSW:
236 opt |= TERMIOS_WAIT;
237 case TCSETS:
238 return set_termios(real_tty, arg, opt);
239 case TCGETA:
240 return get_termio(real_tty,(struct termio *) arg);
241 case TCSETAF:
242 opt |= TERMIOS_FLUSH;
243 case TCSETAW:
244 opt |= TERMIOS_WAIT;
245 case TCSETA:
246 return set_termios(real_tty, arg, opt|TERMIOS_TERMIO);
247 case TCXONC:
248 retval = tty_check_change(tty);
249 if (retval)
250 return retval;
251 switch (arg) {
252 case TCOOFF:
253 stop_tty(tty);
254 break;
255 case TCOON:
256 start_tty(tty);
257 break;
258 case TCIOFF:
259 if (STOP_CHAR(tty) != __DISABLED_CHAR)
260 tty->driver.write(tty, 0,
261 &STOP_CHAR(tty), 1);
262 break;
263 case TCION:
264 if (START_CHAR(tty) != __DISABLED_CHAR)
265 tty->driver.write(tty, 0,
266 &START_CHAR(tty), 1);
267 break;
268 default:
269 return -EINVAL;
270 }
271 return 0;
272 case TCFLSH:
273 retval = tty_check_change(tty);
274 if (retval)
275 return retval;
276 switch (arg) {
277 case TCIFLUSH:
278 if (tty->ldisc.flush_buffer)
279 tty->ldisc.flush_buffer(tty);
280 break;
281 case TCIOFLUSH:
282 if (tty->ldisc.flush_buffer)
283 tty->ldisc.flush_buffer(tty);
284
285 case TCOFLUSH:
286 if (tty->driver.flush_buffer)
287 tty->driver.flush_buffer(tty);
288 break;
289 default:
290 return -EINVAL;
291 }
292 return 0;
293 case TIOCOUTQ:
294 retval = verify_area(VERIFY_WRITE, (void *) arg,
295 sizeof (unsigned long));
296 if (retval)
297 return retval;
298 if (tty->driver.chars_in_buffer)
299 put_fs_long(tty->driver.chars_in_buffer(tty),
300 (unsigned long *) arg);
301 else
302 put_fs_long(0, (unsigned long *) arg);
303 return 0;
304 case TIOCINQ:
305 retval = verify_area(VERIFY_WRITE, (void *) arg,
306 sizeof (unsigned long));
307 if (retval)
308 return retval;
309 if (L_ICANON(tty))
310 put_fs_long(inq_canon(tty),
311 (unsigned long *) arg);
312 else
313 put_fs_long(tty->read_cnt,
314 (unsigned long *) arg);
315 return 0;
316 case TIOCGLCKTRMIOS:
317 retval = verify_area(VERIFY_READ, (void *) arg,
318 sizeof (unsigned long));
319 if (retval)
320 return retval;
321 arg = get_fs_long((unsigned long *) arg);
322 retval = verify_area(VERIFY_WRITE, (void *) arg,
323 sizeof (struct termios));
324 if (retval)
325 return retval;
326 memcpy_tofs((struct termios *) arg,
327 &real_tty->termios_locked,
328 sizeof (struct termios));
329 return 0;
330 case TIOCSLCKTRMIOS:
331 if (!suser())
332 return -EPERM;
333 retval = verify_area(VERIFY_READ, (void *) arg,
334 sizeof (unsigned long));
335 if (retval)
336 return retval;
337 arg = get_fs_long((unsigned long *) arg);
338 retval = verify_area(VERIFY_READ, (void *) arg,
339 sizeof (struct termios));
340 if (retval)
341 return retval;
342 memcpy_fromfs(&real_tty->termios_locked,
343 (struct termios *) arg,
344 sizeof (struct termios));
345 return 0;
346 case TIOCPKT:
347 if (tty->driver.type != TTY_DRIVER_TYPE_PTY ||
348 tty->driver.subtype != PTY_TYPE_MASTER)
349 return -ENOTTY;
350 retval = verify_area(VERIFY_READ, (void *) arg,
351 sizeof (unsigned long));
352 if (retval)
353 return retval;
354 if (get_fs_long(arg)) {
355 if (!tty->packet) {
356 tty->packet = 1;
357 tty->link->ctrl_status = 0;
358 }
359 } else
360 tty->packet = 0;
361 return 0;
362
363
364 case TCSBRK: case TCSBRKP:
365 retval = tty_check_change(tty);
366 if (retval)
367 return retval;
368 wait_until_sent(tty, 0);
369 if (!tty->driver.ioctl)
370 return 0;
371 tty->driver.ioctl(tty, file, cmd, arg);
372 return 0;
373 default:
374 return -ENOIOCTLCMD;
375 }
376 }