I e-mailed this question to Bill Birthisel, the author of Win32::SerialPort and Win32API::CommPort. My original query and his answer (with his permission) follow:

______________________

I'm trying to open COM1 at 115200 baud on a Win98 machine using Win32::SerialPort. After first rebooting, I cannot. In fact, can_baud(115200) returns false, and are_baudrate omits 115200. Other baudrates, up to 38400, work fine. If I then go to HyperTerminal, I can open the same port at 115200, no problem. What's more, if I close the port, then exit H-T and return to my Perl program, it too will open COM1 at 115200 baud -- at least until I change baud rates. Then I need to go back to H-T to set up the port again. I'm using the latest versions of both Win32API::CommPort and Win32::SerialPort.

<GIGGLE>
True, Win9x does not consider 115200 and 57600 legal rates. It DOES accept 56000. This is a long-standing bug in the Windows API which Microsoft has decided not to fix. In the original concept, only TAPI could request the highest rates because "standard serial ports" (8250s/16450s) couldn't keep up. Of course, that doesn't explain 56000 (NT/2000 uses the correct 57600 and also allows 115200).
</GIGGLE>

So I'm wondering: What's happening here? What's HyperTerminal doing to gain access at 115200 baud that Perl can't do on its own?

It is ignoring the baud-rate validation feature in the API.

Can I get around this by altering the DCB using Win32API::CommPort?

Yes.

Should I? Is there a better way? So many questions!

You can try what I suggested to someone else (who didn't confirm it worked, so consider it an experiment):

In CommPort.pm, change the are_baudrate routine to the following:

sub are_baudrate { my $self = shift; return unless $self->{"_C_BAUD"}; if (@_) { my $newbaud = shift; $self->{"_L_BAUD"}{$newbaud} = $newbaud; } return keys(%{$self->{"_L_BAUD"}}); }

Then '@allowed = $PortObj->are_baudrate(115200);' should add it to the "allowed" list. A real implementation should have a bit more validation and error handling. Let me know if it works.

-bill

______________________

I pasted it in directly from his e-mail, and it worked great!

My code now reads:

unless ($Port = new Win32::SerialPort($PortName) and $Port->are_baudrate(115200) and $Port->baudrate($Baudrate) and $Port->parity('none') and $Port->databits(8) and $Port->stopbits(2) and $Port->handshake('rts') and $Port->buffers(4096,4096) and $Port->binary(1) and $Port->xon_limit(3000) and $Port->xoff_limit(300) and $Port->rts_active(1) and $Port->write_settings) { $mw->messageBox( -message => "Can't open $PortName at $Baudrate baud.", -type => 'OK' ); exit }

Many thanks to Bill and the Monks for their time and effort on this one!

-Phil


In reply to Re: Windows serial I/O by Anonymous Monk
in thread Windows serial I/O by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.