WG: Re: Wine and the serial port [LONG]

Gerson Kurz Gerson.Kurz at pergamon-software.de
Wed Nov 7 07:32:34 CST 2001


Hi, I applied your patch and recompiled, but I'm still having trouble. In
what follows I've tried to describe some details. 

The first problem was this: The Comm-Port gets opened with overlapped I/O.
However, for WaitCommEvent() we do not specify an overlapped structure. This
works fine on NT4 / W2K, but is contrary to the documentation, which
specifys that you need to supply an overlapped structure if you do. Quote:
"If hFile was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter
must not be NULL. It must point to a valid OVERLAPPED structure. If hFile
was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function
can incorrectly report that the operation is complete. " However, this has
worked for years in "real life", and is in use by all of our customers
(several thousand of them). So while its clearly our fault, maybe its a
slight incompatibility to the NT-series. 

OK, I fixed the code and now provide (and properly wait for) an overlapped
IO structure for WaitCommEvent. The code goes on, but now has different
problems. 

Here is what our code does:

- We have a "ListenerThread" that does the following, in pseudocode:

	if( WaitCommEvent(&eventmask) )
		if(eventmask & EV_RXCHAR )
			ReadFile()

(of course, now with WaitForSingleObject() handling. Code excerpts available
upon request).

- Set RTS signals (if configured)
- Write to the comport and do wait on -different- overlapped IO.

Ther reason for this: If you use ReadFile() after WriteFile(), the following
might happen on very slow machines: Data comes in on the serial line, and
cannot be buffered by the serial port, and because there is no Read pending,
the data gets lost. (This happened to us, so its a real-life problem and not
something theoretical). 

Anyway, what seems to happen is that the WriteFile() simply doesn't return
(or rather: WriteFile() returns, but WaitForSingleObject(overlappedIO) times
out). 

This is what happens in our trace:
-------------------------------------
[07.11.2001 14:04.30,739 Thread 0x08085e28 Process 0x080673b0 Module 1127]
SerialDevice(PHYSICAL_SERVICES\Devices\TWINSAFE)::Write()
	HDEVICE hDevice = 0x4040ee00
	LPBYTE lpBuffer = 0x42c75cfc
	DWORD dwSize = 26 Bytes
	ULONG ulTimeout = 2000 Milliseconds

[07.11.2001 14:04.30,741 Thread 0x08085e28 Process 0x080673b0 Module 1127]
SerialDevice(PHYSICAL_SERVICES\Devices\TWINSAFE)::PortWrite

[07.11.2001 14:04.30,742 Thread 0x08085e28 Process 0x080673b0 Module 1127]
About to call WriteFile ( 26 Bytes)

[07.11.2001 14:04.30,744 Thread 0x08085e28 Process 0x080673b0 Module 1127]
About to call WaitForSingleObject

[07.11.2001 14:04.35,295 Thread 0x080837f8 Process 0x080673b0 Module 1127]
SerialDevice(PHYSICAL_SERVICES\Devices\TWINSAFE)::ListenerThread()
 WaitForSingleObject warned 258
-------------------------------------
So you see at 14:04.30,742 the WriteFile() using 26 bytes is issued, and
never completes; 5 seconds later the WaitForSingleObject() returns with erro
258 (timeout). (Note the different thread-ids).

In the wine trace (done with +comm +file) you see the following
-------------------------------------
trace:file:CreateFileA opening device 'COM1'
trace:comm:GetCommState handle 268, ptr 0x421666f8
trace:comm:GetCommState OK
trace:comm:GetCommState bytesize 8 baudrate 9600 fParity 1 Parity 0 stopbits
2
trace:comm:GetCommState ~IXON ~IXOFF
trace:comm:GetCommState ~CRTSCTS
trace:comm:BuildCommDCBAndTimeoutsA (baud=9600 parity=o data=8
stop=2,0x421666f8,(nil))
trace:comm:SetCommState handle 268, ptr 0x421666f8
trace:comm:SetCommState bytesize 8 baudrate 9600 fParity 1 Parity 0 stopbits
2
trace:comm:SetCommState ~IXON ~IXOFF
trace:comm:SetCommState CRTSCTS
trace:comm:SetCommState ~CRTSCTS
trace:comm:SetCommTimeouts (10c,0x421666e0)
trace:comm:SetCommMask handle 268, mask 1
trace:comm:PurgeComm handle 268, flags 5
trace:comm:PurgeComm handle 268, flags a
trace:comm:WaitCommEvent (10c 0x42b26e70 0x42b26e54 )
trace:comm:GetCommModemStatus 4126 -> MS_DSR_ON MS_CTS_ON
trace:comm:PurgeComm handle 268, flags a
trace:comm:PurgeComm handle 268, flags 5
trace:comm:SetCommTimeouts (10c,0x42c75a40)
trace:file:WriteFile 268 0x42c75cfc 26 0x42c75a4c 0x42c75a30
trace:file:WriteFileEx file 268 to buf 0x42c75cfc num 26 0x42c75a30 func
(nil) stub
trace:file:FILE_AsyncWriteService (0x42c75a30 0x42c75cfc 00000004)
trace:file:FILE_AsyncWriteService wrote 26 more bytes 26/26 so far
trace:file:GetOverlappedResult (268 0x42c75a30 0x42c75a4c 1)
trace:file:GetOverlappedResult waiting on 0x42c75a30
-------------------------------------

OK, maybe I've done something wrong when compiling. I downloaded the archive
"wine-20011004", and recompiled. When I check the binary (wine* in
/usr/local/bin), everything has a new compile date, but wine --version still
reports "release 20010731". This is what i did:

cd wine-20011004
configure
make deps && make
make install

Bye, Gerson




More information about the wine-users mailing list