Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 213502
b: refs/heads/master
c: d281da7
h: refs/heads/master
v: v3
  • Loading branch information
Alan Cox authored and Greg Kroah-Hartman committed Oct 22, 2010
1 parent 307eb92 commit 2fbc23f
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 68707539df1e9d12435e5d54ffedc7ded50fcd01
refs/heads/master: d281da7ff6f70efca0553c288bb883e8605b3862
21 changes: 21 additions & 0 deletions trunk/drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/serial.h>

#include <linux/uaccess.h>
#include <asm/system.h>
Expand Down Expand Up @@ -2511,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
return tty->ops->tiocmset(tty, file, set, clear);
}

static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
{
int retval = -EINVAL;
struct serial_icounter_struct icount;
memset(&icount, 0, sizeof(icount));
if (tty->ops->get_icount)
retval = tty->ops->get_icount(tty, &icount);
if (retval != 0)
return retval;
if (copy_to_user(arg, &icount, sizeof(icount)))
return -EFAULT;
return 0;
}

struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
{
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
Expand Down Expand Up @@ -2631,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCMBIC:
case TIOCMBIS:
return tty_tiocmset(tty, file, 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;
case TCFLSH:
switch (arg) {
case TCIFLUSH:
Expand Down
35 changes: 16 additions & 19 deletions trunk/drivers/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1074,30 +1074,30 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
static int uart_get_count(struct uart_state *state,
struct serial_icounter_struct __user *icnt)
static int uart_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct serial_icounter_struct icount;
struct uart_state *state = tty->driver_data;
struct uart_icount cnow;
struct uart_port *uport = state->uart_port;

spin_lock_irq(&uport->lock);
memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
spin_unlock_irq(&uport->lock);

icount.cts = cnow.cts;
icount.dsr = cnow.dsr;
icount.rng = cnow.rng;
icount.dcd = cnow.dcd;
icount.rx = cnow.rx;
icount.tx = cnow.tx;
icount.frame = cnow.frame;
icount.overrun = cnow.overrun;
icount.parity = cnow.parity;
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;

return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
return 0;
}

/*
Expand Down Expand Up @@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
case TIOCMIWAIT:
ret = uart_wait_modem_status(state, arg);
break;

case TIOCGICOUNT:
ret = uart_get_count(state, uarg);
break;
}

if (ret != -ENOIOCTLCMD)
Expand Down Expand Up @@ -2295,6 +2291,7 @@ static const struct tty_operations uart_ops = {
#endif
.tiocmget = uart_tiocmget,
.tiocmset = uart_tiocmset,
.get_icount = uart_get_icount,
#ifdef CONFIG_CONSOLE_POLL
.poll_init = uart_poll_init,
.poll_get_char = uart_poll_get_char,
Expand Down
13 changes: 13 additions & 0 deletions trunk/drivers/usb/serial/usb-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file,
return -EINVAL;
}

static int serial_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct usb_serial_port *port = tty->driver_data;

dbg("%s - port %d", __func__, port->number);

if (port->serial->type->get_icount)
return port->serial->type->get_icount(tty, icount);
return -EINVAL;
}

/*
* We would be calling tty_wakeup here, but unfortunately some line
* disciplines have an annoying habit of calling tty->write from
Expand Down Expand Up @@ -1195,6 +1207,7 @@ static const struct tty_operations serial_ops = {
.chars_in_buffer = serial_chars_in_buffer,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
.get_icount = serial_get_icount,
.cleanup = serial_cleanup,
.install = serial_install,
.proc_fops = &serial_proc_fops,
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/linux/tty_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@
* unless the tty also has a valid tty->termiox pointer.
*
* Optional: Called under the termios lock
*
* int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
*
* Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
* structure to complete. This method is optional and will only be called
* if provided (otherwise EINVAL will be returned).
*/

#include <linux/fs.h>
Expand All @@ -232,6 +238,7 @@

struct tty_struct;
struct tty_driver;
struct serial_icounter_struct;

struct tty_operations {
struct tty_struct * (*lookup)(struct tty_driver *driver,
Expand Down Expand Up @@ -268,6 +275,8 @@ struct tty_operations {
unsigned int set, unsigned int clear);
int (*resize)(struct tty_struct *tty, struct winsize *ws);
int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
int (*get_icount)(struct tty_struct *tty,
struct serial_icounter_struct *icount);
#ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct tty_driver *driver, int line, char *options);
int (*poll_get_char)(struct tty_driver *driver, int line);
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/usb/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ struct usb_serial_driver {
int (*tiocmget)(struct tty_struct *tty, struct file *file);
int (*tiocmset)(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
int (*get_icount)(struct tty_struct *tty,
struct serial_icounter_struct *icount);
/* Called by the tty layer for port level work. There may or may not
be an attached tty at this point */
void (*dtr_rts)(struct usb_serial_port *port, int on);
Expand Down

0 comments on commit 2fbc23f

Please sign in to comment.