# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.563 -> 1.564 # drivers/usb/serial/keyspan.c 1.26 -> 1.27 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/04/25 greg@kroah.com 1.564 # USB keyspan driver patch that fixes lots of different problems. # # - Modified port open, port close, and send setup() logic to fix various data and endpoint # synchronization bugs and device LED status bugs. # - Changed keyspan_write_room() to accurately return transmit buffer availability. # - Changed forwardingLength from 1 to 16 for all adapters. # -------------------------------------------- # diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c --- a/drivers/usb/serial/keyspan.c Thu Apr 25 16:26:51 2002 +++ b/drivers/usb/serial/keyspan.c Thu Apr 25 16:26:51 2002 @@ -28,6 +28,14 @@ Change History + Wed Apr 25 12:00:00 PST 2002 (Keyspan) + Started with Hugh Blemings' code dated Jan 17, 2002. All adapters + now supported (including QI and QW). Modified port open, port + close, and send setup() logic to fix various data and endpoint + synchronization bugs and device LED status bugs. Changed keyspan_ + write_room() to accurately return transmit buffer availability. + Changed forwardingLength from 1 to 16 for all adapters. + Fri Oct 12 16:45:00 EST 2001 Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV) @@ -98,7 +106,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.1.2" +#define DRIVER_VERSION "v1.1.3" #define DRIVER_AUTHOR "Hugh Blemings dev = port->serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); - } + if (port->open_count) + if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); + } return; } @@ -461,7 +470,7 @@ if (p_priv->resend_cont) { dbg ("%s - sending setup", __FUNCTION__); - keyspan_usa26_send_setup(port->serial, port, 0); + keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1); } } @@ -519,12 +528,12 @@ /* wake_up_interruptible(&p_priv->open_wait); */ } -exit: /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } +exit: } static void usa26_glocont_callback(struct urb *urb) @@ -572,9 +581,10 @@ /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); - } + if (port->open_count) + if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); + } p_priv->in_flip ^= 1; urb = p_priv->in_urbs[p_priv->in_flip]; @@ -596,7 +606,7 @@ if (p_priv->resend_cont) { dbg ("%s - sending setup", __FUNCTION__); - keyspan_usa28_send_setup(port->serial, port, 0); + keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1); } } @@ -653,12 +663,12 @@ /* wake_up_interruptible(&p_priv->open_wait); */ } -exit: /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } +exit: } static void usa28_glocont_callback(struct urb *urb) @@ -683,7 +693,7 @@ if (p_priv->resend_cont) { dbg ("%s - sending setup", __FUNCTION__); - keyspan_usa49_send_setup(serial, port, 0); + keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1); break; } } @@ -745,13 +755,13 @@ /* wake_up_interruptible(&p_priv->open_wait); */ } -exit: /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } +exit: } static void usa49_inack_callback(struct urb *urb) @@ -805,9 +815,10 @@ /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); - } + if (port->open_count) + if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); + } } /* not used, usa-49 doesn't have per-port control endpoints */ @@ -820,9 +831,27 @@ static int keyspan_write_room (struct usb_serial_port *port) { + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + int flip; + struct urb *this_urb; + dbg("%s", __FUNCTION__); - return (32); + p_priv = (struct keyspan_port_private *)(port->private); + d_details = p_priv->device_details; + + flip = p_priv->out_flip; + /* Check both endpoints to see if any are available. */ + if ((this_urb = p_priv->out_urbs[flip]) != 0) { + if (this_urb->status != -EINPROGRESS) + return (63); + flip = (flip + 1) & d_details->outdat_endp_flip; + if ((this_urb = p_priv->out_urbs[flip]) != 0) + if (this_urb->status != -EINPROGRESS) + return (63); + } + return (0); } @@ -873,7 +902,7 @@ if ((urb = p_priv->out_urbs[i]) == NULL) continue; urb->dev = serial->dev; - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); + /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ } keyspan_send_setup(port, 1); @@ -909,8 +938,12 @@ p_priv->rts_state = 0; p_priv->dtr_state = 0; - if (serial->dev) - keyspan_send_setup(port, 1); + if (serial->dev) { + keyspan_send_setup(port, 2); + /* pilot-xfer seems to work best with this delay */ + mdelay(100); + keyspan_set_termios(port, NULL); + } /*while (p_priv->outcont_urb->status == -EINPROGRESS) { dbg("%s - urb in progress", __FUNCTION__); @@ -922,7 +955,7 @@ if (serial->dev) { /* Stop reading/writing urbs */ stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); + /* stop_urb(p_priv->outcont_urb); */ for (i = 0; i < 2; i++) { stop_urb(p_priv->in_urbs[i]); stop_urb(p_priv->out_urbs[i]); @@ -1365,7 +1398,10 @@ return -1; } - p_priv->resend_cont = 1; + /* Save reset port val for resend. + Don't overwrite resend for close condition. */ + if (p_priv->resend_cont != 3) + p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { /* dbg ("%s - already writing", __FUNCTION__); */ return(-1); @@ -1414,12 +1450,26 @@ msg.ctsFlowControl = (p_priv->flow_control == flow_cts); msg.xonFlowControl = 0; msg.setFlowControl = 0xff; - - msg.forwardingLength = 1; + msg.forwardingLength = 16; msg.xonChar = 17; msg.xoffChar = 19; - if (reset_port) { + /* Opening port */ + if (reset_port == 1) { + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 1; + msg.rxForward = 0; + msg.returnStatus = 0; + msg.resetDataToggle = 0xff; + } + + /* Closing port */ + else if (reset_port == 2) { msg._txOn = 0; msg._txOff = 1; msg.txFlush = 0; @@ -1429,14 +1479,16 @@ msg.rxFlush = 1; msg.rxForward = 0; msg.returnStatus = 0; - msg.resetDataToggle = 0xff; + msg.resetDataToggle = 0; } + + /* Sending intermediate configs */ else { msg._txOn = (! p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); - msg.rxOn = 1; + msg.rxOn = 0; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; @@ -1496,7 +1548,10 @@ return -1; } - p_priv->resend_cont = 1; + /* Save reset port val for resend. + Don't overwrite resend for close condition. */ + if (p_priv->resend_cont != 3) + p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { dbg ("%s already writing", __FUNCTION__); return(-1); @@ -1522,7 +1577,7 @@ msg.rts = p_priv->rts_state; msg.dtr = p_priv->dtr_state; - msg.forwardingLength = 1; + msg.forwardingLength = 16; msg.forwardMs = 10; msg.breakThreshold = 45; msg.xonChar = 17; @@ -1530,8 +1585,22 @@ /*msg.returnStatus = 1; msg.resetDataToggle = 0xff;*/ - - if (reset_port) { + /* Opening port */ + if (reset_port == 1) { + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txForceXoff = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 1; + msg.rxForward = 0; + msg.returnStatus = 0; + msg.resetDataToggle = 0xff; + } + /* Closing port */ + else if (reset_port == 2) { msg._txOn = 0; msg._txOff = 1; msg.txFlush = 0; @@ -1542,15 +1611,16 @@ msg.rxFlush = 1; msg.rxForward = 0; msg.returnStatus = 0; - msg.resetDataToggle = 0xff; + msg.resetDataToggle = 0; } + /* Sending intermediate configs */ else { msg._txOn = (! p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txForceXoff = 0; msg.txBreak = (p_priv->break_on); - msg.rxOn = 1; + msg.rxOn = 0; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; @@ -1610,7 +1680,10 @@ return -1; } - p_priv->resend_cont = 1; + /* Save reset port val for resend. + Don't overwrite resend for close condition. */ + if (p_priv->resend_cont != 3) + p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { /* dbg ("%s - already writing", __FUNCTION__); */ return(-1); @@ -1663,11 +1736,27 @@ msg.xonFlowControl = 0; msg.setFlowControl = 0xff; - msg.forwardingLength = 1; + msg.forwardingLength = 16; msg.xonChar = 17; msg.xoffChar = 19; - if (reset_port) { + /* Opening port */ + if (reset_port == 1) { + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 1; + msg.rxForward = 0; + msg.returnStatus = 0; + msg.resetDataToggle = 0xff; + msg.enablePort = 1; + msg.disablePort = 0; + } + /* Closing port */ + else if (reset_port == 2) { msg._txOn = 0; msg._txOff = 1; msg.txFlush = 0; @@ -1677,23 +1766,23 @@ msg.rxFlush = 1; msg.rxForward = 0; msg.returnStatus = 0; - msg.resetDataToggle = 0xff; + msg.resetDataToggle = 0; msg.enablePort = 0; - msg.disablePort = 0xff; - + msg.disablePort = 1; } + /* Sending intermediate configs */ else { msg._txOn = (! p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); - msg.rxOn = 1; + msg.rxOn = 0; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; msg.returnStatus = 0; msg.resetDataToggle = 0x0; - msg.enablePort = 0xff; + msg.enablePort = 0; msg.disablePort = 0; }