* [PATCH 2.6.36-rc3] USB: serial: handle Data Carrier Detect changes @ 2010-12-17 15:34 Libor Pechacek 2011-01-04 13:53 ` Alan Cox 0 siblings, 1 reply; 4+ messages in thread From: Libor Pechacek @ 2010-12-17 15:34 UTC (permalink / raw) To: Alan Cox, Greg Kroah-Hartman Cc: Peter Berger, Al Borchers, linux-usb, linux-kernel Alan's commit 335f8514f200e63d689113d29cb7253a5c282967 introduced .carrier_raised function in several drivers. That also means tty_port_block_til_ready can now suspend the process trying to open the serial port when Carrier Detect is low and put it into tty_port.open_wait queue. We need to wake up the process when the Carrier Detect goes high. Signed-off-by: Libor Pechacek <lpechacek@suse.cz> Cc: Greg Kroah-Hartman <gregkh@suse.de> Cc: Peter Berger <pberger@brimson.com> Cc: Al Borchers <alborchers@steinerpoint.com> --- Hi Alan, This is an amendment of your patch referenced above. Please review and comment on the changes. @Greg: There are two drivers left to be fixed - drivers/usb/serial/cp210x.c and drivers/usb/serial/keyspan_pda.c. cp210x device does not seem to have an interrupt endpoint to report the changes so a polling thread seems to be needed to detect DCD changes. I can implement the polling for cp210x if you don't have a better idea. The keyspan_pda can report the changes asynchronously, but I haven't found the message format description anywhere. Any idea how that driver can be fixed besides dropping .carrier_raised? drivers/usb/serial/ch341.c | 4 ++++ drivers/usb/serial/digi_acceleport.c | 17 +++++++++++------ drivers/usb/serial/generic.c | 20 ++++++++++++++++++++ drivers/usb/serial/pl2303.c | 4 ++++ drivers/usb/serial/spcp8x5.c | 5 +++++ include/linux/usb/serial.h | 2 ++ 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 63f7cc4..caa1f8d 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -486,12 +486,16 @@ static void ch341_read_int_callback(struct urb *urb) if (actual_length >= 4) { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; + u8 prev_line_status = priv->line_status; spin_lock_irqsave(&priv->lock, flags); priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; if ((data[1] & CH341_MULT_STAT)) priv->multi_status_change = 1; spin_unlock_irqrestore(&priv->lock, flags); + if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) + usb_serial_handle_dcd_change(port, + priv->line_status & CH341_BIT_DCD); wake_up_interruptible(&priv->delta_msr_wait); } diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b92070c..396c2c5 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1738,9 +1738,9 @@ static int digi_read_oob_callback(struct urb *urb) struct usb_serial *serial = port->serial; struct tty_struct *tty; struct digi_port *priv = usb_get_serial_port_data(port); - int opcode, line, status, val; + int opcode, line, status, val, new_dcd_val; int i; - unsigned int rts; + unsigned int rts, dcd; dbg("digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num, urb->actual_length); @@ -1794,10 +1794,15 @@ static int digi_read_oob_callback(struct urb *urb) priv->dp_modem_signals |= TIOCM_RI; else priv->dp_modem_signals &= ~TIOCM_RI; - if (val & DIGI_READ_INPUT_SIGNALS_DCD) - priv->dp_modem_signals |= TIOCM_CD; - else - priv->dp_modem_signals &= ~TIOCM_CD; + + dcd = priv->dp_modem_signals & TIOCM_CD; + new_dcd_val = val & DIGI_READ_INPUT_SIGNALS_DCD; + if (!!new_dcd_val != !!dcd) { + priv->dp_modem_signals = new_dcd_val ? + priv->dp_modem_signals | TIOCM_CD : + priv->dp_modem_signals & ~TIOCM_CD; + usb_serial_handle_dcd_change(port, dcd); + } wake_up_interruptible(&priv->dp_modem_change_wait); spin_unlock(&priv->dp_port_lock); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e6833e2..a877767 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -479,6 +479,26 @@ int usb_serial_handle_break(struct usb_serial_port *port) } EXPORT_SYMBOL_GPL(usb_serial_handle_break); +/** + * usb_serial_handle_dcd_change - handle a change of carrier detect state + * @port: usb_serial_port structure for the open port + * @status: new carrier detect status, nonzero if active + */ +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + unsigned int status) +{ + struct tty_port *port = &usb_port->port; + struct tty_struct *tty = port->tty; + + dbg("%s - port %d, status %d", __func__, usb_port->number, status); + + if (status) + wake_up_interruptible(&port->open_wait); + else if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); +} +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); + int usb_serial_generic_resume(struct usb_serial *serial) { struct usb_serial_port *port; diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 8ae4c6c..9b4f21b 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -680,6 +680,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port, unsigned long flags; u8 status_idx = UART_STATE; u8 length = UART_STATE + 1; + u8 prev_line_status = priv->line_status; u16 idv, idp; idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); @@ -705,6 +706,9 @@ static void pl2303_update_line_status(struct usb_serial_port *port, spin_unlock_irqrestore(&priv->lock, flags); if (priv->line_status & UART_BREAK_ERROR) usb_serial_handle_break(port); + if ((priv->line_status ^ prev_line_status) & UART_DCD) + usb_serial_handle_dcd_change(port, + priv->line_status & UART_DCD); wake_up_interruptible(&priv->delta_msr_wait); } diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 765aa98..42bdb6b 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -452,6 +452,7 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) struct spcp8x5_private *priv = usb_get_serial_port_data(port); int ret; unsigned long flags; + u8 prev_line_status = priv->line_status; u8 status = 0x30; /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */ @@ -479,6 +480,10 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) priv->line_status = status & 0xf0 ; spin_unlock_irqrestore(&priv->lock, flags); + if ((priv->line_status ^ prev_line_status) & MSR_STATUS_LINE_DCD) + usb_serial_handle_dcd_change(port, + priv->line_status & MSR_STATUS_LINE_DCD); + port->port.drain_delay = 256; return usb_serial_generic_open(tty, port); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 16d682f..7fe31a9 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -347,6 +347,8 @@ extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch); extern int usb_serial_handle_break(struct usb_serial_port *port); +extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + unsigned int status); extern int usb_serial_bus_register(struct usb_serial_driver *device); -- 1.6.0.2 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2.6.36-rc3] USB: serial: handle Data Carrier Detect changes 2010-12-17 15:34 [PATCH 2.6.36-rc3] USB: serial: handle Data Carrier Detect changes Libor Pechacek @ 2011-01-04 13:53 ` Alan Cox 2011-01-14 11:53 ` Libor Pechacek 0 siblings, 1 reply; 4+ messages in thread From: Alan Cox @ 2011-01-04 13:53 UTC (permalink / raw) To: Libor Pechacek Cc: Greg Kroah-Hartman, Peter Berger, Al Borchers, linux-usb, linux-kernel On Fri, 17 Dec 2010 16:34:23 +0100 Libor Pechacek <lpechacek@suse.cz> wrote: > Alan's commit 335f8514f200e63d689113d29cb7253a5c282967 introduced > .carrier_raised function in several drivers. That also means > tty_port_block_til_ready can now suspend the process trying to open the serial > port when Carrier Detect is low and put it into tty_port.open_wait queue. We > need to wake up the process when the Carrier Detect goes high. (catching up after Christmas break) > @Greg: There are two drivers left to be fixed - drivers/usb/serial/cp210x.c and > drivers/usb/serial/keyspan_pda.c. cp210x device does not seem to have an > interrupt endpoint to report the changes so a polling thread seems to be needed > to detect DCD changes. I can implement the polling for cp210x if you don't > have a better idea. It might be worth making tty_port_open know how to handle such devices as I'd bet there will be others out there somewhere. Perhaps add a dcd_poll field that holds the poll time in ms then in the tty_port_block_til_ready code change from tty_unlock(); schedule(); tty_lock(); to tty_unlock(); if (port->dcd_poll) schedule_timeout(port->dcd_poll); else schedule(); tty_lock ?? > The keyspan_pda can report the changes asynchronously, but I haven't found the > message format description anywhere. Any idea how that driver can be fixed > besides dropping .carrier_raised? I don't - Greg may have info or of course you could cheat and wake the queue whenever you see an unknown message format, then ask the device 8) > +/** > + * usb_serial_handle_dcd_change - handle a change of carrier detect state > + * @port: usb_serial_port structure for the open port > + * @status: new carrier detect status, nonzero if active > + */ > +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, > + unsigned int status) > +{ > + struct tty_port *port = &usb_port->port; > + struct tty_struct *tty = port->tty; > + > + dbg("%s - port %d, status %d", __func__, usb_port->number, status); > + > + if (status) > + wake_up_interruptible(&port->open_wait); > + else if (tty && !C_CLOCAL(tty)) > + tty_hangup(tty); > +} > +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); This looks good except that port->tty isn't necessarily a safe de-reference so it would be better to pass the tty into the function so the caller must think about that problem (and all the calling points appear to have a tty reference held ready) Looks good Alan ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2.6.36-rc3] USB: serial: handle Data Carrier Detect changes 2011-01-04 13:53 ` Alan Cox @ 2011-01-14 11:53 ` Libor Pechacek 2011-01-14 13:30 ` [PATCH 2.6.37 take 2] " Libor Pechacek 0 siblings, 1 reply; 4+ messages in thread From: Libor Pechacek @ 2011-01-14 11:53 UTC (permalink / raw) To: Alan Cox Cc: Greg Kroah-Hartman, Peter Berger, Al Borchers, linux-usb, linux-kernel On Tue 04-01-11 13:53:13, Alan Cox wrote: > On Fri, 17 Dec 2010 16:34:23 +0100 Libor Pechacek <lpechacek@suse.cz> wrote: > > @Greg: There are two drivers left to be fixed - drivers/usb/serial/cp210x.c and > > drivers/usb/serial/keyspan_pda.c. cp210x device does not seem to have an > > interrupt endpoint to report the changes so a polling thread seems to be needed > > to detect DCD changes. I can implement the polling for cp210x if you don't > > have a better idea. > > It might be worth making tty_port_open know how to handle such devices as > I'd bet there will be others out there somewhere. Perhaps add a dcd_poll > field that holds the poll time in ms then in the tty_port_block_til_ready > code change from > > tty_unlock(); > schedule(); > tty_lock(); > > to > > tty_unlock(); > if (port->dcd_poll) > schedule_timeout(port->dcd_poll); > else > schedule(); > tty_lock I fell in love with the idea and implemented it. Then between implementation and the first testing I realized that we also need to handle the complementary case - DCD drop - where we indicate hangup. At the moment I don't see an elegant solution to sense DCD drop. For some devices reading the status lines also involves an extra USB control transaction that should be done quite often. That looks too clumsy to me and I'd like to avoid that if possible. > > +/** > > + * usb_serial_handle_dcd_change - handle a change of carrier detect state > > + * @port: usb_serial_port structure for the open port > > + * @status: new carrier detect status, nonzero if active > > + */ > > +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, > > + unsigned int status) > > +{ > > + struct tty_port *port = &usb_port->port; > > + struct tty_struct *tty = port->tty; > > + > > + dbg("%s - port %d, status %d", __func__, usb_port->number, status); > > + > > + if (status) > > + wake_up_interruptible(&port->open_wait); > > + else if (tty && !C_CLOCAL(tty)) > > + tty_hangup(tty); > > +} > > +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); > > This looks good except that port->tty isn't necessarily a safe > de-reference so it would be better to pass the tty into the function so > the caller must think about that problem (and all the calling points > appear to have a tty reference held ready) Thanks for the hint. I like the separation and added the parameter. Updated patch will follow. Libor -- Libor Pechacek SUSE L3 Team, Prague ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2.6.37 take 2] USB: serial: handle Data Carrier Detect changes 2011-01-14 11:53 ` Libor Pechacek @ 2011-01-14 13:30 ` Libor Pechacek 0 siblings, 0 replies; 4+ messages in thread From: Libor Pechacek @ 2011-01-14 13:30 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Alan Cox, Peter Berger, Al Borchers, linux-usb, linux-kernel Alan's commit 335f8514f200e63d689113d29cb7253a5c282967 introduced .carrier_raised function in several drivers. That also means tty_port_block_til_ready can now suspend the process trying to open the serial port when Carrier Detect is low and put it into tty_port.open_wait queue. We need to wake up the process when Carrier Detect goes high and trigger TTY hangup when CD goes low. Some of the devices do not report modem status line changes, or at least we don't understand the status message, so for those we remove .carrier_raised again. Signed-off-by: Libor Pechacek <lpechacek@suse.cz> --- drivers/usb/serial/ch341.c | 10 ++++++++++ drivers/usb/serial/cp210x.c | 13 +------------ drivers/usb/serial/digi_acceleport.c | 10 ---------- drivers/usb/serial/generic.c | 20 ++++++++++++++++++++ drivers/usb/serial/keyspan_pda.c | 17 ----------------- drivers/usb/serial/pl2303.c | 11 +++++++++++ drivers/usb/serial/spcp8x5.c | 6 +++++- include/linux/usb/serial.h | 3 +++ 8 files changed, 50 insertions(+), 40 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 63f7cc4..7b8815d 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -486,12 +486,22 @@ static void ch341_read_int_callback(struct urb *urb) if (actual_length >= 4) { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; + u8 prev_line_status = priv->line_status; spin_lock_irqsave(&priv->lock, flags); priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; if ((data[1] & CH341_MULT_STAT)) priv->multi_status_change = 1; spin_unlock_irqrestore(&priv->lock, flags); + + if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & CH341_BIT_DCD); + tty_kref_put(tty); + } + wake_up_interruptible(&priv->delta_msr_wait); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8d7731d..d82cd7a 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -49,7 +49,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); -static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; @@ -165,8 +164,7 @@ static struct usb_serial_driver cp210x_device = { .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, - .dtr_rts = cp210x_dtr_rts, - .carrier_raised = cp210x_carrier_raised + .dtr_rts = cp210x_dtr_rts }; /* Config request types */ @@ -765,15 +763,6 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) return result; } -static int cp210x_carrier_raised(struct usb_serial_port *p) -{ - unsigned int control; - cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1); - if (control & CONTROL_DCD) - return 1; - return 0; -} - static void cp210x_break_ctl (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b92070c..666e5a6 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -455,7 +455,6 @@ static int digi_write_room(struct tty_struct *tty); static int digi_chars_in_buffer(struct tty_struct *tty); static int digi_open(struct tty_struct *tty, struct usb_serial_port *port); static void digi_close(struct usb_serial_port *port); -static int digi_carrier_raised(struct usb_serial_port *port); static void digi_dtr_rts(struct usb_serial_port *port, int on); static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); @@ -511,7 +510,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .open = digi_open, .close = digi_close, .dtr_rts = digi_dtr_rts, - .carrier_raised = digi_carrier_raised, .write = digi_write, .write_room = digi_write_room, .write_bulk_callback = digi_write_bulk_callback, @@ -1339,14 +1337,6 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on) digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1); } -static int digi_carrier_raised(struct usb_serial_port *port) -{ - struct digi_port *priv = usb_get_serial_port_data(port); - if (priv->dp_modem_signals & TIOCM_CD) - return 1; - return 0; -} - static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) { int ret; diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e6833e2..e4db5ad 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -479,6 +479,26 @@ int usb_serial_handle_break(struct usb_serial_port *port) } EXPORT_SYMBOL_GPL(usb_serial_handle_break); +/** + * usb_serial_handle_dcd_change - handle a change of carrier detect state + * @port: usb_serial_port structure for the open port + * @tty: tty_struct structure for the port + * @status: new carrier detect status, nonzero if active + */ +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, unsigned int status) +{ + struct tty_port *port = &usb_port->port; + + dbg("%s - port %d, status %d", __func__, usb_port->number, status); + + if (status) + wake_up_interruptible(&port->open_wait); + else if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); +} +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); + int usb_serial_generic_resume(struct usb_serial *serial) { struct usb_serial_port *port; diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index a10dd56..554a869 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -679,22 +679,6 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) } } -static int keyspan_pda_carrier_raised(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - unsigned char modembits; - - /* If we can read the modem status and the DCD is low then - carrier is not raised yet */ - if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) { - if (!(modembits & (1>>6))) - return 0; - } - /* Carrier raised, or we failed (eg disconnected) so - progress accordingly */ - return 1; -} - static int keyspan_pda_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -881,7 +865,6 @@ static struct usb_serial_driver keyspan_pda_device = { .id_table = id_table_std, .num_ports = 1, .dtr_rts = keyspan_pda_dtr_rts, - .carrier_raised = keyspan_pda_carrier_raised, .open = keyspan_pda_open, .close = keyspan_pda_close, .write = keyspan_pda_write, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 8ae4c6c..e3a9e2e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -677,9 +677,11 @@ static void pl2303_update_line_status(struct usb_serial_port *port, { struct pl2303_private *priv = usb_get_serial_port_data(port); + struct tty_struct *tty; unsigned long flags; u8 status_idx = UART_STATE; u8 length = UART_STATE + 1; + u8 prev_line_status; u16 idv, idp; idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); @@ -701,11 +703,20 @@ static void pl2303_update_line_status(struct usb_serial_port *port, /* Save off the uart status for others to look at */ spin_lock_irqsave(&priv->lock, flags); + prev_line_status = priv->line_status; priv->line_status = data[status_idx]; spin_unlock_irqrestore(&priv->lock, flags); if (priv->line_status & UART_BREAK_ERROR) usb_serial_handle_break(port); wake_up_interruptible(&priv->delta_msr_wait); + + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + if ((priv->line_status ^ prev_line_status) & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & UART_DCD); + tty_kref_put(tty); } static void pl2303_read_int_callback(struct urb *urb) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 765aa98..e212eb6 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -133,7 +133,7 @@ struct spcp8x5_usb_ctrl_arg { /* how come ??? */ #define UART_STATE 0x08 -#define UART_STATE_TRANSIENT_MASK 0x74 +#define UART_STATE_TRANSIENT_MASK 0x75 #define UART_DCD 0x01 #define UART_DSR 0x02 #define UART_BREAK_ERROR 0x04 @@ -525,6 +525,10 @@ static void spcp8x5_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + if (status & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & MSR_STATUS_LINE_DCD); } tty_insert_flip_string_fixed_flag(tty, data, tty_flag, diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 16d682f..c904913 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -347,6 +347,9 @@ extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch); extern int usb_serial_handle_break(struct usb_serial_port *port); +extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, + unsigned int status); extern int usb_serial_bus_register(struct usb_serial_driver *device); -- 1.6.0.2 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-01-14 13:30 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-12-17 15:34 [PATCH 2.6.36-rc3] USB: serial: handle Data Carrier Detect changes Libor Pechacek 2011-01-04 13:53 ` Alan Cox 2011-01-14 11:53 ` Libor Pechacek 2011-01-14 13:30 ` [PATCH 2.6.37 take 2] " Libor Pechacek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox