TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: Peter Schuller
from: Peter Fitzsimmons
date: 1996-07-23 00:34:36
subject: Modem and Direct Screen Writes

PS> But it won't work, DosOpen return 12. Maximus passes 
 PS> on porthandle "5" for COM2. Is there any specific 
 PS> "flag" i have to use?

You do not need to reopen the prot -- Maximus has already opened it.

Here is an old note I wrote:


 /* This sample will help you to the point of getting the ioctl's
  * working. Beginners have a lot of problems with them.   A good comm
  * program, unlike this one,  would have a dedicated read thread,
  * blocked on DosRead().  A good program may even have a write thread
  * too.
  */
 #define INCL_NOPMAPI    // no PM in this program
 #define INCL_DOS
 #define INCL_DOSDEVIOCTL        //DosDevIOCtl Values
 #include 
 #include 

 int main(void)
 {
     HFILE hf;
     APIRET rc;
     ULONG ulAction;
     ULONG bps;
     ULONG ulpinout, uldinout;
     DCBINFO dcb;

     /* Always open the modem in OPEN_SHARE_DENYREADWRITE!!!  Pass the open
      * handle to child programs (doors) that also want to use the modem.
      */
     rc = DosOpen("COM1",
                     &hf,
                     &ulAction,
                     0UL, FILE_NORMAL,
                     OPEN_ACTION_OPEN_IF_EXISTS,
                     OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0);
     if(rc){
         printf("sys%04u: dosopen(comx)\n", rc);
         return 1;
     }

      /* set baud rate */
     ulpinout = sizeof(bps);
     bps = 9600;
     rc  = DosDevIOCtl(  hf, IOCTL_ASYNC, ASYNC_SETBAUDRATE, &bps,
                         ulpinout, &ulpinout, NULL, 0, NULL );
     if(rc){
         printf("sys%04u: dosioctl(setbaud)\n", rc);
         return 1;
     }


     /* For future compatabilty, always read the current DCB and change
      * only those bits you are insterested in.  NEVER stuff your own
      * values into a setdcb call.
      */

     ulpinout=uldinout=0;
     rc = DosDevIOCtl(hf, IOCTL_ASYNC, ASYNC_GETDCBINFO,
             NULL, 0, &ulpinout, &dcb, sizeof(dcb), &uldinout);
     if(rc){
         printf("sys%04u: dosioctl(getdcb)\n", rc);
         return 1;
     }

    dcb.fbTimeout &= ~(MODE_WAIT_READ_TIMEOUT | MODE_READ_TIMEOUT); // turn off
    dcb.fbTimeout |= MODE_NOWAIT_READ_TIMEOUT;                      // turn on

     ulpinout=uldinout=0;
     rc = DosDevIOCtl(hf, IOCTL_ASYNC, ASYNC_SETDCBINFO,
             &dcb, sizeof(dcb), &ulpinout, NULL, 0, &uldinout);

     if(rc){
         printf("sys%04u: dosioctl(setdcb)\n", rc);
         return 1;
     }

     printf("ok\n");
     return 0;
 }

 An os/2 comm program should always be prepared to receive an open file
 handle to the comm port on the command line,  even if only as an option.

 If the handle is passed to it,  the program skips the DosOpen();  in
 this case it should never call DosClose() either.  It will not have to
 change the line speed (bps rate), since the program that called it
 would have done that (assuming that there is a call in progress on the
 modem).  If it needs to change the DCB (to change the read-mode,  for
 example),  it should save a copy of the original DCB on entry,  and
 restore it on exit.

 The program that passes the handle to the child must halt all activity
 to the handle until the child ends.

 If a handle is not passed from a parent program,  than  your program
 will be the only one that ever issues a DosOpen() on the com port.
 Specifying OPEN_SHARE_DENYREADWRITE enforces this.   When you call child
 programs that use the modem ("doors"),  pass the HFILE (file handle) to
 them on the command line (or by some other dynamic method).

 Following these simple rules will prevent a DOS program (vdm) from
 walking on top of a live connection,  and will enforce an orderly way of
 ensuring that only one os/2 program at a time is actively doing i/o to
 the modem.   Think of it as a relay-race;  when a runner passes the
 baton on to the next runner,  he is implicitly agreeing to stop using
 the port (even though it is still open) until he gets the baton back
 (ie: when the child program terminates).

 Many DOS programmers want to protest;  they simply all want to re-open
 "COM1" by name.  This worked ok under dos,  where only one program could
 run at a time (this was the enforcement mechanism for dos).  But under
 os/2 or NT, where you know there can be many programs running,  sharing
 the modem must be enforced by programming;  leaving it up to the user
 (by using OPEN_SHARE_DENY_NONE) will only cause them much grief.

 Don't forget the the serial port is INHERENTLY single-use,  and OS/2 is
 a multitasking OS -- resist the temptation to use "denynone" sharing.

 -------------------------------------------------------------------------

 CM> However, I stumpled across this myself a while ago.  It seems to wait on 
 CM> the DosRead call, and returns only when there's a 
 CM> character in the buffer, or dcbInfo.fbTimeout expires. 
 CM>  That's not really a BIG deal, as I can simply loop 
 CM> back up if there is nothing in the buffer.

That's right.

 CM> However, I would like to avoid that, and simply have 
 CM> the DosRead return only when there's a character.  It 
 CM> just smacks too much of DOS-polling to me.  :-).

In a way -- but unless the timeout is set to a very short period, it is not
like dos polling,  since the DosRead() is blocked in ring0 by the device
driver.

If you set the timeout period to 5000ms,  for example,  and DosRead()
returns 0 bytes,  it is a great time to do a carrier check.    And during
the 5000ms,  your thread will have used 0% of the cpu;  the DD will have
stopped it dead it its tracks.

The reason why "wait for something",  even with its timeout
period, is desired over "normal" read-timeout-processing (I
assume everyone knows "no wait" mode is bad too) is this:

    Most serial comm programs never know how many bytes to expect;  even
    if they think they know (during an xmodem packet receive,  for
    example) they have to anticipate that noise may cause the size of
    the packet to be larger of smaller than expected.

    Since (in normal mode) DosRead() will NEVER RETURN (short of
    timeout) until it has ready as many bytes as you asked for,  you're
    going to be in big trouble if even it is one byte short.

    The solution to this to DosRead() one byte at a time, or to set a
    timeout setting so short (a few ms) that you may as well be using
    "No wait" mode.  Both of these solutions are GROSSLY inefficient.
    You can not even support 9600 bps by calling DosRead/DosWrite one
    byte at a time,  since the pathway to the device driver is very long
    and requires a ring switch both there and back.

    Now,  in wait-for-something mode,  the you can pass the device
    driver a large DosRead() buffer (1000 bytes for example),  and it
    will return with as much as it can.  Let's say 12 bytes arrive, then
    there is a slight pause in the incoming stream --- the DD will
    return you the 12 bytes so you can process them.  Or, perhaps,  when
    you call DosRead() there were some bytes already waiting (saved by
    the DD's IRQ service routine), it will return those to you right
    away.  If there is a steady stream of bytes coming in,  the DD will
    fill your 1000 byte buffer all of the way before returning.

    Therefore,  you always find out about incoming data almost right
    away, yet do not have to enter the device driver (ie: call DosRead)
    very often. I'm in heaven.


If you really want a function that never returns until it has data,write a
wrapper around the DosRead() code, or using somehting like MAXCOMM.DLL that
does this for you.


--- Maximus/2 3.00
* Origin: Sol 3 * Toronto * V.32 * (905)858-8488 (1:259/414)
SEEN-BY: 50/99 270/101 620/243 625/100 711/401 409 410 413 430 808 809 934
SEEN-BY: 711/955 712/407 515 624 628 713/888 800/1
@PATH: 259/414 400 99 250/99 3615/50 396/1 270/101 712/515 711/808 934

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.