diff options
author | Alan Cox <alan@linux.intel.com> | 2010-09-16 13:21:24 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:20:04 -0400 |
commit | d281da7ff6f70efca0553c288bb883e8605b3862 (patch) | |
tree | ee6a46b33070159af51c07643cf99186f1ef3e03 /drivers | |
parent | 68707539df1e9d12435e5d54ffedc7ded50fcd01 (diff) |
tty: Make tiocgicount a handler
Dan Rosenberg noted that various drivers return the struct with uncleared
fields. Instead of spending forever trying to stomp all the drivers that
get it wrong (and every new driver) do the job in one place.
This first patch adds the needed operations and hooks them up, including
the needed USB midlayer and serial core plumbing.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/tty_io.c | 21 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 35 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 13 |
3 files changed, 50 insertions, 19 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e185db36f8ad..c05c5af5aa04 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -96,6 +96,7 @@ | |||
96 | #include <linux/bitops.h> | 96 | #include <linux/bitops.h> |
97 | #include <linux/delay.h> | 97 | #include <linux/delay.h> |
98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
99 | #include <linux/serial.h> | ||
99 | 100 | ||
100 | #include <linux/uaccess.h> | 101 | #include <linux/uaccess.h> |
101 | #include <asm/system.h> | 102 | #include <asm/system.h> |
@@ -2511,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
2511 | return tty->ops->tiocmset(tty, file, set, clear); | 2512 | return tty->ops->tiocmset(tty, file, set, clear); |
2512 | } | 2513 | } |
2513 | 2514 | ||
2515 | static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) | ||
2516 | { | ||
2517 | int retval = -EINVAL; | ||
2518 | struct serial_icounter_struct icount; | ||
2519 | memset(&icount, 0, sizeof(icount)); | ||
2520 | if (tty->ops->get_icount) | ||
2521 | retval = tty->ops->get_icount(tty, &icount); | ||
2522 | if (retval != 0) | ||
2523 | return retval; | ||
2524 | if (copy_to_user(arg, &icount, sizeof(icount))) | ||
2525 | return -EFAULT; | ||
2526 | return 0; | ||
2527 | } | ||
2528 | |||
2514 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) | 2529 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) |
2515 | { | 2530 | { |
2516 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 2531 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -2631,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2631 | case TIOCMBIC: | 2646 | case TIOCMBIC: |
2632 | case TIOCMBIS: | 2647 | case TIOCMBIS: |
2633 | return tty_tiocmset(tty, file, cmd, p); | 2648 | return tty_tiocmset(tty, file, cmd, p); |
2649 | case TIOCGICOUNT: | ||
2650 | retval = tty_tiocgicount(tty, p); | ||
2651 | /* For the moment allow fall through to the old method */ | ||
2652 | if (retval != -EINVAL) | ||
2653 | return retval; | ||
2654 | break; | ||
2634 | case TCFLSH: | 2655 | case TCFLSH: |
2635 | switch (arg) { | 2656 | switch (arg) { |
2636 | case TCIFLUSH: | 2657 | case TCIFLUSH: |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index bc6cddd10294..c4ea14670d44 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -1074,10 +1074,10 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) | |||
1074 | * NB: both 1->0 and 0->1 transitions are counted except for | 1074 | * NB: both 1->0 and 0->1 transitions are counted except for |
1075 | * RI where only 0->1 is counted. | 1075 | * RI where only 0->1 is counted. |
1076 | */ | 1076 | */ |
1077 | static int uart_get_count(struct uart_state *state, | 1077 | static int uart_get_icount(struct tty_struct *tty, |
1078 | struct serial_icounter_struct __user *icnt) | 1078 | struct serial_icounter_struct *icount) |
1079 | { | 1079 | { |
1080 | struct serial_icounter_struct icount; | 1080 | struct uart_state *state = tty->driver_data; |
1081 | struct uart_icount cnow; | 1081 | struct uart_icount cnow; |
1082 | struct uart_port *uport = state->uart_port; | 1082 | struct uart_port *uport = state->uart_port; |
1083 | 1083 | ||
@@ -1085,19 +1085,19 @@ static int uart_get_count(struct uart_state *state, | |||
1085 | memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); | 1085 | memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); |
1086 | spin_unlock_irq(&uport->lock); | 1086 | spin_unlock_irq(&uport->lock); |
1087 | 1087 | ||
1088 | icount.cts = cnow.cts; | 1088 | icount->cts = cnow.cts; |
1089 | icount.dsr = cnow.dsr; | 1089 | icount->dsr = cnow.dsr; |
1090 | icount.rng = cnow.rng; | 1090 | icount->rng = cnow.rng; |
1091 | icount.dcd = cnow.dcd; | 1091 | icount->dcd = cnow.dcd; |
1092 | icount.rx = cnow.rx; | 1092 | icount->rx = cnow.rx; |
1093 | icount.tx = cnow.tx; | 1093 | icount->tx = cnow.tx; |
1094 | icount.frame = cnow.frame; | 1094 | icount->frame = cnow.frame; |
1095 | icount.overrun = cnow.overrun; | 1095 | icount->overrun = cnow.overrun; |
1096 | icount.parity = cnow.parity; | 1096 | icount->parity = cnow.parity; |
1097 | icount.brk = cnow.brk; | 1097 | icount->brk = cnow.brk; |
1098 | icount.buf_overrun = cnow.buf_overrun; | 1098 | icount->buf_overrun = cnow.buf_overrun; |
1099 | 1099 | ||
1100 | return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; | 1100 | return 0; |
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | /* | 1103 | /* |
@@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1150 | case TIOCMIWAIT: | 1150 | case TIOCMIWAIT: |
1151 | ret = uart_wait_modem_status(state, arg); | 1151 | ret = uart_wait_modem_status(state, arg); |
1152 | break; | 1152 | break; |
1153 | |||
1154 | case TIOCGICOUNT: | ||
1155 | ret = uart_get_count(state, uarg); | ||
1156 | break; | ||
1157 | } | 1153 | } |
1158 | 1154 | ||
1159 | if (ret != -ENOIOCTLCMD) | 1155 | if (ret != -ENOIOCTLCMD) |
@@ -2295,6 +2291,7 @@ static const struct tty_operations uart_ops = { | |||
2295 | #endif | 2291 | #endif |
2296 | .tiocmget = uart_tiocmget, | 2292 | .tiocmget = uart_tiocmget, |
2297 | .tiocmset = uart_tiocmset, | 2293 | .tiocmset = uart_tiocmset, |
2294 | .get_icount = uart_get_icount, | ||
2298 | #ifdef CONFIG_CONSOLE_POLL | 2295 | #ifdef CONFIG_CONSOLE_POLL |
2299 | .poll_init = uart_poll_init, | 2296 | .poll_init = uart_poll_init, |
2300 | .poll_get_char = uart_poll_get_char, | 2297 | .poll_get_char = uart_poll_get_char, |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 7a2177c79bde..e64da74bdcc5 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file, | |||
519 | return -EINVAL; | 519 | return -EINVAL; |
520 | } | 520 | } |
521 | 521 | ||
522 | static int serial_get_icount(struct tty_struct *tty, | ||
523 | struct serial_icounter_struct *icount) | ||
524 | { | ||
525 | struct usb_serial_port *port = tty->driver_data; | ||
526 | |||
527 | dbg("%s - port %d", __func__, port->number); | ||
528 | |||
529 | if (port->serial->type->get_icount) | ||
530 | return port->serial->type->get_icount(tty, icount); | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
522 | /* | 534 | /* |
523 | * We would be calling tty_wakeup here, but unfortunately some line | 535 | * We would be calling tty_wakeup here, but unfortunately some line |
524 | * disciplines have an annoying habit of calling tty->write from | 536 | * disciplines have an annoying habit of calling tty->write from |
@@ -1195,6 +1207,7 @@ static const struct tty_operations serial_ops = { | |||
1195 | .chars_in_buffer = serial_chars_in_buffer, | 1207 | .chars_in_buffer = serial_chars_in_buffer, |
1196 | .tiocmget = serial_tiocmget, | 1208 | .tiocmget = serial_tiocmget, |
1197 | .tiocmset = serial_tiocmset, | 1209 | .tiocmset = serial_tiocmset, |
1210 | .get_icount = serial_get_icount, | ||
1198 | .cleanup = serial_cleanup, | 1211 | .cleanup = serial_cleanup, |
1199 | .install = serial_install, | 1212 | .install = serial_install, |
1200 | .proc_fops = &serial_proc_fops, | 1213 | .proc_fops = &serial_proc_fops, |