tty: rework break handling
Some hardware needs to do break handling itself and may have partial support only. Make break_ctl return an error code. Add a tty driver flag so you can indicate driver hardware side break support. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
abbe629ae4
Коммит
9e98966c7b
|
@ -218,7 +218,7 @@ config MOXA_SMARTIO
|
|||
|
||||
config ISI
|
||||
tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
|
||||
depends on SERIAL_NONSTANDARD && PCI
|
||||
depends on SERIAL_NONSTANDARD && PCI && BROKEN
|
||||
select FW_LOADER
|
||||
help
|
||||
This is a driver for the Multi-Tech cards which provide several
|
||||
|
|
|
@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
/*
|
||||
* rs_break() --- routine which turns the break handling on or off
|
||||
*/
|
||||
static void rs_break(struct tty_struct *tty, int break_state)
|
||||
static int rs_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state)
|
|||
custom.adkcon = AC_UARTBRK;
|
||||
mb();
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
/*
|
||||
* cy_break() --- routine which turns the break handling on or off
|
||||
*/
|
||||
static void cy_break(struct tty_struct *tty, int break_state)
|
||||
static int cy_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct cyclades_port *info = tty->driver_data;
|
||||
struct cyclades_card *card;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "cy_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
card = info->card;
|
||||
|
||||
|
@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
int retval;
|
||||
|
||||
if (break_state == -1) {
|
||||
retval = cyz_issue_cmd(card,
|
||||
info->line - card->first_line,
|
||||
|
@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state)
|
|||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&card->card_lock, flags);
|
||||
return retval;
|
||||
} /* cy_break */
|
||||
|
||||
static int get_mon_info(struct cyclades_port *info,
|
||||
|
|
|
@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
/*
|
||||
* rs_break() --- routine which turns the break handling on or off
|
||||
*/
|
||||
static void esp_break(struct tty_struct *tty, int break_state)
|
||||
static int esp_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct esp_struct *info = tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "esp_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
if (break_state == -1) {
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
|
@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state)
|
|||
serial_out(info, UART_ESI_CMD2, 0x00);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rs_ioctl(struct tty_struct *tty, struct file *file,
|
||||
|
|
|
@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty);
|
|||
static void stli_stop(struct tty_struct *tty);
|
||||
static void stli_start(struct tty_struct *tty);
|
||||
static void stli_flushbuffer(struct tty_struct *tty);
|
||||
static void stli_breakctl(struct tty_struct *tty, int state);
|
||||
static int stli_breakctl(struct tty_struct *tty, int state);
|
||||
static void stli_waituntilsent(struct tty_struct *tty, int timeout);
|
||||
static void stli_sendxchar(struct tty_struct *tty, char ch);
|
||||
static void stli_hangup(struct tty_struct *tty);
|
||||
|
@ -1909,7 +1909,7 @@ static void stli_flushbuffer(struct tty_struct *tty)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void stli_breakctl(struct tty_struct *tty, int state)
|
||||
static int stli_breakctl(struct tty_struct *tty, int state)
|
||||
{
|
||||
struct stlibrd *brdp;
|
||||
struct stliport *portp;
|
||||
|
@ -1917,15 +1917,16 @@ static void stli_breakctl(struct tty_struct *tty, int state)
|
|||
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
return -EINVAL;
|
||||
if (portp->brdnr >= stli_nrbrds)
|
||||
return;
|
||||
return -EINVAL;
|
||||
brdp = stli_brds[portp->brdnr];
|
||||
if (brdp == NULL)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
arg = (state == -1) ? BREAKON : BREAKOFF;
|
||||
stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -374,12 +374,13 @@ copy:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void moxa_break_ctl(struct tty_struct *tty, int state)
|
||||
static int moxa_break_ctl(struct tty_struct *tty, int state)
|
||||
{
|
||||
struct moxa_port *port = tty->driver_data;
|
||||
|
||||
moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
|
||||
Magic_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tty_operations moxa_ops = {
|
||||
|
|
|
@ -2183,7 +2183,7 @@ static void mxser_hangup(struct tty_struct *tty)
|
|||
/*
|
||||
* mxser_rs_break() --- routine which turns the break handling on or off
|
||||
*/
|
||||
static void mxser_rs_break(struct tty_struct *tty, int break_state)
|
||||
static int mxser_rs_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
@ -2196,6 +2196,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state)
|
|||
outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
|
||||
info->ioaddr + UART_LCR);
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxser_receive_chars(struct mxser_port *port, int *status)
|
||||
|
|
|
@ -2230,7 +2230,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
|
|||
* Arguments: tty pointer to tty instance data
|
||||
* break_state -1=set break condition, 0=clear
|
||||
*/
|
||||
static void mgslpc_break(struct tty_struct *tty, int break_state)
|
||||
static int mgslpc_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
@ -2240,7 +2240,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
|
|||
__FILE__,__LINE__, info->device_name, break_state);
|
||||
|
||||
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
if (break_state == -1)
|
||||
|
@ -2248,6 +2248,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
|
|||
else
|
||||
clear_reg_bits(info, CHA+DAFO, BIT6);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Service an IOCTL request
|
||||
|
|
|
@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty,
|
|||
}
|
||||
}
|
||||
|
||||
static void rp_break(struct tty_struct *tty, int break_state)
|
||||
static int rp_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct r_port *info = (struct r_port *) tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
||||
if (rocket_paranoia_check(info, "rp_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&info->slock, flags);
|
||||
if (break_state == -1)
|
||||
|
@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state)
|
|||
else
|
||||
sClrBreak(&info->channel);
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1840,7 +1840,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void sx_break(struct tty_struct *tty, int flag)
|
||||
static int sx_break(struct tty_struct *tty, int flag)
|
||||
{
|
||||
struct sx_port *port = tty->driver_data;
|
||||
int rv;
|
||||
|
@ -1857,6 +1857,7 @@ static void sx_break(struct tty_struct *tty, int flag)
|
|||
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
|
||||
unlock_kernel();
|
||||
func_exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
|
||||
|
|
|
@ -2897,9 +2897,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
|
|||
*
|
||||
* Arguments: tty pointer to tty instance data
|
||||
* break_state -1=set break condition, 0=clear
|
||||
* Return Value: None
|
||||
* Return Value: error code
|
||||
*/
|
||||
static void mgsl_break(struct tty_struct *tty, int break_state)
|
||||
static int mgsl_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
@ -2909,7 +2909,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
|
|||
__FILE__,__LINE__, info->device_name, break_state);
|
||||
|
||||
if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&info->irq_spinlock,flags);
|
||||
if (break_state == -1)
|
||||
|
@ -2917,6 +2917,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
|
|||
else
|
||||
usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
|
||||
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
||||
return 0;
|
||||
|
||||
} /* end of mgsl_break() */
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
|
|||
static int chars_in_buffer(struct tty_struct *tty);
|
||||
static void throttle(struct tty_struct * tty);
|
||||
static void unthrottle(struct tty_struct * tty);
|
||||
static void set_break(struct tty_struct *tty, int break_state);
|
||||
static int set_break(struct tty_struct *tty, int break_state);
|
||||
|
||||
/*
|
||||
* generic HDLC support and callbacks
|
||||
|
@ -513,7 +513,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
|
|||
static int tiocmget(struct tty_struct *tty, struct file *file);
|
||||
static int tiocmset(struct tty_struct *tty, struct file *file,
|
||||
unsigned int set, unsigned int clear);
|
||||
static void set_break(struct tty_struct *tty, int break_state);
|
||||
static int set_break(struct tty_struct *tty, int break_state);
|
||||
static int get_interface(struct slgt_info *info, int __user *if_mode);
|
||||
static int set_interface(struct slgt_info *info, int if_mode);
|
||||
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
|
||||
|
@ -1452,14 +1452,14 @@ static void unthrottle(struct tty_struct * tty)
|
|||
* set or clear transmit break condition
|
||||
* break_state -1=set break condition, 0=clear
|
||||
*/
|
||||
static void set_break(struct tty_struct *tty, int break_state)
|
||||
static int set_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct slgt_info *info = tty->driver_data;
|
||||
unsigned short value;
|
||||
unsigned long flags;
|
||||
|
||||
if (sanity_check(info, tty->name, "set_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
|
||||
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
|
@ -1470,6 +1470,7 @@ static void set_break(struct tty_struct *tty, int break_state)
|
|||
value &= ~BIT6;
|
||||
wr_reg16(info, TCR, value);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SYNCLINK_GENERIC_HDLC
|
||||
|
|
|
@ -527,7 +527,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
|
|||
static int chars_in_buffer(struct tty_struct *tty);
|
||||
static void throttle(struct tty_struct * tty);
|
||||
static void unthrottle(struct tty_struct * tty);
|
||||
static void set_break(struct tty_struct *tty, int break_state);
|
||||
static int set_break(struct tty_struct *tty, int break_state);
|
||||
|
||||
#if SYNCLINK_GENERIC_HDLC
|
||||
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
|
||||
|
@ -552,7 +552,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
|
|||
static int tiocmget(struct tty_struct *tty, struct file *file);
|
||||
static int tiocmset(struct tty_struct *tty, struct file *file,
|
||||
unsigned int set, unsigned int clear);
|
||||
static void set_break(struct tty_struct *tty, int break_state);
|
||||
static int set_break(struct tty_struct *tty, int break_state);
|
||||
|
||||
static void add_device(SLMP_INFO *info);
|
||||
static void device_init(int adapter_num, struct pci_dev *pdev);
|
||||
|
@ -1587,7 +1587,7 @@ static void unthrottle(struct tty_struct * tty)
|
|||
/* set or clear transmit break condition
|
||||
* break_state -1=set break condition, 0=clear
|
||||
*/
|
||||
static void set_break(struct tty_struct *tty, int break_state)
|
||||
static int set_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
unsigned char RegValue;
|
||||
SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
|
||||
|
@ -1598,7 +1598,7 @@ static void set_break(struct tty_struct *tty, int break_state)
|
|||
__FILE__,__LINE__, info->device_name, break_state);
|
||||
|
||||
if (sanity_check(info, tty->name, "set_break"))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&info->lock,flags);
|
||||
RegValue = read_reg(info, CTL);
|
||||
|
@ -1608,6 +1608,7 @@ static void set_break(struct tty_struct *tty, int break_state)
|
|||
RegValue &= ~BIT3;
|
||||
write_reg(info, CTL, RegValue);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SYNCLINK_GENERIC_HDLC
|
||||
|
|
|
@ -2849,16 +2849,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
|
|||
|
||||
static int send_break(struct tty_struct *tty, unsigned int duration)
|
||||
{
|
||||
if (tty_write_lock(tty, 0) < 0)
|
||||
return -EINTR;
|
||||
tty->ops->break_ctl(tty, -1);
|
||||
if (!signal_pending(current))
|
||||
msleep_interruptible(duration);
|
||||
tty->ops->break_ctl(tty, 0);
|
||||
tty_write_unlock(tty);
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
return 0;
|
||||
int retval;
|
||||
|
||||
if (tty->ops->break_ctl == NULL)
|
||||
return 0;
|
||||
|
||||
if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
|
||||
retval = tty->ops->break_ctl(tty, duration);
|
||||
else {
|
||||
/* Do the work ourselves */
|
||||
if (tty_write_lock(tty, 0) < 0)
|
||||
return -EINTR;
|
||||
retval = tty->ops->break_ctl(tty, -1);
|
||||
if (retval)
|
||||
goto out;
|
||||
if (!signal_pending(current))
|
||||
msleep_interruptible(duration);
|
||||
retval = tty->ops->break_ctl(tty, 0);
|
||||
out:
|
||||
tty_write_unlock(tty);
|
||||
if (signal_pending(current))
|
||||
retval = -EINTR;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2949,36 +2962,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
tty->driver->subtype == PTY_TYPE_MASTER)
|
||||
real_tty = tty->link;
|
||||
|
||||
/*
|
||||
* Break handling by driver
|
||||
*/
|
||||
|
||||
retval = -EINVAL;
|
||||
|
||||
if (!tty->ops->break_ctl) {
|
||||
switch (cmd) {
|
||||
case TIOCSBRK:
|
||||
case TIOCCBRK:
|
||||
if (tty->ops->ioctl)
|
||||
retval = tty->ops->ioctl(tty, file, cmd, arg);
|
||||
if (retval != -EINVAL && retval != -ENOIOCTLCMD)
|
||||
printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
|
||||
return retval;
|
||||
|
||||
/* These two ioctl's always return success; even if */
|
||||
/* the driver doesn't support them. */
|
||||
case TCSBRK:
|
||||
case TCSBRKP:
|
||||
if (!tty->ops->ioctl)
|
||||
return 0;
|
||||
retval = tty->ops->ioctl(tty, file, cmd, arg);
|
||||
if (retval != -EINVAL && retval != -ENOIOCTLCMD)
|
||||
printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
|
||||
if (retval == -ENOIOCTLCMD)
|
||||
retval = 0;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Factor out some common prep work
|
||||
|
@ -3000,6 +2983,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now do the stuff.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case TIOCSTI:
|
||||
return tiocsti(tty, p);
|
||||
|
@ -3043,12 +3029,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
*/
|
||||
case TIOCSBRK: /* Turn break on, unconditionally */
|
||||
if (tty->ops->break_ctl)
|
||||
tty->ops->break_ctl(tty, -1);
|
||||
return tty->ops->break_ctl(tty, -1);
|
||||
return 0;
|
||||
|
||||
case TIOCCBRK: /* Turn break off, unconditionally */
|
||||
if (tty->ops->break_ctl)
|
||||
tty->ops->break_ctl(tty, 0);
|
||||
return tty->ops->break_ctl(tty, 0);
|
||||
return 0;
|
||||
case TCSBRK: /* SVID version: non-zero arg --> no break */
|
||||
/* non-zero arg means wait for all output data
|
||||
|
|
|
@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data);
|
|||
static irqreturn_t scc_stat_int(int irq, void *data);
|
||||
static irqreturn_t scc_spcond_int(int irq, void *data);
|
||||
static void scc_setsignals(struct scc_port *port, int dtr, int rts);
|
||||
static void scc_break_ctl(struct tty_struct *tty, int break_state);
|
||||
static int scc_break_ctl(struct tty_struct *tty, int break_state);
|
||||
|
||||
static struct tty_driver *scc_driver;
|
||||
|
||||
|
@ -942,7 +942,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file,
|
|||
}
|
||||
|
||||
|
||||
static void scc_break_ctl(struct tty_struct *tty, int break_state)
|
||||
static int scc_break_ctl(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct scc_port *port = (struct scc_port *)tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
@ -952,6 +952,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state)
|
|||
SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
|
||||
break_state ? TCR_SEND_BREAK : 0);
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1302,11 +1302,12 @@ static void capinc_tty_hangup(struct tty_struct *tty)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
|
||||
static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
|
||||
{
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void capinc_tty_flush_buffer(struct tty_struct *tty)
|
||||
|
|
|
@ -934,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void uart_break_ctl(struct tty_struct *tty, int break_state)
|
||||
static int uart_break_ctl(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct uart_state *state = tty->driver_data;
|
||||
struct uart_port *port = state->port;
|
||||
|
@ -945,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
|
|||
port->ops->break_ctl(port, break_state);
|
||||
|
||||
mutex_unlock(&state->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uart_do_autoconfig(struct uart_state *state)
|
||||
|
|
|
@ -732,13 +732,16 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
|
|||
tasklet_schedule(&acm->urb_task);
|
||||
}
|
||||
|
||||
static void acm_tty_break_ctl(struct tty_struct *tty, int state)
|
||||
static int acm_tty_break_ctl(struct tty_struct *tty, int state)
|
||||
{
|
||||
struct acm *acm = tty->driver_data;
|
||||
int retval;
|
||||
if (!ACM_READY(acm))
|
||||
return;
|
||||
if (acm_send_break(acm, state ? 0xffff : 0))
|
||||
return -EINVAL;
|
||||
retval = acm_send_break(acm, state ? 0xffff : 0);
|
||||
if (retval < 0)
|
||||
dbg("send break failed");
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
|
||||
|
|
|
@ -395,7 +395,7 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
|
|||
tty_termios_copy_hw(tty->termios, old);
|
||||
}
|
||||
|
||||
static void serial_break(struct tty_struct *tty, int break_state)
|
||||
static int serial_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
|
||||
|
@ -409,6 +409,7 @@ static void serial_break(struct tty_struct *tty, int break_state)
|
|||
port->serial->type->break_ctl(tty, break_state);
|
||||
unlock_kernel();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_read_proc(char *page, char **start, off_t off, int count,
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
*
|
||||
* Optional:
|
||||
*
|
||||
* void (*break_ctl)(struct tty_stuct *tty, int state);
|
||||
* int (*break_ctl)(struct tty_stuct *tty, int state);
|
||||
*
|
||||
* This optional routine requests the tty driver to turn on or
|
||||
* off BREAK status on the RS-232 port. If state is -1,
|
||||
|
@ -146,6 +146,10 @@
|
|||
* handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
|
||||
* TIOCCBRK.
|
||||
*
|
||||
* If the driver sets TTY_DRIVER_HARDWARE_BREAK then the interface
|
||||
* will also be called with actual times and the hardware is expected
|
||||
* to do the delay work itself. 0 and -1 are still used for on/off.
|
||||
*
|
||||
* Optional: Required for TCSBRK/BRKP/etc handling.
|
||||
*
|
||||
* void (*wait_until_sent)(struct tty_struct *tty, int timeout);
|
||||
|
@ -192,7 +196,7 @@ struct tty_operations {
|
|||
void (*stop)(struct tty_struct *tty);
|
||||
void (*start)(struct tty_struct *tty);
|
||||
void (*hangup)(struct tty_struct *tty);
|
||||
void (*break_ctl)(struct tty_struct *tty, int state);
|
||||
int (*break_ctl)(struct tty_struct *tty, int state);
|
||||
void (*flush_buffer)(struct tty_struct *tty);
|
||||
void (*set_ldisc)(struct tty_struct *tty);
|
||||
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
|
||||
|
@ -285,12 +289,18 @@ extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
|
|||
* TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
|
||||
* use dynamic memory keyed through the devpts filesystem. This
|
||||
* is only applicable to the pty driver.
|
||||
*
|
||||
* TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass
|
||||
* the requested timeout to the caller instead of using a simple
|
||||
* on/off interface.
|
||||
*
|
||||
*/
|
||||
#define TTY_DRIVER_INSTALLED 0x0001
|
||||
#define TTY_DRIVER_RESET_TERMIOS 0x0002
|
||||
#define TTY_DRIVER_REAL_RAW 0x0004
|
||||
#define TTY_DRIVER_DYNAMIC_DEV 0x0008
|
||||
#define TTY_DRIVER_DEVPTS_MEM 0x0010
|
||||
#define TTY_DRIVER_HARDWARE_BREAK 0x0020
|
||||
|
||||
/* tty driver types */
|
||||
#define TTY_DRIVER_TYPE_SYSTEM 0x0001
|
||||
|
|
Загрузка…
Ссылка в новой задаче