]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/tty_compat.c
26efe41d531f9dcba19e5ab4e0d359d85c15b266
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
32 * Copyright (c) 1982, 1986, 1991, 1993
33 * The Regents of the University of California. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * @(#)tty_compat.c 8.1 (Berkeley) 6/10/93
67 * mapping routines for old line discipline (yuck)
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/ioctl.h>
73 #include <sys/proc_internal.h>
75 #include <sys/termios.h>
76 #include <sys/file_internal.h>
78 #include <sys/kernel.h>
79 #include <sys/sysctl.h>
80 #include <sys/syslog.h>
82 /* NeXT Move define down here cause COMPAT_43_TTY not valid earlier */
83 #if COMPAT_43_TTY || defined(COMPAT_SUNOS)
85 static int ttcompatgetflags(struct tty
*tp
);
86 static void ttcompatsetflags(struct tty
*tp
, struct termios
*t
);
87 static void ttcompatsetlflags(struct tty
*tp
, struct termios
*t
);
88 static int ttcompatspeedtab(int speed
, struct speedtab
*table
);
91 * These two tables encode baud rate to speed code and speed code to
92 * baud rate information. They are a mapping between the <sys/termios.h>
93 * baud rate constants and the <sys/ttydev.h> baud rate constants. We
94 * cannot use those constants directly here because they occupy the same
97 static struct speedtab compatspeeds
[] = {
119 static int compatspcodes
[] = {
120 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
121 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
127 * Description: Given a baud rate value as an integer, and a speed table,
128 * convert the baud rate to a speed code, according to the
129 * contents of the table. This effectively changes termios.h
130 * baud rate values into ttydev.h baud rate codes.
132 * Parameters: int speed Baud rate, as an integer
133 * struct speedtab *table Baud rate table to speed code table
135 * Returns: 1 B50 speed code; returned if we can
136 * not find an answer in the table.
137 * 0 If a 0 was requested in order to
138 * trigger a hangup (250ms of line
139 * silence, per Bell 103C standard).
140 * * A speed code matching the requested
141 * baud rate (potentially rounded down,
142 * if there is no exact match).
144 * Notes: This function is used for TIOCGETP, TIOCSETP, and TIOCSETN.
147 ttcompatspeedtab(int speed
, struct speedtab
*table
)
150 return (0); /* hangup */
151 for ( ; table
->sp_speed
> 0; table
++)
152 if (table
->sp_speed
<= speed
) /* nearest one, rounded down */
153 return (table
->sp_code
);
154 return (1); /* 50, min and not hangup */
160 * Description: Convert backward compatability set command arguments as
163 * TIOCSETP -> TIOSETAF
164 * TIOCSETN -> TIOCSETA
165 * TIOCSETC -> TIOCSETA
166 * TIOCSLTC -> TIOCSETA
167 * TIOCLBIS -> TIOCSETA
168 * TIOCLBIC -> TIOCSETA
169 * TIOCLSET -> TIOCSETA
171 * The converted command argument and potentially modified 'term'
172 * argument are returned to the caller, which will then call ttioctl(),
173 * if this function returns successfully.
175 * Parameters struct tty *tp The tty on which the operation is
177 * u_long *com A pointer to the terminal input/output
178 * command being requested; its contents
179 * will be modified per the table above,
180 * on a non-error return.
181 * caddr_t data Command specific parameter data; this
182 * data is read but not modified.
183 * struct termios *term A local stack termios structure from
184 * ttcompat(), whose contents are to be
185 * modified based on *com and *data.
187 * Returns: EINVAL An input speed or output speed is
188 * outside the allowable range for a
189 * TIOCSETP or TIOCSETN command.
190 * 0 All other cases return 0.
192 * Notes: This function may modify the contents of the tp->t_flags
193 * field in a successful call to TIOCSETP, TIOCSETN, TIOCLBIS,
194 * TIOCLBIC, or TIOCLSET.
196 * All other tp fields will remain unmodifed, since the struct
197 * termious is a local stack copy from ttcompat(), and not the
198 * real thing. A subsequent call to ttioctl() in ttcompat(),
199 * however, may result in subsequent changes.
201 __private_extern__
int
202 ttsetcompat(struct tty
*tp
, u_long
*com
, caddr_t data
, struct termios
*term
)
207 * Wait for all characters queued for output to drain, then
208 * Discard all characters queued for input, and then set
209 * the input and output speeds and device flags, per the
210 * contents of the struct sgttyb that 'data' points to.
214 * Same as TIOCSETP, but the output is not drained, and any
215 * pending input is not discarded.
218 register struct sgttyb
*sg
= (struct sgttyb
*)data
;
221 if ((speed
= sg
->sg_ispeed
) > MAX_SPEED
|| speed
< 0)
223 else if (speed
!= ttcompatspeedtab(tp
->t_ispeed
, compatspeeds
))
224 term
->c_ispeed
= compatspcodes
[speed
];
226 term
->c_ispeed
= tp
->t_ispeed
;
227 if ((speed
= sg
->sg_ospeed
) > MAX_SPEED
|| speed
< 0)
229 else if (speed
!= ttcompatspeedtab(tp
->t_ospeed
, compatspeeds
))
230 term
->c_ospeed
= compatspcodes
[speed
];
232 term
->c_ospeed
= tp
->t_ospeed
;
233 term
->c_cc
[VERASE
] = sg
->sg_erase
;
234 term
->c_cc
[VKILL
] = sg
->sg_kill
;
235 tp
->t_flags
= (tp
->t_flags
&0xffff0000) | (sg
->sg_flags
&0xffff);
236 ttcompatsetflags(tp
, term
);
237 *com
= (*com
== TIOCSETP
) ? TIOCSETAF
: TIOCSETA
;
242 * Set the terminal control characters per the contents of
243 * the struct tchars that 'data' points to.
246 struct tchars
*tc
= (struct tchars
*)data
;
250 cc
[VINTR
] = tc
->t_intrc
;
251 cc
[VQUIT
] = tc
->t_quitc
;
252 cc
[VSTART
] = tc
->t_startc
;
253 cc
[VSTOP
] = tc
->t_stopc
;
254 cc
[VEOF
] = tc
->t_eofc
;
255 cc
[VEOL
] = tc
->t_brkc
;
256 if (tc
->t_brkc
== -1)
257 cc
[VEOL2
] = _POSIX_VDISABLE
;
263 * Set the terminal control characters per the contents of
264 * the struct ltchars that 'data' points to.
267 struct ltchars
*ltc
= (struct ltchars
*)data
;
271 cc
[VSUSP
] = ltc
->t_suspc
;
272 cc
[VDSUSP
] = ltc
->t_dsuspc
;
273 cc
[VREPRINT
] = ltc
->t_rprntc
;
274 cc
[VDISCARD
] = ltc
->t_flushc
;
275 cc
[VWERASE
] = ltc
->t_werasc
;
276 cc
[VLNEXT
] = ltc
->t_lnextc
;
282 * Set the bits in the terminal state local flags word
283 * (16 bits) for the terminal to the current bits OR
284 * those in the 16 bit value pointed to by 'data'.
288 * Clear the bits in the terminal state local flags word
289 * for the terminal to the current bits AND those bits NOT
290 * in the 16 bit value pointed to by 'data'.
294 * Set the terminal state local flags word to exactly those
295 * bits that correspond to the 16 bit value pointed to by
298 if (*com
== TIOCLSET
)
299 tp
->t_flags
= (tp
->t_flags
&0xffff) | *(int *)data
<<16;
302 (ttcompatgetflags(tp
)&0xffff0000)|(tp
->t_flags
&0xffff);
303 if (*com
== TIOCLBIS
)
304 tp
->t_flags
|= *(int *)data
<<16;
306 tp
->t_flags
&= ~(*(int *)data
<<16);
308 ttcompatsetlflags(tp
, term
);
318 * Description: For 'set' commands, convert the command and arguments as
319 * necessary, and call ttioctl(), returning the result as
320 * our result; for 'get' commands, obtain the requested data
321 * from the appropriate source, and return it in the expected
322 * format. If the command is not recognized, return EINVAL.
324 * Parameters struct tty *tp The tty on which the operation is
326 * u_long com The terminal input/output command
328 * caddr_t data The pointer to the user data argument
329 * provided with the command.
330 * int flag The file open flags (e.g. FREAD).
331 * struct proc *p The current process pointer for the
334 * Returns: 0 Most 'get' operations can't fail, and
335 * therefore return this.
336 * ENOTTY TIOCGSID may return this when you
337 * attempt to get the session ID for a
338 * terminal with no associated session,
339 * or for which there is a session, but
341 * EIOCTL If the command cannot be handled at
342 * this layer, this will be returned.
343 * * Any value returned by ttioctl(), if a
344 * set command is requested.
346 * NOTES: The process pointer may be a proxy on whose behalf we are
347 * operating, so it is not safe to simply use current_process()
351 __private_extern__
int
352 ttcompat(struct tty
*tp
, u_long com
, caddr_t data
, int flag
, struct proc
*p
)
363 * See ttsetcompat() for a full description of these command
364 * values and their meanings.
370 term
= tp
->t_termios
;
371 if ((error
= ttsetcompat(tp
, &com
, data
, &term
)) != 0)
373 return ttioctl(tp
, com
, (caddr_t
) &term
, flag
, p
);
377 * Get the current input and output speeds, and device
378 * flags, into the structure pointed to by 'data'.
381 register struct sgttyb
*sg
= (struct sgttyb
*)data
;
382 register cc_t
*cc
= tp
->t_cc
;
384 sg
->sg_ospeed
= ttcompatspeedtab(tp
->t_ospeed
, compatspeeds
);
385 if (tp
->t_ispeed
== 0)
386 sg
->sg_ispeed
= sg
->sg_ospeed
;
388 sg
->sg_ispeed
= ttcompatspeedtab(tp
->t_ispeed
, compatspeeds
);
389 sg
->sg_erase
= cc
[VERASE
];
390 sg
->sg_kill
= cc
[VKILL
];
391 sg
->sg_flags
= tp
->t_flags
= ttcompatgetflags(tp
);
396 * Get the terminal control characters into the struct
397 * tchars that 'data' points to.
400 struct tchars
*tc
= (struct tchars
*)data
;
401 register cc_t
*cc
= tp
->t_cc
;
403 tc
->t_intrc
= cc
[VINTR
];
404 tc
->t_quitc
= cc
[VQUIT
];
405 tc
->t_startc
= cc
[VSTART
];
406 tc
->t_stopc
= cc
[VSTOP
];
407 tc
->t_eofc
= cc
[VEOF
];
408 tc
->t_brkc
= cc
[VEOL
];
413 * Get the terminal control characters into the struct
414 * ltchars that 'data' points to.
417 struct ltchars
*ltc
= (struct ltchars
*)data
;
418 register cc_t
*cc
= tp
->t_cc
;
420 ltc
->t_suspc
= cc
[VSUSP
];
421 ltc
->t_dsuspc
= cc
[VDSUSP
];
422 ltc
->t_rprntc
= cc
[VREPRINT
];
423 ltc
->t_flushc
= cc
[VDISCARD
];
424 ltc
->t_werasc
= cc
[VWERASE
];
425 ltc
->t_lnextc
= cc
[VLNEXT
];
430 * Get the terminal state local flags word into the 16 bit
431 * value pointed to by 'data'.
434 (ttcompatgetflags(tp
) & 0xffff0000UL
)
435 | (tp
->t_flags
& 0xffff);
436 *(int *)data
= tp
->t_flags
>>16;
441 * Get the current line discipline into the int pointed to
444 *(int *)data
= tp
->t_line
? tp
->t_line
: 2;
449 * Set the current line discipline based on the value of the
450 * int pointed to by 'data'.
455 return (ttioctl(tp
, TIOCSETD
,
456 *(int *)data
== 2 ? (caddr_t
)&ldisczero
: data
, flag
, p
));
461 * Become the console device.
464 return (ttioctl(tp
, TIOCCONS
, data
, flag
, p
));
468 * Get the current session ID (controlling process' PID).
470 if (tp
->t_session
== NULL
)
473 if (tp
->t_session
->s_leader
== NULL
)
476 *(int *) data
= tp
->t_session
->s_leader
->p_pid
;
481 * This ioctl is not handled at this layer.
487 * Successful 'get' operation.
495 * Description: Get the terminal state local flags, device flags, and current
496 * speed code for the device (all 32 bits are returned).
498 * Parameters struct tty *tp The tty on which the operation is
501 * Returns: * Integer value corresponding to the
502 * current terminal state local flags
505 * Notes: Caller is responsible for breaking these bits back out into
506 * separate 16 bit filelds, if that's what was actually desired.
509 ttcompatgetflags(struct tty
*tp
)
511 register tcflag_t iflag
= tp
->t_iflag
;
512 register tcflag_t lflag
= tp
->t_lflag
;
513 register tcflag_t oflag
= tp
->t_oflag
;
514 register tcflag_t cflag
= tp
->t_cflag
;
515 register int flags
= 0;
519 if (iflag
&ICRNL
|| oflag
&ONLCR
)
521 if ((cflag
&CSIZE
) == CS8
) {
526 else if (cflag
&PARENB
) {
533 flags
|= EVENP
| ODDP
;
536 if ((lflag
&ICANON
) == 0) {
538 if (iflag
&(INPCK
|ISTRIP
|IXON
) || lflag
&(IEXTEN
|ISIG
)
539 || (cflag
&(CSIZE
|PARENB
)) != CS8
)
544 if (!(flags
&RAW
) && !(oflag
&OPOST
) && (cflag
&(CSIZE
|PARENB
)) == CS8
)
548 if ((cflag
&HUPCL
) == 0)
553 flags
|= CRTERA
|CRTBS
;
555 flags
|= CRTKIL
|CRTBS
;
560 if ((iflag
&IXANY
) == 0)
562 flags
|= lflag
&(ECHO
|TOSTOP
|FLUSHO
|PENDIN
|NOFLSH
);
569 * Description: Given a set of compatability flags, convert the compatability
570 * flags in the terminal flags fields into canonical flags in the
571 * provided termios struct.
573 * Parameters: struct tty *tp The tty on which the operation is
575 * struct termios *t The termios structure into which to
576 * return the converted flags.
578 * Returns: void (implicit: *t, modified)
581 ttcompatsetflags(struct tty
*tp
, struct termios
*t
)
583 register int flags
= tp
->t_flags
;
584 register tcflag_t iflag
= t
->c_iflag
;
585 register tcflag_t oflag
= t
->c_oflag
;
586 register tcflag_t lflag
= t
->c_lflag
;
587 register tcflag_t cflag
= t
->c_cflag
;
591 lflag
&= ~(ECHOCTL
|ISIG
|ICANON
|IEXTEN
);
593 iflag
&= ~(PARMRK
|IGNPAR
|IGNCR
|INLCR
);
594 iflag
|= BRKINT
|IXON
|IMAXBEL
;
595 lflag
|= ISIG
|IEXTEN
|ECHOCTL
; /* XXX was echoctl on ? */
617 cflag
&= ~(CSIZE
|PARENB
);
618 if (flags
&(RAW
|LITOUT
|PASS8
)) {
620 if (!(flags
&(RAW
|PASS8
))
621 || (flags
&(RAW
|PASS8
|ANYP
)) == (PASS8
|ANYP
))
625 if (flags
&(RAW
|LITOUT
))
634 /* XXX don't set INPCK if RAW or PASS8? */
635 if ((flags
&(EVENP
|ODDP
)) == EVENP
) {
638 } else if ((flags
&(EVENP
|ODDP
)) == ODDP
) {
647 if ((flags
&DECCTQ
) == 0)
660 * Description: Given a set of compatability terminal state local flags,
661 * convert the compatability flags in the terminal flags
662 * fields into canonical flags in the provided termios struct.
664 * Parameters: struct tty *tp The tty on which the operation is
666 * struct termios *t The termios structure into which to
667 * return the converted local flags.
669 * Returns: void (implicit: *t, modified)
672 ttcompatsetlflags(struct tty
*tp
, struct termios
*t
)
674 register int flags
= tp
->t_flags
;
675 register tcflag_t iflag
= t
->c_iflag
;
676 register tcflag_t oflag
= t
->c_oflag
;
677 register tcflag_t lflag
= t
->c_lflag
;
678 register tcflag_t cflag
= t
->c_cflag
;
680 iflag
&= ~(PARMRK
|IGNPAR
|IGNCR
|INLCR
);
701 if ((flags
&DECCTQ
) == 0)
713 lflag
&= ~(TOSTOP
|FLUSHO
|PENDIN
|NOFLSH
);
714 lflag
|= flags
&(TOSTOP
|FLUSHO
|PENDIN
|NOFLSH
);
717 * The next if-else statement is copied from above so don't bother
718 * checking it separately. We could avoid fiddlling with the
719 * character size if the mode is already RAW or if neither the
720 * LITOUT bit or the PASS8 bit is being changed, but the delta of
721 * the change is not available here and skipping the RAW case would
722 * make the code different from above.
724 cflag
&= ~(CSIZE
|PARENB
);
725 if (flags
&(RAW
|LITOUT
|PASS8
)) {
727 if (!(flags
&(RAW
|PASS8
))
728 || (flags
&(RAW
|PASS8
|ANYP
)) == (PASS8
|ANYP
))
732 if (flags
&(RAW
|LITOUT
))
746 #endif /* COMPAT_43_TTY || COMPAT_SUNOS */