At 3:33 PM +0000 6/13/02, scottdouglasgoodwin wrote:
Here's the problem. The windows serial driver has a built in
function/dialog that allows you to configure the serial port.
If you use the port settings under the device manager, you will see
that you are presented with a dialog that has a dropdown list for
setting the baud rate. The list doesn't include 16457. And you can't
type in 16457. So there's no way to set it to 16457 through the
device manager. If you use MSCOMM in VB, you can use the settings
property to set the baud rate, etc. Again, it won't accept 16457 for
the same reason. The package javax.javacomm apparently has the same
problem---it just won't accept 16457 because it is using the serial
driver's list of valid baud rates.
Of course, programs like LocoNetMon, RR&Co, and Winlok work just fine
on the same computers that MSCOMM,javax.javacomm, etc don't work. Why?
Well, if you look at the source code for LocoNetMon (available from
the loconethackers group), you will see that it opens the Com Port
using Win32K's CreateFile function wich returns a file handle/file
descriptor. This file handle is used in the function GetComState
which gets the current device control block (dcb). You can then set
the baud rate in the dcb to 16457. Then use SetCommState to apply the
new settings.
I've just spent a long day trying to get the RXTX implementation to work at 16457 baud. My apologies for the length of this; if you're not interested in hardcore details, please skip the rest of the email. But if there's any chance you can help, I'd appreciate it.
The good news: It's now pretty clear what the code is doing. After various preliminaries, there's a case statement that takes the 'speed' as an integer (e.g. 9600) and converts it to a defined constant (e.g. B9600). This value then is used to invoke
if(
cfsetispeed( &ttyset, cspeed ) < 0 ||
cfsetospeed( &ttyset, cspeed ) < 0 )
{
report( "nativeSetSerialPortParams: Cannot Set Speed\n" );
goto fail;
}
where the constant was in the "cspeed" value and ttyset is a termios structure.
This can't handle the LocoNet rate, as cfsetispeed doesn't know about that rate; there's not a B16457 constant to express it, and the code doesn't look for it.
There is some code for dealing with the divisor explicitly. It's only compiled in if WIN32 is _not_ defined:
if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
{
goto fail;
}
...
sstruct.custom_divisor = ( sstruct.baud_base/cspeed );
if ( sstruct.baud_base < 1 ||
ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
{
goto fail;
}
(In the snippet above, cspeed contains the rate as an integer, not as a defined constant; yes, that's confusing.)
This is the point where it gets wierd. Note that cfsetispeed isn't part of the native windows API, so what's happening here? The RXTX maintainers have produced their own implementation of cfsetispeed on top of the Windows routines! It lives in their termios.c and win32termios.h.
cfsetispeed and cfsetospeed just make notes for a latter copy to a Windows DCB's BaudRate member; ioctl(.., TIOCSSERIAL, ...) doesn't do anything at all!
So after a huge amount of indirection, the program really is just setting dcb.BaudRate and invoking SetCommState. Amazing!
All of the above is based on static analysis, but it looks right.
Now for the bad news. Despite 15 hours of effort (c.f. ) I still can't get the original program to compile! RXTX is a Linux project, so their instructions involve cross-compiling with gcc. It's a mess of Java-generated headers, headers copied from Windows to Linux, etc, all munged together by a 7k-line configure script.
I've appealed for help from the maintainers mailing list. I'm not sure what else to do.
The easiest hack (if I could get it to compile!) would be to change the mapping so that some other baud rate actually gets written to the DCB as 16457. For example, nobody uses 110 baud anymore, so I could just hack this line:
case B110: ret = CBR_110; break;
(CBR_110 is literally 110, and will eventually be loaded into the DCB) to
case B110: ret = 16457; break;
then have the program try 110 baud on Windows. If I could just get the $%%^$& thing to compile!!!
Anybody feel like trying to edit the binary contents in a .dll?
Bob
--
--------------
Bob Jacobsen (Bob_Jacobsen@..., 510-486-7355, fax 510-495-2957)
Am working off a huge email backlog, call if it's urgent.