@@ -2040,6 +2040,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
struct ftdi_private *priv, unsigned char *buf, int len)
{
unsigned char status;
+ bool brkint = false;
int i;
char flag;
@@ -2091,13 +2092,17 @@ static int ftdi_process_packet(struct usb_serial_port *port,
*/
flag = TTY_NORMAL;
if (buf[1] & FTDI_RS_ERR_MASK) {
- /* Break takes precedence over parity, which takes precedence
- * over framing errors */
- if (buf[1] & FTDI_RS_BI) {
- flag = TTY_BREAK;
+ /*
+ * Break takes precedence over parity, which takes precedence
+ * over framing errors. Note that break is only associated
+ * with the last character in the buffer and only when it's a
+ * NUL.
+ */
+ if (buf[1] & FTDI_RS_BI && buf[len - 1] == '\0') {
port->icount.brk++;
- usb_serial_handle_break(port);
- } else if (buf[1] & FTDI_RS_PE) {
+ brkint = true;
+ }
+ if (buf[1] & FTDI_RS_PE) {
flag = TTY_PARITY;
port->icount.parity++;
} else if (buf[1] & FTDI_RS_FE) {
@@ -2113,8 +2118,13 @@ static int ftdi_process_packet(struct usb_serial_port *port,
port->icount.rx += len - 2;
- if (port->port.console && port->sysrq) {
+ if (brkint || (port->port.console && port->sysrq)) {
for (i = 2; i < len; i++) {
+ if (brkint && i == len - 1) {
+ if (usb_serial_handle_break(port))
+ return len - 3;
+ flag = TTY_BREAK;
+ }
if (usb_serial_handle_sysrq_char(port, buf[i]))
continue;
tty_insert_flip_char(&port->port, buf[i], flag);