162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/termios_internal.h>
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci/*
562306a36Sopenharmony_ci * c_cc characters in the termio structure.  Oh, how I love being
662306a36Sopenharmony_ci * backwardly compatible.  Notice that character 4 and 5 are
762306a36Sopenharmony_ci * interpreted differently depending on whether ICANON is set in
862306a36Sopenharmony_ci * c_lflag.  If it's set, they are used as _VEOF and _VEOL, otherwise
962306a36Sopenharmony_ci * as _VMIN and V_TIME.  This is for compatibility with OSF/1 (which
1062306a36Sopenharmony_ci * is compatible with sysV)...
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci#define _VMIN	4
1362306a36Sopenharmony_ci#define _VTIME	5
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ciint kernel_termios_to_user_termio(struct termio __user *termio,
1662306a36Sopenharmony_ci						struct ktermios *termios)
1762306a36Sopenharmony_ci{
1862306a36Sopenharmony_ci	struct termio v;
1962306a36Sopenharmony_ci	memset(&v, 0, sizeof(struct termio));
2062306a36Sopenharmony_ci	v.c_iflag = termios->c_iflag;
2162306a36Sopenharmony_ci	v.c_oflag = termios->c_oflag;
2262306a36Sopenharmony_ci	v.c_cflag = termios->c_cflag;
2362306a36Sopenharmony_ci	v.c_lflag = termios->c_lflag;
2462306a36Sopenharmony_ci	v.c_line = termios->c_line;
2562306a36Sopenharmony_ci	memcpy(v.c_cc, termios->c_cc, NCC);
2662306a36Sopenharmony_ci	if (!(v.c_lflag & ICANON)) {
2762306a36Sopenharmony_ci		v.c_cc[_VMIN] = termios->c_cc[VMIN];
2862306a36Sopenharmony_ci		v.c_cc[_VTIME] = termios->c_cc[VTIME];
2962306a36Sopenharmony_ci	}
3062306a36Sopenharmony_ci	return copy_to_user(termio, &v, sizeof(struct termio));
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciint user_termios_to_kernel_termios(struct ktermios *k,
3462306a36Sopenharmony_ci						 struct termios2 __user *u)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	int err;
3762306a36Sopenharmony_ci	err  = get_user(k->c_iflag, &u->c_iflag);
3862306a36Sopenharmony_ci	err |= get_user(k->c_oflag, &u->c_oflag);
3962306a36Sopenharmony_ci	err |= get_user(k->c_cflag, &u->c_cflag);
4062306a36Sopenharmony_ci	err |= get_user(k->c_lflag, &u->c_lflag);
4162306a36Sopenharmony_ci	err |= get_user(k->c_line,  &u->c_line);
4262306a36Sopenharmony_ci	err |= copy_from_user(k->c_cc, u->c_cc, NCCS);
4362306a36Sopenharmony_ci	if (k->c_lflag & ICANON) {
4462306a36Sopenharmony_ci		err |= get_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
4562306a36Sopenharmony_ci		err |= get_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
4662306a36Sopenharmony_ci	} else {
4762306a36Sopenharmony_ci		err |= get_user(k->c_cc[VMIN],  &u->c_cc[_VMIN]);
4862306a36Sopenharmony_ci		err |= get_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci	err |= get_user(k->c_ispeed,  &u->c_ispeed);
5162306a36Sopenharmony_ci	err |= get_user(k->c_ospeed,  &u->c_ospeed);
5262306a36Sopenharmony_ci	return err;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciint kernel_termios_to_user_termios(struct termios2 __user *u,
5662306a36Sopenharmony_ci						 struct ktermios *k)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	int err;
5962306a36Sopenharmony_ci	err  = put_user(k->c_iflag, &u->c_iflag);
6062306a36Sopenharmony_ci	err |= put_user(k->c_oflag, &u->c_oflag);
6162306a36Sopenharmony_ci	err |= put_user(k->c_cflag, &u->c_cflag);
6262306a36Sopenharmony_ci	err |= put_user(k->c_lflag, &u->c_lflag);
6362306a36Sopenharmony_ci	err |= put_user(k->c_line, &u->c_line);
6462306a36Sopenharmony_ci	err |= copy_to_user(u->c_cc, k->c_cc, NCCS);
6562306a36Sopenharmony_ci	if (!(k->c_lflag & ICANON)) {
6662306a36Sopenharmony_ci		err |= put_user(k->c_cc[VMIN],  &u->c_cc[_VMIN]);
6762306a36Sopenharmony_ci		err |= put_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
6862306a36Sopenharmony_ci	} else {
6962306a36Sopenharmony_ci		err |= put_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
7062306a36Sopenharmony_ci		err |= put_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci	err |= put_user(k->c_ispeed, &u->c_ispeed);
7362306a36Sopenharmony_ci	err |= put_user(k->c_ospeed, &u->c_ospeed);
7462306a36Sopenharmony_ci	return err;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciint user_termios_to_kernel_termios_1(struct ktermios *k,
7862306a36Sopenharmony_ci						 struct termios __user *u)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	int err;
8162306a36Sopenharmony_ci	err  = get_user(k->c_iflag, &u->c_iflag);
8262306a36Sopenharmony_ci	err |= get_user(k->c_oflag, &u->c_oflag);
8362306a36Sopenharmony_ci	err |= get_user(k->c_cflag, &u->c_cflag);
8462306a36Sopenharmony_ci	err |= get_user(k->c_lflag, &u->c_lflag);
8562306a36Sopenharmony_ci	err |= get_user(k->c_line,  &u->c_line);
8662306a36Sopenharmony_ci	err |= copy_from_user(k->c_cc, u->c_cc, NCCS);
8762306a36Sopenharmony_ci	if (k->c_lflag & ICANON) {
8862306a36Sopenharmony_ci		err |= get_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
8962306a36Sopenharmony_ci		err |= get_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
9062306a36Sopenharmony_ci	} else {
9162306a36Sopenharmony_ci		err |= get_user(k->c_cc[VMIN],  &u->c_cc[_VMIN]);
9262306a36Sopenharmony_ci		err |= get_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci	return err;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciint kernel_termios_to_user_termios_1(struct termios __user *u,
9862306a36Sopenharmony_ci						 struct ktermios *k)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	int err;
10162306a36Sopenharmony_ci	err  = put_user(k->c_iflag, &u->c_iflag);
10262306a36Sopenharmony_ci	err |= put_user(k->c_oflag, &u->c_oflag);
10362306a36Sopenharmony_ci	err |= put_user(k->c_cflag, &u->c_cflag);
10462306a36Sopenharmony_ci	err |= put_user(k->c_lflag, &u->c_lflag);
10562306a36Sopenharmony_ci	err |= put_user(k->c_line, &u->c_line);
10662306a36Sopenharmony_ci	err |= copy_to_user(u->c_cc, k->c_cc, NCCS);
10762306a36Sopenharmony_ci	if (!(k->c_lflag & ICANON)) {
10862306a36Sopenharmony_ci		err |= put_user(k->c_cc[VMIN],  &u->c_cc[_VMIN]);
10962306a36Sopenharmony_ci		err |= put_user(k->c_cc[VTIME], &u->c_cc[_VTIME]);
11062306a36Sopenharmony_ci	} else {
11162306a36Sopenharmony_ci		err |= put_user(k->c_cc[VEOF], &u->c_cc[VEOF]);
11262306a36Sopenharmony_ci		err |= put_user(k->c_cc[VEOL], &u->c_cc[VEOL]);
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci	return err;
11562306a36Sopenharmony_ci}
116