@@ -65,6 +65,8 @@ struct ftdi_private {
int flags; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts; /* saved modem control outputs */
char prev_status; /* Used for TIOCMIWAIT */
+ char prev_errs;
+ char held;
char transmit_empty; /* If transmitter is empty or not */
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
(0 for FT232/245) */
@@ -2045,6 +2047,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
int i;
char status;
char flag;
+ char errs;
char *ch;
if (len < 2) {
@@ -2086,6 +2089,21 @@ static int ftdi_process_packet(struct usb_serial_port *port,
else
priv->transmit_empty = 0;
+ if (priv->prev_errs) {
+ errs = priv->prev_errs & packet[1];
+ flag = TTY_NORMAL;
+ if ((len <= 2) && (errs & FTDI_RS_BI)) {
+ printk("BREAK\n");
+ flag = TTY_BREAK;
+ port->icount.brk++;
+ usb_serial_handle_break(port);
+ }
+ printk("%s: flag=%d data=%02x\n", __func__, flag, priv->held);
+ tty_insert_flip_char(&port->port, priv->held, flag);
+ ++port->icount.rx;
+ priv->prev_errs = 0;
+ }
+
len -= 2;
if (!len)
return 0; /* status only */
@@ -2094,18 +2112,22 @@ static int ftdi_process_packet(struct usb_serial_port *port,
* Break and error status must only be processed for packets with
* data payload to avoid over-reporting.
*/
+ errs = packet[1] & FTDI_RS_ERR_MASK;
flag = TTY_NORMAL;
- if (packet[1] & FTDI_RS_ERR_MASK) {
- /* Break takes precedence over parity, which takes precedence
- * over framing errors */
- if (packet[1] & FTDI_RS_BI) {
- flag = TTY_BREAK;
- port->icount.brk++;
- usb_serial_handle_break(port);
- } else if (packet[1] & FTDI_RS_PE) {
+ ch = packet + 2;
+ if (errs) {
+ if (errs & FTDI_RS_BI) {
+ priv->prev_errs = errs;
+ priv->held = ch[len - 1];
+ if (--len == 0)
+ return 0;
+ }
+ if (errs & FTDI_RS_PE) {
+ printk("PARITY\n");
flag = TTY_PARITY;
port->icount.parity++;
- } else if (packet[1] & FTDI_RS_FE) {
+ } else if (errs & FTDI_RS_FE) {
+ printk("FRAME\n");
flag = TTY_FRAME;
port->icount.frame++;
}
@@ -2116,8 +2138,19 @@ static int ftdi_process_packet(struct usb_serial_port *port,
}
}
+
port->icount.rx += len;
- ch = packet + 2;
+
+ {
+ char buf[128], *dst = buf, *end = &buf[128];
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ snprintf (dst, end - dst, " %02x", ch[i]);
+ dst += 3;
+ }
+ printk("%s: flag=%d data=[%s ]\n", __func__, flag, buf);
+ }
if (port->port.console && port->sysrq) {
for (i = 0; i < len; i++, ch++) {