#382 win32file.GetCommState incorrect handling of DCB

closed-rejected
nobody
win32 (141)
5
2009-01-30
2008-09-27
No

I believe I have found a bug in win32file.GetCommState and win32file.SetCommState. I have seen it in Python 2.4 and Python 2.5, running an older version of pywin32, as well as the current (212) version. It exists in Win2k and WinXP. I use pyserial 2.4 as a wrapper for the comm ports, though I believe the problem is in win32file.

The problem manifests itself when I try to open a com port in Python after having that port open in Procomm (an old, no longer supported terminal program). I have only seen it happen with a particular brand of USB to serial converters (Edgeport, made by Digi). In these conditions the python script will hang at the win32file.SetCommState() command, usually timing out after 5-30 seconds, and quitting with no error message.

After having done some probing I think I basically understand the problem, and have a workaround, but I lack the know-how to fix it where it should be fixed, in win32file. When Procomm opens the port, it sets XoffLim to 16128 and the XonLim to 15872. When my script (actually, serialwin32.py from pyserial) tries to open the port it first reads the DCB with GetCommState(), changes baud rate, etc in the local PyDCB object, and then tries to reconfigure the port with SetCommState().

From what I can tell, SetCommState won't accept a value for XoffLim or XonLim >4096. For example, if I try to execute the following:
DCB.XoffLim = 16128
SetCommState(porthandle,DCB)

I get an exception: (87, 'SetCommState', 'The parameter is incorrect.')

However, if GetCommState gets a DCB which has XoffLim = 16128, and then that DCB is passed to SetCommState, the script hangs for several seconds before exiting without opening the port and with no error message. For example, after having opened and closed the port in Procomm:

>>> DCB = GetCommState(porthandle)
>>> DCB.XoffLim
16128L
>>> SetCommState(porthandle,DCB)
(...... hangs here for several seconds ......)

If I set XoffLim and XonLim to values from 0-4096 before calling SetCommState, then it works fine. For example, after having opened and closed the port in Procomm:

>>> DCB = GetCommState(porthandle)
>>> DCB.XoffLim = 128
>>> DCB.XonLim = 512
>>> SetCommState(porthandle,DCB)
>>>
This works fine, and I can go on to open the port normally. I have incorporated this fix into serialwin32.py which is working for me now, but it's not an elegant solution. I am still baffled by why
SetCommState limits Xon/XoffLim to 4096, and by what GetCommState does to the PyDCB to make it cause SetCommState to fail so dramatically. I also don't understand why I only see this problem with the Edgeport USB converters, and not with several other USB converters or hardware serial ports. Maybe someone with a more intimate understanding of Python and Win32 can come up with some answers.

Thank you
-Alan Gardner
Woods Hole Oceanographic Institution
Woods Hole, MA 02543

Discussion

  • Roger Upole

    Roger Upole - 2008-09-27

    I don't see any problem with the way the DCB is passed to/from
    SetCommState and GetCommState. The XonLim and XoffLim members
    consistently have the correct value.

    If I recall from looking at pyserial a while back, it sets the
    buffer sizes to 4096. Have you tried increasing them in the
    call to SetupComm ?

     
  • Alan Gardner

    Alan Gardner - 2008-09-30

    OK, since I realize this may be a difficult problem to recreate I have annotated some screen captures from the interpreter. In the process I realized that the XonLim and XoffLim are obviously going to be limited by the buffer size, and yes, pyserial does set the buffer to 4096. OK, so now I have another workaround, increasing the buffer size so that the XonLim and XoffLim values are no longer to large. But I still think that there is an underlying bug. When a port is opened with CreateFile it appears to assign a default buffer size, and this can lead to XonLim and XoffLim values which are out of range. If SetCommState then tries to set an out of range value to one of these parameters, it hangs. I have some captures from DebugView and PortMon which show Python.exe repeatedly getting and setting parameters on the serial port in a nearly endless loop. I can upload these if it would be helpful, but they are moderately large and arcane. For now I will upload the annotated screen captures showing what I see at this end.
    File Added: win32file.SetCommState_interactive.txt

     
  • Mark Hammond

    Mark Hammond - 2008-09-30

    If you think pywin32 is doing something incorrect with its DCB handling, the only real way to demonstrate that is a snippet of C code that behaves differently. Given our arg handling looks OK, we will otherwise need to assume the behaviour is just a characteristic of the windows API itself.

     
  • Roger Upole

    Roger Upole - 2008-10-01
    • status: open --> pending
     
  • Roger Upole

    Roger Upole - 2008-10-01

    The code to call SetCommState does not do any retries.
    If you're seeing multiple attempts to set the configuration
    parameters, they're probably coming from the driver itself.

    Since this problem only happens for a particular device, and
    only after a completely separate program has accessed it,
    it's most likely due to the device driver, and/or the
    state in which the other program leaves the port. I really
    don't think there's anything that can be done in win32file
    to solve it.

     
  • Alan Gardner

    Alan Gardner - 2008-10-02

    Gentlemen,
    I appreciate your time helping me work this out. I have been in contact with the vendor, and after trying several things they had started to point the finger at Python. I am feeling pretty confident now that the problem is not related to Python, and I have a reasonably good handle on what's going on. I will follow up with the vendor. Unfortunately Procomm is unsupported now, but I really don't think that it is doing anything "wrong", it just leaves the port in a state that the driver reacts badly to. I will follow up here if I learn anything more.
    Thank you.
    -Alan

     
  • Alan Gardner

    Alan Gardner - 2008-10-02
    • status: pending --> open
     
  • Mark Hammond

    Mark Hammond - 2009-01-30

    I think we agree nothing in pywin32 should change due to this.

     
  • Mark Hammond

    Mark Hammond - 2009-01-30
    • status: open --> closed-rejected
     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks