mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
Merge branch 'work.tty-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull tty ioctl updates from Al Viro:
"This is the compat_ioctl work related to tty ioctls.
Quite a bit of dead code taken out, all tty-related stuff gone from
fs/compat_ioctl.c. A bunch of compat bugs fixed - some still remain,
but all more or less generic tty-related ioctls should be covered
(remaining issues are in things like driver-private ioctls in a pcmcia
serial card driver not getting properly handled in 32bit processes on
64bit host, etc)"
* 'work.tty-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (53 commits)
kill TIOCSERGSTRUCT
change semantics of ldisc ->compat_ioctl()
kill TIOCSER[SG]WILD
synclink_gt(): fix compat_ioctl()
pty: fix compat ioctls
compat_ioctl - kill keyboard ioctl handling
gigaset: add ->compat_ioctl()
vt_compat_ioctl(): clean up, use compat_ptr() properly
gigaset: don't try to printk userland buffer contents
dgnc: don't bother with (empty) stub for TCXONC
dgnc: leave TIOC[GS]SOFTCAR to ldisc
remove fallback to drivers for TIOCGICOUNT
dgnc: break-related ioctls won't reach ->ioctl()
kill the rest of tty COMPAT_IOCTL() entries
dgnc: TIOCM... won't reach ->ioctl()
isdn_tty: TCSBRK{,P} won't reach ->ioctl()
kill capinc_tty_ioctl()
take compat TIOC[SG]SERIAL treatment into tty_compat_ioctl()
synclink: reduce pointless checks in ->ioctl()
complete ->[sg]et_serial() switchover
...
This commit is contained in:
commit
44adbac8f7
56 changed files with 779 additions and 1522 deletions
|
|
@ -996,63 +996,55 @@ static void rs_unthrottle(struct tty_struct * tty)
|
|||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||
struct serial_struct __user * retinfo)
|
||||
static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
struct serial_state *state = tty->driver_data;
|
||||
|
||||
tty_lock(tty);
|
||||
tmp.line = tty->index;
|
||||
tmp.port = state->port;
|
||||
tmp.flags = state->tport.flags;
|
||||
tmp.xmit_fifo_size = state->xmit_fifo_size;
|
||||
tmp.baud_base = state->baud_base;
|
||||
tmp.close_delay = state->tport.close_delay;
|
||||
tmp.closing_wait = state->tport.closing_wait;
|
||||
tmp.custom_divisor = state->custom_divisor;
|
||||
ss->line = tty->index;
|
||||
ss->port = state->port;
|
||||
ss->flags = state->tport.flags;
|
||||
ss->xmit_fifo_size = state->xmit_fifo_size;
|
||||
ss->baud_base = state->baud_base;
|
||||
ss->close_delay = state->tport.close_delay;
|
||||
ss->closing_wait = state->tport.closing_wait;
|
||||
ss->custom_divisor = state->custom_divisor;
|
||||
tty_unlock(tty);
|
||||
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
|
||||
struct serial_struct __user * new_info)
|
||||
static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
|
||||
{
|
||||
struct serial_state *state = tty->driver_data;
|
||||
struct tty_port *port = &state->tport;
|
||||
struct serial_struct new_serial;
|
||||
bool change_spd;
|
||||
int retval = 0;
|
||||
|
||||
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
|
||||
return -EFAULT;
|
||||
|
||||
tty_lock(tty);
|
||||
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
||||
new_serial.custom_divisor != state->custom_divisor;
|
||||
if (new_serial.irq || new_serial.port != state->port ||
|
||||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
|
||||
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
|
||||
ss->custom_divisor != state->custom_divisor;
|
||||
if (ss->irq || ss->port != state->port ||
|
||||
ss->xmit_fifo_size != state->xmit_fifo_size) {
|
||||
tty_unlock(tty);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!serial_isroot()) {
|
||||
if ((new_serial.baud_base != state->baud_base) ||
|
||||
(new_serial.close_delay != port->close_delay) ||
|
||||
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
|
||||
((new_serial.flags & ~ASYNC_USR_MASK) !=
|
||||
if ((ss->baud_base != state->baud_base) ||
|
||||
(ss->close_delay != port->close_delay) ||
|
||||
(ss->xmit_fifo_size != state->xmit_fifo_size) ||
|
||||
((ss->flags & ~ASYNC_USR_MASK) !=
|
||||
(port->flags & ~ASYNC_USR_MASK))) {
|
||||
tty_unlock(tty);
|
||||
return -EPERM;
|
||||
}
|
||||
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
|
||||
(new_serial.flags & ASYNC_USR_MASK));
|
||||
state->custom_divisor = new_serial.custom_divisor;
|
||||
(ss->flags & ASYNC_USR_MASK));
|
||||
state->custom_divisor = ss->custom_divisor;
|
||||
goto check_and_exit;
|
||||
}
|
||||
|
||||
if (new_serial.baud_base < 9600) {
|
||||
if (ss->baud_base < 9600) {
|
||||
tty_unlock(tty);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1062,19 +1054,19 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
|
|||
* At this point, we start making changes.....
|
||||
*/
|
||||
|
||||
state->baud_base = new_serial.baud_base;
|
||||
state->baud_base = ss->baud_base;
|
||||
port->flags = ((port->flags & ~ASYNC_FLAGS) |
|
||||
(new_serial.flags & ASYNC_FLAGS));
|
||||
state->custom_divisor = new_serial.custom_divisor;
|
||||
port->close_delay = new_serial.close_delay * HZ/100;
|
||||
port->closing_wait = new_serial.closing_wait * HZ/100;
|
||||
(ss->flags & ASYNC_FLAGS));
|
||||
state->custom_divisor = ss->custom_divisor;
|
||||
port->close_delay = ss->close_delay * HZ/100;
|
||||
port->closing_wait = ss->closing_wait * HZ/100;
|
||||
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||||
|
||||
check_and_exit:
|
||||
if (tty_port_initialized(port)) {
|
||||
if (change_spd) {
|
||||
/* warn about deprecation unless clearing */
|
||||
if (new_serial.flags & ASYNC_SPD_MASK)
|
||||
if (ss->flags & ASYNC_SPD_MASK)
|
||||
dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
|
||||
change_speed(tty, state, NULL);
|
||||
}
|
||||
|
|
@ -1084,7 +1076,6 @@ check_and_exit:
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_lsr_info - get line status register info
|
||||
*
|
||||
|
|
@ -1224,30 +1215,19 @@ static int rs_ioctl(struct tty_struct *tty,
|
|||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
||||
return -ENODEV;
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
|
||||
if ((cmd != TIOCSERCONFIG) &&
|
||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
if (tty_io_error(tty))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
return get_serial_info(tty, info, argp);
|
||||
case TIOCSSERIAL:
|
||||
return set_serial_info(tty, info, argp);
|
||||
case TIOCSERCONFIG:
|
||||
return 0;
|
||||
|
||||
case TIOCSERGETLSR: /* Get line status register */
|
||||
return get_lsr_info(info, argp);
|
||||
|
||||
case TIOCSERGSTRUCT:
|
||||
if (copy_to_user(argp,
|
||||
info, sizeof(struct serial_state)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
|
||||
* - mask passed in arg for lines of interest
|
||||
|
|
@ -1288,12 +1268,6 @@ static int rs_ioctl(struct tty_struct *tty,
|
|||
finish_wait(&info->tport.delta_msr_wait, &wait);
|
||||
return ret;
|
||||
|
||||
case TIOCSERGWILD:
|
||||
case TIOCSERSWILD:
|
||||
/* "setserial -W" is called in Debian boot */
|
||||
printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
@ -1607,6 +1581,8 @@ static const struct tty_operations serial_ops = {
|
|||
.tiocmget = rs_tiocmget,
|
||||
.tiocmset = rs_tiocmset,
|
||||
.get_icount = rs_get_icount,
|
||||
.set_serial = set_serial_info,
|
||||
.get_serial = get_serial_info,
|
||||
.proc_show = rs_proc_show,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2257,44 +2257,45 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
|
|||
}
|
||||
} /* set_line_char */
|
||||
|
||||
static int cy_get_serial_info(struct cyclades_port *info,
|
||||
struct serial_struct __user *retinfo)
|
||||
static int cy_get_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct cyclades_port *info = tty->driver_data;
|
||||
struct cyclades_card *cinfo = info->card;
|
||||
struct serial_struct tmp = {
|
||||
.type = info->type,
|
||||
.line = info->line,
|
||||
.port = (info->card - cy_card) * 0x100 + info->line -
|
||||
cinfo->first_line,
|
||||
.irq = cinfo->irq,
|
||||
.flags = info->port.flags,
|
||||
.close_delay = info->port.close_delay,
|
||||
.closing_wait = info->port.closing_wait,
|
||||
.baud_base = info->baud,
|
||||
.custom_divisor = info->custom_divisor,
|
||||
};
|
||||
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
|
||||
return -ENODEV;
|
||||
ss->type = info->type;
|
||||
ss->line = info->line;
|
||||
ss->port = (info->card - cy_card) * 0x100 + info->line -
|
||||
cinfo->first_line;
|
||||
ss->irq = cinfo->irq;
|
||||
ss->flags = info->port.flags;
|
||||
ss->close_delay = info->port.close_delay;
|
||||
ss->closing_wait = info->port.closing_wait;
|
||||
ss->baud_base = info->baud;
|
||||
ss->custom_divisor = info->custom_divisor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
|
||||
struct serial_struct __user *new_info)
|
||||
static int cy_set_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct new_serial;
|
||||
struct cyclades_port *info = tty->driver_data;
|
||||
int old_flags;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
|
||||
return -EFAULT;
|
||||
if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&info->port.mutex);
|
||||
|
||||
old_flags = info->port.flags;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
if (new_serial.close_delay != info->port.close_delay ||
|
||||
new_serial.baud_base != info->baud ||
|
||||
(new_serial.flags & ASYNC_FLAGS &
|
||||
if (ss->close_delay != info->port.close_delay ||
|
||||
ss->baud_base != info->baud ||
|
||||
(ss->flags & ASYNC_FLAGS &
|
||||
~ASYNC_USR_MASK) !=
|
||||
(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
|
||||
{
|
||||
|
|
@ -2302,9 +2303,9 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
|
|||
return -EPERM;
|
||||
}
|
||||
info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
|
||||
(new_serial.flags & ASYNC_USR_MASK);
|
||||
info->baud = new_serial.baud_base;
|
||||
info->custom_divisor = new_serial.custom_divisor;
|
||||
(ss->flags & ASYNC_USR_MASK);
|
||||
info->baud = ss->baud_base;
|
||||
info->custom_divisor = ss->custom_divisor;
|
||||
goto check_and_exit;
|
||||
}
|
||||
|
||||
|
|
@ -2313,18 +2314,18 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
|
|||
* At this point, we start making changes.....
|
||||
*/
|
||||
|
||||
info->baud = new_serial.baud_base;
|
||||
info->custom_divisor = new_serial.custom_divisor;
|
||||
info->baud = ss->baud_base;
|
||||
info->custom_divisor = ss->custom_divisor;
|
||||
info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
|
||||
(new_serial.flags & ASYNC_FLAGS);
|
||||
info->port.close_delay = new_serial.close_delay * HZ / 100;
|
||||
info->port.closing_wait = new_serial.closing_wait * HZ / 100;
|
||||
(ss->flags & ASYNC_FLAGS);
|
||||
info->port.close_delay = ss->close_delay * HZ / 100;
|
||||
info->port.closing_wait = ss->closing_wait * HZ / 100;
|
||||
|
||||
check_and_exit:
|
||||
if (tty_port_initialized(&info->port)) {
|
||||
if ((new_serial.flags ^ old_flags) & ASYNC_SPD_MASK) {
|
||||
if ((ss->flags ^ old_flags) & ASYNC_SPD_MASK) {
|
||||
/* warn about deprecation unless clearing */
|
||||
if (new_serial.flags & ASYNC_SPD_MASK)
|
||||
if (ss->flags & ASYNC_SPD_MASK)
|
||||
dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
|
||||
}
|
||||
cy_set_line_char(info, tty);
|
||||
|
|
@ -2698,12 +2699,6 @@ cy_ioctl(struct tty_struct *tty,
|
|||
case CYGETWAIT:
|
||||
ret_val = info->port.closing_wait / (HZ / 100);
|
||||
break;
|
||||
case TIOCGSERIAL:
|
||||
ret_val = cy_get_serial_info(info, argp);
|
||||
break;
|
||||
case TIOCSSERIAL:
|
||||
ret_val = cy_set_serial_info(info, tty, argp);
|
||||
break;
|
||||
case TIOCSERGETLSR: /* Get line status register */
|
||||
ret_val = get_lsr_info(info, argp);
|
||||
break;
|
||||
|
|
@ -4011,6 +4006,8 @@ static const struct tty_operations cy_ops = {
|
|||
.tiocmget = cy_tiocmget,
|
||||
.tiocmset = cy_tiocmset,
|
||||
.get_icount = cy_get_icount,
|
||||
.set_serial = cy_set_serial_info,
|
||||
.get_serial = cy_get_serial_info,
|
||||
.proc_show = cyclades_proc_show,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -248,22 +248,29 @@ static int ipw_write_room(struct tty_struct *linux_tty)
|
|||
return room;
|
||||
}
|
||||
|
||||
static int ipwireless_get_serial_info(struct ipw_tty *tty,
|
||||
struct serial_struct __user *retinfo)
|
||||
static int ipwireless_get_serial_info(struct tty_struct *linux_tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct ipw_tty *tty = linux_tty->driver_data;
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
tmp.type = PORT_UNKNOWN;
|
||||
tmp.line = tty->index;
|
||||
tmp.baud_base = 115200;
|
||||
if (!tty)
|
||||
return -ENODEV;
|
||||
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
if (!tty->port.count)
|
||||
return -EINVAL;
|
||||
|
||||
ss->type = PORT_UNKNOWN;
|
||||
ss->line = tty->index;
|
||||
ss->baud_base = 115200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipwireless_set_serial_info(struct tty_struct *linux_tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
return 0; /* Keeps the PCMCIA scripts happy. */
|
||||
}
|
||||
|
||||
static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
|
||||
{
|
||||
struct ipw_tty *tty = linux_tty->driver_data;
|
||||
|
|
@ -386,15 +393,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty,
|
|||
return -EINVAL;
|
||||
|
||||
/* FIXME: Exactly how is the tty object locked here .. */
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
return ipwireless_get_serial_info(tty, (void __user *) arg);
|
||||
|
||||
case TIOCSSERIAL:
|
||||
return 0; /* Keeps the PCMCIA scripts happy. */
|
||||
}
|
||||
|
||||
if (tty->tty_type == TTYTYPE_MODEM) {
|
||||
switch (cmd) {
|
||||
case PPPIOCGCHAN:
|
||||
|
|
@ -561,6 +559,8 @@ static const struct tty_operations tty_ops = {
|
|||
.chars_in_buffer = ipw_chars_in_buffer,
|
||||
.tiocmget = ipw_tiocmget,
|
||||
.tiocmset = ipw_tiocmset,
|
||||
.set_serial = ipwireless_set_serial_info,
|
||||
.get_serial = ipwireless_get_serial_info,
|
||||
};
|
||||
|
||||
int ipwireless_tty_init(void)
|
||||
|
|
|
|||
|
|
@ -1091,34 +1091,33 @@ static int isicom_tiocmset(struct tty_struct *tty,
|
|||
}
|
||||
|
||||
static int isicom_set_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct __user *info)
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct isi_port *port = tty->driver_data;
|
||||
struct serial_struct newinfo;
|
||||
int reconfig_port;
|
||||
|
||||
if (copy_from_user(&newinfo, info, sizeof(newinfo)))
|
||||
return -EFAULT;
|
||||
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&port->port.mutex);
|
||||
reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
|
||||
(newinfo.flags & ASYNC_SPD_MASK));
|
||||
(ss->flags & ASYNC_SPD_MASK));
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
if ((newinfo.close_delay != port->port.close_delay) ||
|
||||
(newinfo.closing_wait != port->port.closing_wait) ||
|
||||
((newinfo.flags & ~ASYNC_USR_MASK) !=
|
||||
if ((ss->close_delay != port->port.close_delay) ||
|
||||
(ss->closing_wait != port->port.closing_wait) ||
|
||||
((ss->flags & ~ASYNC_USR_MASK) !=
|
||||
(port->port.flags & ~ASYNC_USR_MASK))) {
|
||||
mutex_unlock(&port->port.mutex);
|
||||
return -EPERM;
|
||||
}
|
||||
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
|
||||
(newinfo.flags & ASYNC_USR_MASK));
|
||||
(ss->flags & ASYNC_USR_MASK));
|
||||
} else {
|
||||
port->port.close_delay = newinfo.close_delay;
|
||||
port->port.closing_wait = newinfo.closing_wait;
|
||||
port->port.close_delay = ss->close_delay;
|
||||
port->port.closing_wait = ss->closing_wait;
|
||||
port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
|
||||
(newinfo.flags & ASYNC_FLAGS));
|
||||
(ss->flags & ASYNC_FLAGS));
|
||||
}
|
||||
if (reconfig_port) {
|
||||
unsigned long flags;
|
||||
|
|
@ -1130,46 +1129,24 @@ static int isicom_set_serial_info(struct tty_struct *tty,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int isicom_get_serial_info(struct isi_port *port,
|
||||
struct serial_struct __user *info)
|
||||
{
|
||||
struct serial_struct out_info;
|
||||
|
||||
mutex_lock(&port->port.mutex);
|
||||
memset(&out_info, 0, sizeof(out_info));
|
||||
/* out_info.type = ? */
|
||||
out_info.line = port - isi_ports;
|
||||
out_info.port = port->card->base;
|
||||
out_info.irq = port->card->irq;
|
||||
out_info.flags = port->port.flags;
|
||||
/* out_info.baud_base = ? */
|
||||
out_info.close_delay = port->port.close_delay;
|
||||
out_info.closing_wait = port->port.closing_wait;
|
||||
mutex_unlock(&port->port.mutex);
|
||||
if (copy_to_user(info, &out_info, sizeof(out_info)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isicom_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static int isicom_get_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct isi_port *port = tty->driver_data;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
|
||||
return -ENODEV;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
return isicom_get_serial_info(port, argp);
|
||||
|
||||
case TIOCSSERIAL:
|
||||
return isicom_set_serial_info(tty, argp);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
mutex_lock(&port->port.mutex);
|
||||
/* ss->type = ? */
|
||||
ss->line = port - isi_ports;
|
||||
ss->port = port->card->base;
|
||||
ss->irq = port->card->irq;
|
||||
ss->flags = port->port.flags;
|
||||
/* ss->baud_base = ? */
|
||||
ss->close_delay = port->port.close_delay;
|
||||
ss->closing_wait = port->port.closing_wait;
|
||||
mutex_unlock(&port->port.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1273,7 +1250,6 @@ static const struct tty_operations isicom_ops = {
|
|||
.flush_chars = isicom_flush_chars,
|
||||
.write_room = isicom_write_room,
|
||||
.chars_in_buffer = isicom_chars_in_buffer,
|
||||
.ioctl = isicom_ioctl,
|
||||
.set_termios = isicom_set_termios,
|
||||
.throttle = isicom_throttle,
|
||||
.unthrottle = isicom_unthrottle,
|
||||
|
|
@ -1284,6 +1260,8 @@ static const struct tty_operations isicom_ops = {
|
|||
.tiocmget = isicom_tiocmget,
|
||||
.tiocmset = isicom_tiocmset,
|
||||
.break_ctl = isicom_send_break,
|
||||
.get_serial = isicom_get_serial_info,
|
||||
.set_serial = isicom_set_serial_info,
|
||||
};
|
||||
|
||||
static const struct tty_port_operations isicom_port_ops = {
|
||||
|
|
|
|||
|
|
@ -221,8 +221,8 @@ static int MoxaPortRxQueue(struct moxa_port *);
|
|||
static int MoxaPortTxFree(struct moxa_port *);
|
||||
static void MoxaPortTxDisable(struct moxa_port *);
|
||||
static void MoxaPortTxEnable(struct moxa_port *);
|
||||
static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
|
||||
static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
|
||||
static int moxa_get_serial_info(struct tty_struct *, struct serial_struct *);
|
||||
static int moxa_set_serial_info(struct tty_struct *, struct serial_struct *);
|
||||
static void MoxaSetFifo(struct moxa_port *port, int enable);
|
||||
|
||||
/*
|
||||
|
|
@ -375,16 +375,6 @@ copy:
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TIOCGSERIAL:
|
||||
mutex_lock(&ch->port.mutex);
|
||||
ret = moxa_get_serial_info(ch, argp);
|
||||
mutex_unlock(&ch->port.mutex);
|
||||
break;
|
||||
case TIOCSSERIAL:
|
||||
mutex_lock(&ch->port.mutex);
|
||||
ret = moxa_set_serial_info(ch, argp);
|
||||
mutex_unlock(&ch->port.mutex);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
@ -415,6 +405,8 @@ static const struct tty_operations moxa_ops = {
|
|||
.break_ctl = moxa_break_ctl,
|
||||
.tiocmget = moxa_tiocmget,
|
||||
.tiocmset = moxa_tiocmset,
|
||||
.set_serial = moxa_set_serial_info,
|
||||
.get_serial = moxa_get_serial_info,
|
||||
};
|
||||
|
||||
static const struct tty_port_operations moxa_port_ops = {
|
||||
|
|
@ -2034,46 +2026,55 @@ static void MoxaPortTxEnable(struct moxa_port *port)
|
|||
moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
|
||||
}
|
||||
|
||||
static int moxa_get_serial_info(struct moxa_port *info,
|
||||
struct serial_struct __user *retinfo)
|
||||
static int moxa_get_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct tmp = {
|
||||
.type = info->type,
|
||||
.line = info->port.tty->index,
|
||||
.flags = info->port.flags,
|
||||
.baud_base = 921600,
|
||||
.close_delay = info->port.close_delay
|
||||
};
|
||||
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
|
||||
struct moxa_port *info = tty->driver_data;
|
||||
|
||||
if (tty->index == MAX_PORTS)
|
||||
return -EINVAL;
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
mutex_lock(&info->port.mutex);
|
||||
ss->type = info->type,
|
||||
ss->line = info->port.tty->index,
|
||||
ss->flags = info->port.flags,
|
||||
ss->baud_base = 921600,
|
||||
ss->close_delay = info->port.close_delay;
|
||||
mutex_unlock(&info->port.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int moxa_set_serial_info(struct moxa_port *info,
|
||||
struct serial_struct __user *new_info)
|
||||
static int moxa_set_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct new_serial;
|
||||
struct moxa_port *info = tty->driver_data;
|
||||
|
||||
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
|
||||
return -EFAULT;
|
||||
if (tty->index == MAX_PORTS)
|
||||
return -EINVAL;
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
if (new_serial.irq != 0 || new_serial.port != 0 ||
|
||||
new_serial.custom_divisor != 0 ||
|
||||
new_serial.baud_base != 921600)
|
||||
if (ss->irq != 0 || ss->port != 0 ||
|
||||
ss->custom_divisor != 0 ||
|
||||
ss->baud_base != 921600)
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&info->port.mutex);
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
if (((new_serial.flags & ~ASYNC_USR_MASK) !=
|
||||
(info->port.flags & ~ASYNC_USR_MASK)))
|
||||
if (((ss->flags & ~ASYNC_USR_MASK) !=
|
||||
(info->port.flags & ~ASYNC_USR_MASK))) {
|
||||
mutex_unlock(&info->port.mutex);
|
||||
return -EPERM;
|
||||
} else
|
||||
info->port.close_delay = new_serial.close_delay * HZ / 100;
|
||||
}
|
||||
}
|
||||
info->port.close_delay = ss->close_delay * HZ / 100;
|
||||
|
||||
new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
|
||||
new_serial.flags |= (info->port.flags & ASYNC_FLAGS);
|
||||
MoxaSetFifo(info, ss->type == PORT_16550A);
|
||||
|
||||
MoxaSetFifo(info, new_serial.type == PORT_16550A);
|
||||
|
||||
info->type = new_serial.type;
|
||||
info->type = ss->type;
|
||||
mutex_unlock(&info->port.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1207,76 +1207,90 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
|
|||
* ------------------------------------------------------------
|
||||
*/
|
||||
static int mxser_get_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct __user *retinfo)
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
struct serial_struct tmp = {
|
||||
.type = info->type,
|
||||
.line = tty->index,
|
||||
.port = info->ioaddr,
|
||||
.irq = info->board->irq,
|
||||
.flags = info->port.flags,
|
||||
.baud_base = info->baud_base,
|
||||
.close_delay = info->port.close_delay,
|
||||
.closing_wait = info->port.closing_wait,
|
||||
.custom_divisor = info->custom_divisor,
|
||||
};
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
struct tty_port *port = &info->port;
|
||||
|
||||
if (tty->index == MXSER_PORTS)
|
||||
return -ENOTTY;
|
||||
|
||||
mutex_lock(&port->mutex);
|
||||
ss->type = info->type,
|
||||
ss->line = tty->index,
|
||||
ss->port = info->ioaddr,
|
||||
ss->irq = info->board->irq,
|
||||
ss->flags = info->port.flags,
|
||||
ss->baud_base = info->baud_base,
|
||||
ss->close_delay = info->port.close_delay,
|
||||
ss->closing_wait = info->port.closing_wait,
|
||||
ss->custom_divisor = info->custom_divisor,
|
||||
mutex_unlock(&port->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxser_set_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct __user *new_info)
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
struct tty_port *port = &info->port;
|
||||
struct serial_struct new_serial;
|
||||
speed_t baud;
|
||||
unsigned long sl_flags;
|
||||
unsigned int flags;
|
||||
int retval = 0;
|
||||
|
||||
if (!new_info || !info->ioaddr)
|
||||
return -ENODEV;
|
||||
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
|
||||
return -EFAULT;
|
||||
if (tty->index == MXSER_PORTS)
|
||||
return -ENOTTY;
|
||||
if (tty_io_error(tty))
|
||||
return -EIO;
|
||||
|
||||
if (new_serial.irq != info->board->irq ||
|
||||
new_serial.port != info->ioaddr)
|
||||
mutex_lock(&port->mutex);
|
||||
if (!info->ioaddr) {
|
||||
mutex_unlock(&port->mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ss->irq != info->board->irq ||
|
||||
ss->port != info->ioaddr) {
|
||||
mutex_unlock(&port->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = port->flags & ASYNC_SPD_MASK;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
if ((new_serial.baud_base != info->baud_base) ||
|
||||
(new_serial.close_delay != info->port.close_delay) ||
|
||||
((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK)))
|
||||
if ((ss->baud_base != info->baud_base) ||
|
||||
(ss->close_delay != info->port.close_delay) ||
|
||||
((ss->flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) {
|
||||
mutex_unlock(&port->mutex);
|
||||
return -EPERM;
|
||||
}
|
||||
info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
|
||||
(new_serial.flags & ASYNC_USR_MASK));
|
||||
(ss->flags & ASYNC_USR_MASK));
|
||||
} else {
|
||||
/*
|
||||
* OK, past this point, all the error checking has been done.
|
||||
* At this point, we start making changes.....
|
||||
*/
|
||||
port->flags = ((port->flags & ~ASYNC_FLAGS) |
|
||||
(new_serial.flags & ASYNC_FLAGS));
|
||||
port->close_delay = new_serial.close_delay * HZ / 100;
|
||||
port->closing_wait = new_serial.closing_wait * HZ / 100;
|
||||
(ss->flags & ASYNC_FLAGS));
|
||||
port->close_delay = ss->close_delay * HZ / 100;
|
||||
port->closing_wait = ss->closing_wait * HZ / 100;
|
||||
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||||
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
|
||||
(new_serial.baud_base != info->baud_base ||
|
||||
new_serial.custom_divisor !=
|
||||
(ss->baud_base != info->baud_base ||
|
||||
ss->custom_divisor !=
|
||||
info->custom_divisor)) {
|
||||
if (new_serial.custom_divisor == 0)
|
||||
if (ss->custom_divisor == 0) {
|
||||
mutex_unlock(&port->mutex);
|
||||
return -EINVAL;
|
||||
baud = new_serial.baud_base / new_serial.custom_divisor;
|
||||
}
|
||||
baud = ss->baud_base / ss->custom_divisor;
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
}
|
||||
}
|
||||
|
||||
info->type = new_serial.type;
|
||||
info->type = ss->type;
|
||||
|
||||
process_txrx_fifo(info);
|
||||
|
||||
|
|
@ -1291,6 +1305,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
|
|||
if (retval == 0)
|
||||
tty_port_set_initialized(port, 1);
|
||||
}
|
||||
mutex_unlock(&port->mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -1660,11 +1675,9 @@ static int mxser_ioctl(struct tty_struct *tty,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
struct tty_port *port = &info->port;
|
||||
struct async_icount cnow;
|
||||
unsigned long flags;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int retval;
|
||||
|
||||
if (tty->index == MXSER_PORTS)
|
||||
return mxser_ioctl_special(cmd, argp);
|
||||
|
|
@ -1708,20 +1721,10 @@ static int mxser_ioctl(struct tty_struct *tty,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && tty_io_error(tty))
|
||||
if (cmd != TIOCMIWAIT && tty_io_error(tty))
|
||||
return -EIO;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
mutex_lock(&port->mutex);
|
||||
retval = mxser_get_serial_info(tty, argp);
|
||||
mutex_unlock(&port->mutex);
|
||||
return retval;
|
||||
case TIOCSSERIAL:
|
||||
mutex_lock(&port->mutex);
|
||||
retval = mxser_set_serial_info(tty, argp);
|
||||
mutex_unlock(&port->mutex);
|
||||
return retval;
|
||||
case TIOCSERGETLSR: /* Get line status register */
|
||||
return mxser_get_lsr_info(info, argp);
|
||||
/*
|
||||
|
|
@ -2325,6 +2328,8 @@ static const struct tty_operations mxser_ops = {
|
|||
.wait_until_sent = mxser_wait_until_sent,
|
||||
.tiocmget = mxser_tiocmget,
|
||||
.tiocmset = mxser_tiocmset,
|
||||
.set_serial = mxser_set_serial_info,
|
||||
.get_serial = mxser_get_serial_info,
|
||||
.get_icount = mxser_get_icount,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2614,14 +2614,6 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long gsmld_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return gsmld_ioctl(tty, file, cmd, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Network interface
|
||||
*
|
||||
|
|
@ -2833,9 +2825,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
|
|||
.flush_buffer = gsmld_flush_buffer,
|
||||
.read = gsmld_read,
|
||||
.write = gsmld_write,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = gsmld_compat_ioctl,
|
||||
#endif
|
||||
.ioctl = gsmld_ioctl,
|
||||
.poll = gsmld_poll,
|
||||
.receive_buf = gsmld_receive_buf,
|
||||
|
|
|
|||
|
|
@ -134,6 +134,10 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
|||
const unsigned char *buf, size_t nr);
|
||||
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#endif
|
||||
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
|
||||
static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
|
||||
struct poll_table_struct *wait);
|
||||
|
|
@ -149,6 +153,9 @@ static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
|
|||
.read = r3964_read,
|
||||
.write = r3964_write,
|
||||
.ioctl = r3964_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = r3964_compat_ioctl,
|
||||
#endif
|
||||
.set_termios = r3964_set_termios,
|
||||
.poll = r3964_poll,
|
||||
.receive_buf = r3964_receive_buf,
|
||||
|
|
@ -1210,6 +1217,21 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case R3964_ENABLE_SIGNALS:
|
||||
case R3964_SETPRIORITY:
|
||||
case R3964_USE_BCC:
|
||||
return r3964_ioctl(tty, file, cmd, arg);
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
{
|
||||
TRACE_L("set_termios");
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/mount.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
#undef TTY_DEBUG_HANGUP
|
||||
#ifdef TTY_DEBUG_HANGUP
|
||||
|
|
@ -488,6 +489,7 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long pty_bsd_compat_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
|
|
@ -495,8 +497,11 @@ static long pty_bsd_compat_ioctl(struct tty_struct *tty,
|
|||
* PTY ioctls don't require any special translation between 32-bit and
|
||||
* 64-bit userspace, they are already compatible.
|
||||
*/
|
||||
return pty_bsd_ioctl(tty, cmd, arg);
|
||||
return pty_bsd_ioctl(tty, cmd, (unsigned long)compat_ptr(arg));
|
||||
}
|
||||
#else
|
||||
#define pty_bsd_compat_ioctl NULL
|
||||
#endif
|
||||
|
||||
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
|
||||
/*
|
||||
|
|
@ -676,6 +681,7 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long pty_unix98_compat_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
|
|
@ -683,8 +689,12 @@ static long pty_unix98_compat_ioctl(struct tty_struct *tty,
|
|||
* PTY ioctls don't require any special translation between 32-bit and
|
||||
* 64-bit userspace, they are already compatible.
|
||||
*/
|
||||
return pty_unix98_ioctl(tty, cmd, arg);
|
||||
return pty_unix98_ioctl(tty, cmd,
|
||||
cmd == TIOCSIG ? arg : (unsigned long)compat_ptr(arg));
|
||||
}
|
||||
#else
|
||||
#define pty_unix98_compat_ioctl NULL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ptm_unix98_lookup - find a pty master
|
||||
|
|
|
|||
|
|
@ -778,17 +778,13 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int uart_get_info_user(struct tty_port *port,
|
||||
struct serial_struct __user *retinfo)
|
||||
static int uart_get_info_user(struct tty_struct *tty,
|
||||
struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
struct uart_state *state = tty->driver_data;
|
||||
struct tty_port *port = &state->port;
|
||||
|
||||
if (uart_get_info(port, &tmp) < 0)
|
||||
return -EIO;
|
||||
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
return uart_get_info(port, ss) < 0 ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
||||
|
|
@ -990,16 +986,13 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state,
|
||||
struct serial_struct __user *newinfo)
|
||||
static int uart_set_info_user(struct tty_struct *tty, struct serial_struct *ss)
|
||||
{
|
||||
struct serial_struct new_serial;
|
||||
struct uart_state *state = tty->driver_data;
|
||||
struct tty_port *port = &state->port;
|
||||
int retval;
|
||||
|
||||
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
|
||||
return -EFAULT;
|
||||
|
||||
down_write(&tty->termios_rwsem);
|
||||
/*
|
||||
* This semaphore protects port->count. It is also
|
||||
* very useful to prevent opens. Also, take the
|
||||
|
|
@ -1008,8 +1001,9 @@ static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state,
|
|||
* under us.
|
||||
*/
|
||||
mutex_lock(&port->mutex);
|
||||
retval = uart_set_info(tty, port, state, &new_serial);
|
||||
retval = uart_set_info(tty, port, state, ss);
|
||||
mutex_unlock(&port->mutex);
|
||||
up_write(&tty->termios_rwsem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -1325,26 +1319,11 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
|
|||
* These ioctls don't rely on the hardware to be present.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
ret = uart_get_info_user(port, uarg);
|
||||
break;
|
||||
|
||||
case TIOCSSERIAL:
|
||||
down_write(&tty->termios_rwsem);
|
||||
ret = uart_set_info_user(tty, state, uarg);
|
||||
up_write(&tty->termios_rwsem);
|
||||
break;
|
||||
|
||||
case TIOCSERCONFIG:
|
||||
down_write(&tty->termios_rwsem);
|
||||
ret = uart_do_autoconfig(tty, state);
|
||||
up_write(&tty->termios_rwsem);
|
||||
break;
|
||||
|
||||
case TIOCSERGWILD: /* obsolete */
|
||||
case TIOCSERSWILD: /* obsolete */
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != -ENOIOCTLCMD)
|
||||
|
|
@ -2413,6 +2392,8 @@ static const struct tty_operations uart_ops = {
|
|||
#endif
|
||||
.tiocmget = uart_tiocmget,
|
||||
.tiocmset = uart_tiocmset,
|
||||
.set_serial = uart_set_info_user,
|
||||
.get_serial = uart_get_info_user,
|
||||
.get_icount = uart_get_icount,
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_init = uart_poll_init,
|
||||
|
|
|
|||
|
|
@ -2959,8 +2959,7 @@ static int mgsl_ioctl(struct tty_struct *tty,
|
|||
if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl"))
|
||||
return -ENODEV;
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (cmd != TIOCMIWAIT) {
|
||||
if (tty_io_error(tty))
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1029,8 +1029,7 @@ static int ioctl(struct tty_struct *tty,
|
|||
return -ENODEV;
|
||||
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (cmd != TIOCMIWAIT) {
|
||||
if (tty_io_error(tty))
|
||||
return -EIO;
|
||||
}
|
||||
|
|
@ -1186,14 +1185,13 @@ static long slgt_compat_ioctl(struct tty_struct *tty,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct slgt_info *info = tty->driver_data;
|
||||
int rc = -ENOIOCTLCMD;
|
||||
int rc;
|
||||
|
||||
if (sanity_check(info, tty->name, "compat_ioctl"))
|
||||
return -ENODEV;
|
||||
DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case MGSL_IOCSPARAMS32:
|
||||
rc = set_params32(info, compat_ptr(arg));
|
||||
break;
|
||||
|
|
@ -1213,18 +1211,11 @@ static long slgt_compat_ioctl(struct tty_struct *tty,
|
|||
case MGSL_IOCWAITGPIO:
|
||||
case MGSL_IOCGXSYNC:
|
||||
case MGSL_IOCGXCTRL:
|
||||
case MGSL_IOCSTXIDLE:
|
||||
case MGSL_IOCTXENABLE:
|
||||
case MGSL_IOCRXENABLE:
|
||||
case MGSL_IOCTXABORT:
|
||||
case TIOCMIWAIT:
|
||||
case MGSL_IOCSIF:
|
||||
case MGSL_IOCSXSYNC:
|
||||
case MGSL_IOCSXCTRL:
|
||||
rc = ioctl(tty, cmd, arg);
|
||||
rc = ioctl(tty, cmd, (unsigned long)compat_ptr(arg));
|
||||
break;
|
||||
default:
|
||||
rc = ioctl(tty, cmd, arg);
|
||||
}
|
||||
|
||||
DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1259,8 +1259,7 @@ static int ioctl(struct tty_struct *tty,
|
|||
if (sanity_check(info, tty->name, "ioctl"))
|
||||
return -ENODEV;
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (cmd != TIOCMIWAIT) {
|
||||
if (tty_io_error(tty))
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
|
@ -2292,34 +2293,6 @@ static int tioccons(struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fionbio - non blocking ioctl
|
||||
* @file: file to set blocking value
|
||||
* @p: user parameter
|
||||
*
|
||||
* Historical tty interfaces had a blocking control ioctl before
|
||||
* the generic functionality existed. This piece of history is preserved
|
||||
* in the expected tty API of posix OS's.
|
||||
*
|
||||
* Locking: none, the open file handle ensures it won't go away.
|
||||
*/
|
||||
|
||||
static int fionbio(struct file *file, int __user *p)
|
||||
{
|
||||
int nonblock;
|
||||
|
||||
if (get_user(nonblock, p))
|
||||
return -EFAULT;
|
||||
|
||||
spin_lock(&file->f_lock);
|
||||
if (nonblock)
|
||||
file->f_flags |= O_NONBLOCK;
|
||||
else
|
||||
file->f_flags &= ~O_NONBLOCK;
|
||||
spin_unlock(&file->f_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tiocsetd - set line discipline
|
||||
* @tty: tty device
|
||||
|
|
@ -2488,22 +2461,40 @@ static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void tty_warn_deprecated_flags(struct serial_struct __user *ss)
|
||||
static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *ss)
|
||||
{
|
||||
static DEFINE_RATELIMIT_STATE(depr_flags,
|
||||
DEFAULT_RATELIMIT_INTERVAL,
|
||||
DEFAULT_RATELIMIT_BURST);
|
||||
char comm[TASK_COMM_LEN];
|
||||
struct serial_struct v;
|
||||
int flags;
|
||||
|
||||
if (get_user(flags, &ss->flags))
|
||||
return;
|
||||
if (copy_from_user(&v, ss, sizeof(struct serial_struct)))
|
||||
return -EFAULT;
|
||||
|
||||
flags &= ASYNC_DEPRECATED;
|
||||
flags = v.flags & ASYNC_DEPRECATED;
|
||||
|
||||
if (flags && __ratelimit(&depr_flags))
|
||||
pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
|
||||
__func__, get_task_comm(comm, current), flags);
|
||||
if (!tty->ops->set_serial)
|
||||
return -ENOTTY;
|
||||
return tty->ops->set_serial(tty, &v);
|
||||
}
|
||||
|
||||
static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user *ss)
|
||||
{
|
||||
struct serial_struct v;
|
||||
int err;
|
||||
|
||||
memset(&v, 0, sizeof(struct serial_struct));
|
||||
if (!tty->ops->get_serial)
|
||||
return -ENOTTY;
|
||||
err = tty->ops->get_serial(tty, &v);
|
||||
if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct)))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2566,8 +2557,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
return tiocswinsz(real_tty, p);
|
||||
case TIOCCONS:
|
||||
return real_tty != tty ? -EINVAL : tioccons(file);
|
||||
case FIONBIO:
|
||||
return fionbio(file, p);
|
||||
case TIOCEXCL:
|
||||
set_bit(TTY_EXCLUSIVE, &tty->flags);
|
||||
return 0;
|
||||
|
|
@ -2622,11 +2611,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case TIOCMBIS:
|
||||
return tty_tiocmset(tty, cmd, p);
|
||||
case TIOCGICOUNT:
|
||||
retval = tty_tiocgicount(tty, p);
|
||||
/* For the moment allow fall through to the old method */
|
||||
if (retval != -EINVAL)
|
||||
return retval;
|
||||
break;
|
||||
return tty_tiocgicount(tty, p);
|
||||
case TCFLSH:
|
||||
switch (arg) {
|
||||
case TCIFLUSH:
|
||||
|
|
@ -2637,8 +2622,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
break;
|
||||
case TIOCSSERIAL:
|
||||
tty_warn_deprecated_flags(p);
|
||||
break;
|
||||
return tty_tiocsserial(tty, p);
|
||||
case TIOCGSERIAL:
|
||||
return tty_tiocgserial(tty, p);
|
||||
case TIOCGPTPEER:
|
||||
/* Special because the struct file is needed */
|
||||
return ptm_open_peer(file, tty, (int)arg);
|
||||
|
|
@ -2666,6 +2652,81 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
struct serial_struct32 {
|
||||
compat_int_t type;
|
||||
compat_int_t line;
|
||||
compat_uint_t port;
|
||||
compat_int_t irq;
|
||||
compat_int_t flags;
|
||||
compat_int_t xmit_fifo_size;
|
||||
compat_int_t custom_divisor;
|
||||
compat_int_t baud_base;
|
||||
unsigned short close_delay;
|
||||
char io_type;
|
||||
char reserved_char[1];
|
||||
compat_int_t hub6;
|
||||
unsigned short closing_wait; /* time to wait before closing */
|
||||
unsigned short closing_wait2; /* no longer used... */
|
||||
compat_uint_t iomem_base;
|
||||
unsigned short iomem_reg_shift;
|
||||
unsigned int port_high;
|
||||
/* compat_ulong_t iomap_base FIXME */
|
||||
compat_int_t reserved[1];
|
||||
};
|
||||
|
||||
static int compat_tty_tiocsserial(struct tty_struct *tty,
|
||||
struct serial_struct32 __user *ss)
|
||||
{
|
||||
static DEFINE_RATELIMIT_STATE(depr_flags,
|
||||
DEFAULT_RATELIMIT_INTERVAL,
|
||||
DEFAULT_RATELIMIT_BURST);
|
||||
char comm[TASK_COMM_LEN];
|
||||
struct serial_struct32 v32;
|
||||
struct serial_struct v;
|
||||
int flags;
|
||||
|
||||
if (copy_from_user(&v32, ss, sizeof(struct serial_struct32)))
|
||||
return -EFAULT;
|
||||
|
||||
memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base));
|
||||
v.iomem_base = compat_ptr(v32.iomem_base);
|
||||
v.iomem_reg_shift = v32.iomem_reg_shift;
|
||||
v.port_high = v32.port_high;
|
||||
v.iomap_base = 0;
|
||||
|
||||
flags = v.flags & ASYNC_DEPRECATED;
|
||||
|
||||
if (flags && __ratelimit(&depr_flags))
|
||||
pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
|
||||
__func__, get_task_comm(comm, current), flags);
|
||||
if (!tty->ops->set_serial)
|
||||
return -ENOTTY;
|
||||
return tty->ops->set_serial(tty, &v);
|
||||
}
|
||||
|
||||
static int compat_tty_tiocgserial(struct tty_struct *tty,
|
||||
struct serial_struct32 __user *ss)
|
||||
{
|
||||
struct serial_struct32 v32;
|
||||
struct serial_struct v;
|
||||
int err;
|
||||
memset(&v, 0, sizeof(struct serial_struct));
|
||||
|
||||
if (!tty->ops->set_serial)
|
||||
return -ENOTTY;
|
||||
err = tty->ops->get_serial(tty, &v);
|
||||
if (!err) {
|
||||
memcpy(&v32, &v, offsetof(struct serial_struct32, iomem_base));
|
||||
v32.iomem_base = (unsigned long)v.iomem_base >> 32 ?
|
||||
0xfffffff : ptr_to_compat(v.iomem_base);
|
||||
v32.iomem_reg_shift = v.iomem_reg_shift;
|
||||
v32.port_high = v.port_high;
|
||||
if (copy_to_user(ss, &v32, sizeof(struct serial_struct32)))
|
||||
err = -EFAULT;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
static long tty_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
|
|
@ -2673,9 +2734,90 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
|
|||
struct tty_ldisc *ld;
|
||||
int retval = -ENOIOCTLCMD;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCSTI:
|
||||
case TIOCGWINSZ:
|
||||
case TIOCSWINSZ:
|
||||
case TIOCGEXCL:
|
||||
case TIOCGETD:
|
||||
case TIOCSETD:
|
||||
case TIOCGDEV:
|
||||
case TIOCMGET:
|
||||
case TIOCMSET:
|
||||
case TIOCMBIC:
|
||||
case TIOCMBIS:
|
||||
case TIOCGICOUNT:
|
||||
case TIOCGPGRP:
|
||||
case TIOCSPGRP:
|
||||
case TIOCGSID:
|
||||
case TIOCSERGETLSR:
|
||||
case TIOCGRS485:
|
||||
case TIOCSRS485:
|
||||
#ifdef TIOCGETP
|
||||
case TIOCGETP:
|
||||
case TIOCSETP:
|
||||
case TIOCSETN:
|
||||
#endif
|
||||
#ifdef TIOCGETC
|
||||
case TIOCGETC:
|
||||
case TIOCSETC:
|
||||
#endif
|
||||
#ifdef TIOCGLTC
|
||||
case TIOCGLTC:
|
||||
case TIOCSLTC:
|
||||
#endif
|
||||
case TCSETSF:
|
||||
case TCSETSW:
|
||||
case TCSETS:
|
||||
case TCGETS:
|
||||
#ifdef TCGETS2
|
||||
case TCGETS2:
|
||||
case TCSETSF2:
|
||||
case TCSETSW2:
|
||||
case TCSETS2:
|
||||
#endif
|
||||
case TCGETA:
|
||||
case TCSETAF:
|
||||
case TCSETAW:
|
||||
case TCSETA:
|
||||
case TIOCGLCKTRMIOS:
|
||||
case TIOCSLCKTRMIOS:
|
||||
#ifdef TCGETX
|
||||
case TCGETX:
|
||||
case TCSETX:
|
||||
case TCSETXW:
|
||||
case TCSETXF:
|
||||
#endif
|
||||
case TIOCGSOFTCAR:
|
||||
case TIOCSSOFTCAR:
|
||||
return tty_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
|
||||
case TIOCCONS:
|
||||
case TIOCEXCL:
|
||||
case TIOCNXCL:
|
||||
case TIOCVHANGUP:
|
||||
case TIOCSBRK:
|
||||
case TIOCCBRK:
|
||||
case TCSBRK:
|
||||
case TCSBRKP:
|
||||
case TCFLSH:
|
||||
case TIOCGPTPEER:
|
||||
case TIOCNOTTY:
|
||||
case TIOCSCTTY:
|
||||
case TCXONC:
|
||||
case TIOCMIWAIT:
|
||||
case TIOCSERCONFIG:
|
||||
return tty_ioctl(file, cmd, arg);
|
||||
}
|
||||
|
||||
if (tty_paranoia_check(tty, file_inode(file), "tty_ioctl"))
|
||||
return -EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCSSERIAL:
|
||||
return compat_tty_tiocsserial(tty, compat_ptr(arg));
|
||||
case TIOCGSERIAL:
|
||||
return compat_tty_tiocgserial(tty, compat_ptr(arg));
|
||||
}
|
||||
if (tty->ops->compat_ioctl) {
|
||||
retval = tty->ops->compat_ioctl(tty, cmd, arg);
|
||||
if (retval != -ENOIOCTLCMD)
|
||||
|
|
@ -2687,8 +2829,9 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
|
|||
return hung_up_tty_compat_ioctl(file, cmd, arg);
|
||||
if (ld->ops->compat_ioctl)
|
||||
retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
|
||||
else
|
||||
retval = n_tty_compat_ioctl_helper(tty, file, cmd, arg);
|
||||
if (retval == -ENOIOCTLCMD && ld->ops->ioctl)
|
||||
retval = ld->ops->ioctl(tty, file,
|
||||
(unsigned long)compat_ptr(cmd), arg);
|
||||
tty_ldisc_deref(ld);
|
||||
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -941,19 +941,3 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
|
|||
}
|
||||
}
|
||||
EXPORT_SYMBOL(n_tty_ioctl_helper);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case TIOCGLCKTRMIOS:
|
||||
case TIOCSLCKTRMIOS:
|
||||
return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1175,17 +1175,13 @@ long vt_compat_ioctl(struct tty_struct *tty,
|
|||
{
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
struct console_font_op op; /* used in multiple places here */
|
||||
unsigned int console;
|
||||
void __user *up = (void __user *)arg;
|
||||
unsigned int console = vc->vc_num;
|
||||
void __user *up = compat_ptr(arg);
|
||||
int perm;
|
||||
int ret = 0;
|
||||
|
||||
console = vc->vc_num;
|
||||
|
||||
if (!vc_cons_allocated(console)) { /* impossible? */
|
||||
ret = -ENOIOCTLCMD;
|
||||
goto out;
|
||||
}
|
||||
if (!vc_cons_allocated(console)) /* impossible? */
|
||||
return -ENOIOCTLCMD;
|
||||
|
||||
/*
|
||||
* To have permissions to do most of the vt ioctls, we either have
|
||||
|
|
@ -1201,17 +1197,14 @@ long vt_compat_ioctl(struct tty_struct *tty,
|
|||
*/
|
||||
case PIO_FONTX:
|
||||
case GIO_FONTX:
|
||||
ret = compat_fontx_ioctl(cmd, up, perm, &op);
|
||||
break;
|
||||
return compat_fontx_ioctl(cmd, up, perm, &op);
|
||||
|
||||
case KDFONTOP:
|
||||
ret = compat_kdfontop_ioctl(up, perm, &op, vc);
|
||||
break;
|
||||
return compat_kdfontop_ioctl(up, perm, &op, vc);
|
||||
|
||||
case PIO_UNIMAP:
|
||||
case GIO_UNIMAP:
|
||||
ret = compat_unimap_ioctl(cmd, up, perm, vc);
|
||||
break;
|
||||
return compat_unimap_ioctl(cmd, up, perm, vc);
|
||||
|
||||
/*
|
||||
* all these treat 'arg' as an integer
|
||||
|
|
@ -1236,21 +1229,15 @@ long vt_compat_ioctl(struct tty_struct *tty,
|
|||
case VT_DISALLOCATE:
|
||||
case VT_RESIZE:
|
||||
case VT_RESIZEX:
|
||||
goto fallback;
|
||||
return vt_ioctl(tty, cmd, arg);
|
||||
|
||||
/*
|
||||
* the rest has a compatible data structure behind arg,
|
||||
* but we have to convert it to a proper 64 bit pointer.
|
||||
*/
|
||||
default:
|
||||
arg = (unsigned long)compat_ptr(arg);
|
||||
goto fallback;
|
||||
return vt_ioctl(tty, cmd, (unsigned long)up);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
|
||||
fallback:
|
||||
return vt_ioctl(tty, cmd, arg);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue