home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES2.ZIP / UUCICO / ulibos2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-20  |  45.9 KB  |  1,490 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    u l i b o s 2 . c                                               */
  3. /*                                                                    */
  4. /*    OS/2 serial port support for UUCICO                             */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *       $Id: ulibos2.c 1.32 1993/11/20 14:48:53 ahd Exp $
  21.  *       $Log: ulibos2.c $
  22.  * Revision 1.32  1993/11/20  14:48:53  ahd
  23.  * Add support for passing port name/port handle/port speed/user id to child
  24.  *
  25.  * Revision 1.31  1993/11/16  05:37:01  ahd
  26.  * Double buffer I/O to reduce overruns
  27.  *
  28.  * Revision 1.30  1993/11/15  05:43:29  ahd
  29.  * Save/restore port status for dain bramaged programs like TCP/IP
  30.  * Normalize, shorten error messages
  31.  *
  32.  * Revision 1.29  1993/11/08  04:46:49  ahd
  33.  * Drop DTR if program is killed
  34.  *
  35.  * Revision 1.28  1993/11/06  17:57:09  rhg
  36.  * Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  37.  *
  38.  * Revision 1.27  1993/11/06  13:04:13  ahd
  39.  * Disable RTS handshaking ... OS/2 rejects it
  40.  *
  41.  * Revision 1.26  1993/11/06  12:19:26  rommel
  42.  * Enable DTR and RTS for modem
  43.  *
  44.  * Revision 1.25  1993/10/12  01:33:23  ahd
  45.  * Normalize comments to PL/I style
  46.  *
  47.  * Revision 1.24  1993/10/07  22:56:45  ahd
  48.  * Use dynamically allocated buffer
  49.  *
  50.  * Revision 1.23  1993/10/03  22:09:09  ahd
  51.  * Use unsigned long to display speed
  52.  *
  53.  * Revision 1.22  1993/10/01  01:17:44  ahd
  54.  * Drop unneeded special case for port in use message
  55.  *
  56.  * Revision 1.21  1993/09/29  05:25:21  ahd
  57.  * Don't die after duplicate port close
  58.  *
  59.  * Revision 1.20  1993/09/29  04:52:03  ahd
  60.  * Use unique handler for port suspending
  61.  *
  62.  * Revision 1.19  1993/09/27  04:04:06  ahd
  63.  * Normalize references to modem speed to avoid incorrect displays
  64.  *
  65.  * Revision 1.18  1993/09/25  03:07:56  ahd
  66.  * Convert to standard OS/2 error message call
  67.  *
  68.  * Revision 1.17  1993/09/24  03:43:27  ahd
  69.  * Use OS/2 error message routine
  70.  *
  71.  * Revision 1.16  1993/09/21  01:42:13  ahd
  72.  * Use standard MAXPACK limit for save buffer size
  73.  *
  74.  * Revision 1.15  1993/09/20  04:46:34  ahd
  75.  * OS/2 2.x support (BC++ 1.0 support)
  76.  * TCP/IP support from Dave Watt
  77.  * 't' protocol support
  78.  *
  79.  * Revision 1.14  1993/05/30  15:25:50  ahd
  80.  * Multiple driver support
  81.  *
  82.  * Revision 1.13  1993/05/30  00:08:03  ahd
  83.  * Multiple communications driver support
  84.  * Delete trace functions
  85.  *
  86.  * Revision 1.12  1993/05/09  03:41:47  ahd
  87.  * Make swrite accept constant input strings
  88.  *
  89.  * Revision 1.11  1993/04/11  00:34:11  ahd
  90.  * Global edits for year, TEXT, etc.
  91.  *
  92.  * Revision 1.10  1993/04/10  21:25:16  dmwatt
  93.  * Add Windows/NT support
  94.  *
  95.  * Revision 1.9  1993/04/05  04:32:19  ahd
  96.  * Additional traps for modem dropping out
  97.  *
  98.  * Revision 1.8  1993/04/04  04:57:01  ahd
  99.  * Add configurable OS/2 priority values
  100.  *
  101.  * Revision 1.7  1992/12/30  13:02:55  dmwatt
  102.  * Dual path for Windows/NT and OS/2
  103.  *
  104.  * Revision 1.6  1992/12/11  12:45:11  ahd
  105.  * Correct RTS handshake
  106.  *
  107.  * Revision 1.5  1992/12/04  01:00:27  ahd
  108.  * Add copyright message, reblock other comments
  109.  *
  110.  * Revision 1.4  1992/11/29  22:09:10  ahd
  111.  * Add new define for BC++ OS/2 build
  112.  *
  113.  * Revision 1.3  1992/11/19  03:00:39  ahd
  114.  * drop rcsid
  115.  *
  116.  * Revision 1.2  1992/11/15  20:11:48  ahd
  117.  * Add English display of modem status and error bits
  118.  *
  119.  */
  120.  
  121. /*--------------------------------------------------------------------*/
  122. /*                        System include files                        */
  123. /*--------------------------------------------------------------------*/
  124.  
  125. #include <stdlib.h>
  126. #include <stdio.h>
  127. #include <string.h>
  128. #include <fcntl.h>
  129. #include <io.h>
  130. #include <time.h>
  131.  
  132. /*--------------------------------------------------------------------*/
  133. /*                         OS/2 include files                         */
  134. /*--------------------------------------------------------------------*/
  135.  
  136. #define INCL_DOSDEVIOCTL
  137. #define INCL_BASE
  138. #define INCL_NOPMAPI
  139.  
  140. #include <os2.h>
  141. #include <limits.h>
  142.  
  143. #ifndef __OS2__
  144. typedef USHORT APIRET ;  /* Define older API return type              */
  145. #endif
  146.  
  147. /*--------------------------------------------------------------------*/
  148. /*                    UUPC/extended include files                     */
  149. /*--------------------------------------------------------------------*/
  150.  
  151. #include "lib.h"
  152. #include "ulib.h"
  153. #include "ssleep.h"
  154. #include "catcher.h"
  155. #include "pos2err.h"
  156.  
  157. #include "commlib.h"
  158. #include "usrcatch.h"
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*                          Global variables                          */
  162. /*--------------------------------------------------------------------*/
  163.  
  164. currentfile();
  165.  
  166. static boolean   carrierDetect = FALSE;  /* Modem is not connected    */
  167.  
  168. static boolean hangupNeeded = FALSE;
  169.  
  170. static unsigned short currentSpeed = 0;
  171. static BPS saveSpeed = 0;
  172.  
  173. #define FAR_NULL ((PVOID) 0L)
  174.  
  175. /*--------------------------------------------------------------------*/
  176. /*           Definitions of control structures for DOS API            */
  177. /*--------------------------------------------------------------------*/
  178.  
  179. static HFILE com_handle;
  180. static LINECONTROL com_attrib;
  181. static MODEMSTATUS com_signals;
  182. static DCBINFO com_dcbinfo;
  183.  
  184. static LINECONTROL save_com_attrib;
  185. static DCBINFO save_com_dcbinfo;
  186.  
  187. static void ShowError( const USHORT status );
  188.  
  189. static void ShowModem( const BYTE status );
  190.  
  191. /*--------------------------------------------------------------------*/
  192. /*    n o p e n l i n e                                               */
  193. /*                                                                    */
  194. /*    Open the serial port for I/O                                    */
  195. /*--------------------------------------------------------------------*/
  196.  
  197. int nopenline(char *name, BPS portSpeed, const boolean direct )
  198. {
  199.  
  200.    APIRET rc;
  201.    USHORT com_error;
  202.  
  203. #ifdef __OS2__
  204.    ULONG ParmLengthInOut;
  205.    ULONG DataLengthInOut;
  206.  
  207.    ULONG action;
  208.  
  209. #else
  210.  
  211.    USHORT action;
  212.  
  213. #endif
  214.  
  215.    if (portActive)               /* Was the port already active?    */
  216.       closeline();               /* Yes --> Shutdown it before open */
  217.  
  218. #ifdef UDEBUG
  219.    printmsg(15, "nopenline: %s, %lu", name, portSpeed);
  220. #endif
  221.  
  222. /*--------------------------------------------------------------------*/
  223. /*                      Validate the port format                      */
  224. /*--------------------------------------------------------------------*/
  225.  
  226.    if (!equaln(name, "COM", 3 ))
  227.    {
  228.       printmsg(0,"nopenline: Communications port begin with COM, was %s",
  229.          name);
  230.       panic();
  231.    }
  232.  
  233. /*--------------------------------------------------------------------*/
  234. /*                          Perform the open                          */
  235. /*--------------------------------------------------------------------*/
  236.  
  237.    rc = DosOpen( name,
  238.                  &com_handle,
  239.                  &action,
  240.                  0L,
  241.                  0 ,
  242.                  FILE_OPEN ,
  243.                  OPEN_FLAGS_FAIL_ON_ERROR |
  244.                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0L );
  245.  
  246. /*--------------------------------------------------------------------*/
  247. /*    Check the open worked.  We translation the common obvious       */
  248. /*    error of file in use to english, for all other errors are we    */
  249. /*    report the raw error code.                                      */
  250. /*--------------------------------------------------------------------*/
  251.  
  252.    if ( rc )
  253.    {
  254.       printOS2error( name, rc );
  255.       return TRUE;
  256.    }
  257.  
  258. /*--------------------------------------------------------------------*/
  259. /*            Reset any errors on the communications port             */
  260. /*--------------------------------------------------------------------*/
  261.  
  262. #ifdef __OS2__
  263.  
  264.    ParmLengthInOut = 0;
  265.    DataLengthInOut = sizeof(com_error);
  266.    rc = DosDevIOCtl( com_handle, IOCTL_ASYNC, ASYNC_GETCOMMERROR,
  267.       NULL,0L,&ParmLengthInOut,(PVOID) &com_error,sizeof(com_error),
  268.       &DataLengthInOut);
  269.  
  270. #else
  271.  
  272.    rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
  273.                      IOCTL_ASYNC, com_handle);
  274.  
  275. #endif
  276.  
  277.    if (rc)
  278.    {
  279.       ShowError( com_error );
  280.       printOS2error( "ASYNC_GETCOMMERROR", rc );
  281.    } /*if */
  282.    else if ( com_error )
  283.       ShowError( com_error );
  284.  
  285.  
  286. /*--------------------------------------------------------------------*/
  287. /*                           Set port speed                           */
  288. /*--------------------------------------------------------------------*/
  289.  
  290.    saveSpeed = GetSpeed();    /* Save original speed                 */
  291.    SIOSpeed(portSpeed);
  292.  
  293. /*--------------------------------------------------------------------*/
  294. /*                        Set line attributes                         */
  295. /*--------------------------------------------------------------------*/
  296.  
  297. #ifdef UDEBUG
  298.    printmsg(15,"nopenline: Getting attributes");
  299. #endif
  300.  
  301. #ifdef __OS2__
  302.  
  303.    ParmLengthInOut = 0;
  304.    DataLengthInOut = sizeof(com_attrib);
  305.    rc = DosDevIOCtl( com_handle,
  306.                      IOCTL_ASYNC,
  307.                      ASYNC_GETLINECTRL,
  308.                      NULL,
  309.                      0L,
  310.                      &ParmLengthInOut,
  311.                      (PVOID) &com_attrib,
  312.                      sizeof(com_attrib),
  313.                      &DataLengthInOut); /* Get old attributes from device  */
  314.  
  315. #else
  316.  
  317.    rc = DosDevIOCtl( &com_attrib,
  318.                      FAR_NULL,
  319.                      ASYNC_GETLINECTRL,
  320.                      IOCTL_ASYNC,
  321.                      com_handle);   /* Get old attributes from device  */
  322. #endif
  323.  
  324.    if (rc)
  325.    {
  326.       printOS2error( "ASYNC_GETLINECTRL", rc );
  327.       panic();
  328.    } /*if */
  329.  
  330.    memcpy( &save_com_attrib, &com_attrib, sizeof com_attrib );
  331.                               /* Save the attributes                */
  332.  
  333.    com_attrib.bDataBits = 0x08; /* Use eight bit path for data      */
  334.    com_attrib.bParity   = 0x00; /* No parity                        */
  335.    com_attrib.bStopBits = 0x00; /* 1 Stop Bit                       */
  336.  
  337. #ifdef UDEBUG
  338.    printmsg(15,"nopenline: Setting attributes");
  339. #endif
  340.  
  341. #ifdef __OS2__
  342.  
  343.    ParmLengthInOut = sizeof(com_attrib);
  344.    DataLengthInOut = 0;
  345.    rc = DosDevIOCtl( com_handle,
  346.                      IOCTL_ASYNC,
  347.                      ASYNC_SETLINECTRL,
  348.                      (PVOID) &com_attrib,
  349.                      sizeof(com_attrib),
  350.                      &ParmLengthInOut,
  351.                      NULL,
  352.                      0L,
  353.                      &DataLengthInOut);
  354.  
  355. #else
  356.  
  357.    rc = DosDevIOCtl( FAR_NULL,
  358.                      &com_attrib,
  359.                      ASYNC_SETLINECTRL,
  360.                      IOCTL_ASYNC,
  361.                      com_handle);
  362. #endif
  363.  
  364.    if (rc)
  365.    {
  366.       printOS2error( "ASYNC_SETLINECTRL", rc );
  367.       panic();
  368.    } /*if */
  369.  
  370. /*--------------------------------------------------------------------*/
  371. /*       Disable software (XON/XOFF) flow control and enable          */
  372. /*       hardware (CTS) for flow control                              */
  373. /*--------------------------------------------------------------------*/
  374.  
  375. #ifdef UDEBUG
  376.    printmsg(15,"nopenline: Getting flow control information");
  377. #endif
  378.  
  379. #ifdef __OS2__
  380.  
  381.    ParmLengthInOut = 0;
  382.    DataLengthInOut = sizeof(com_dcbinfo);
  383.    rc = DosDevIOCtl( com_handle,
  384.                      IOCTL_ASYNC,
  385.                      ASYNC_GETDCBINFO,
  386.                      NULL,
  387.                      0L,
  388.                      &ParmLengthInOut,
  389.                      (PVOID) &com_dcbinfo,
  390.                      sizeof(com_dcbinfo),
  391.                      &DataLengthInOut);   /* Get old attributes from device  */
  392.  
  393. #else
  394.  
  395.    rc = DosDevIOCtl( &com_dcbinfo,
  396.                      FAR_NULL,
  397.                      ASYNC_GETDCBINFO,
  398.                      IOCTL_ASYNC,
  399.                      com_handle);    /* Get old attributes from device  */
  400.  
  401. #endif
  402.  
  403.    if (rc)
  404.    {
  405.       printOS2error( "ASYNC_GETDCBINFO", rc );
  406.       panic();
  407.    } /*if */
  408.  
  409.    memcpy( &save_com_dcbinfo, &com_dcbinfo, sizeof com_dcbinfo );
  410.                               /* Save the DCB information            */
  411.  
  412.    com_dcbinfo.usWriteTimeout = 2999;  /* Write timeout 30 seconds   */
  413.    com_dcbinfo.usReadTimeout = 24;     /* Read timeout .25 seconds   */
  414.    com_dcbinfo.fbCtlHndShake = (BYTE) (MODE_DTR_CONTROL |
  415.                                       (direct ? 0 : MODE_CTS_HANDSHAKE));
  416.                                        /* Always drop DTR at port close,
  417.                                           only use CTS handshaking on
  418.                                           requested ports.            */
  419.  
  420.    com_dcbinfo.fbFlowReplace = MODE_RTS_HANDSHAKE;
  421.                                        /* Handshake on output         */
  422.  
  423.    com_dcbinfo.fbTimeout = MODE_READ_TIMEOUT | MODE_NO_WRITE_TIMEOUT;
  424.  
  425. #ifdef UDEBUG
  426.    printmsg(15,"nopenline: Setting dcb information");
  427. #endif
  428.  
  429. #ifdef __OS2__
  430.  
  431.    ParmLengthInOut = sizeof(com_dcbinfo);
  432.    DataLengthInOut = 0;
  433.    rc = DosDevIOCtl( com_handle,
  434.                      IOCTL_ASYNC,
  435.                      ASYNC_SETDCBINFO,
  436.                      (PVOID) &com_dcbinfo,
  437.                      sizeof(com_dcbinfo),
  438.                      &ParmLengthInOut,
  439.                      NULL,
  440.                      0L,
  441.                      &DataLengthInOut);
  442.  
  443. #else
  444.  
  445.    rc = DosDevIOCtl( FAR_NULL,
  446.                      &com_dcbinfo,
  447.                      ASYNC_SETDCBINFO,
  448.                      IOCTL_ASYNC,
  449.                      com_handle);
  450.  
  451. #endif
  452.  
  453.    if ( rc )
  454.    {
  455.       printOS2error( "ASYNC_SETDCBINFO", rc );
  456.       panic();
  457.    } /*if */
  458.  
  459. /*--------------------------------------------------------------------*/
  460. /*                     Raise Data Terminal Ready                      */
  461. /*--------------------------------------------------------------------*/
  462.  
  463.    com_signals.fbModemOn = DTR_ON;
  464.    com_signals.fbModemOff = 0xff;
  465.  
  466. #ifdef UDEBUG
  467.    printmsg(15,"nopenline: Raising RTS/DTR");
  468. #endif
  469.  
  470. #ifdef __OS2__
  471.  
  472.    ParmLengthInOut = sizeof(com_signals);
  473.    DataLengthInOut = sizeof(com_error);
  474.  
  475.    rc = DosDevIOCtl( com_handle,
  476.                      IOCTL_ASYNC,
  477.                      ASYNC_SETMODEMCTRL,
  478.                      (PVOID)&com_signals,
  479.                      sizeof(com_signals),
  480.                      &ParmLengthInOut,
  481.                      (PVOID) &com_error,
  482.                      sizeof(com_error),
  483.                      &DataLengthInOut);
  484.  
  485. #else
  486.  
  487.    rc = DosDevIOCtl( &com_error,
  488.                      &com_signals,
  489.                      ASYNC_SETMODEMCTRL,
  490.                      IOCTL_ASYNC,
  491.                      com_handle);
  492.  
  493. #endif
  494.  
  495.    if (rc)
  496.    {
  497.       printOS2error( "ASYNC_SETMODEMCTRL", rc );
  498.       ShowError( com_error );
  499.       panic();
  500.    } /*if */
  501.  
  502.    traceStart( name );     /* Enable logging                         */
  503.  
  504.    portActive = TRUE;      /* record status for error handler        */
  505.    carrierDetect = FALSE;  /* Modem is not connected                 */
  506.  
  507. /*--------------------------------------------------------------------*/
  508. /*                     Wait for port to stablize                      */
  509. /*--------------------------------------------------------------------*/
  510.  
  511.    ddelay(500);            /* Allow port to stablize          */
  512.    return 0;
  513.  
  514. } /*nopenline*/
  515.  
  516. /*--------------------------------------------------------------------*/
  517. /*    n s r e a d                                                     */
  518. /*                                                                    */
  519. /*    Read from the serial port                                       */
  520. /*                                                                    */
  521. /*   Non-blocking read essential to "g" protocol.  See "dcpgpkt.c"    */
  522. /*   for description.                                                 */
  523. /*                                                                    */
  524. /*   This all changes in a multi-tasking system.  Requests for I/O    */
  525. /*   should get queued and an event flag given.  Then the             */
  526. /*   requesting process (e.g. gmachine()) waits for the event flag    */
  527. /*   to fire processing either a read or a write.  Could be           */
  528. /*   implemented on VAX/VMS or DG but not MS-DOS.                     */
  529. /*                                                                    */
  530. /*    OS/2 we could multitask, but we just let the system provide     */
  531. /*    a timeout for us with very little CPU usage.                    */
  532. /*--------------------------------------------------------------------*/
  533.  
  534. unsigned int nsread(char *output, unsigned int wanted, unsigned int timeout)
  535. {
  536.    APIRET rc;
  537.    time_t stop_time ;
  538.    time_t now ;
  539.    USHORT com_error;
  540.  
  541.    boolean firstPass = TRUE;
  542.  
  543. #ifdef __OS2__
  544.    ULONG ParmLengthInOut;
  545.    ULONG DataLengthInOut;
  546. #endif
  547.  
  548. /*--------------------------------------------------------------------*/
  549. /*                           Validate input                           */
  550. /*--------------------------------------------------------------------*/
  551.  
  552.    if ( wanted > commBufferLength )
  553.    {
  554.       printmsg(0,"nsread: Overlength read, wanted %u bytes into %u buffer!",
  555.                      (unsigned int) wanted,
  556.                      (unsigned int) commBufferLength );
  557.       panic();
  558.    }
  559.  
  560. /*--------------------------------------------------------------------*/
  561. /*           Determine if our internal buffer has the data            */
  562. /*--------------------------------------------------------------------*/
  563.  
  564.    if (commBufferUsed >= wanted)
  565.    {
  566.       memcpy( output, commBuffer, wanted );
  567.       commBufferUsed -= wanted;
  568.       if ( commBufferUsed )   /* Any data left over?                 */
  569.          memmove( commBuffer, commBuffer + wanted, commBufferUsed );
  570.                               /* Yes --> Save it                     */
  571.       return wanted + commBufferUsed;
  572.    } /* if */
  573.  
  574. /*--------------------------------------------------------------------*/
  575. /*            Reset any errors on the communications port             */
  576. /*--------------------------------------------------------------------*/
  577.  
  578. #ifdef __OS2__
  579.  
  580.    ParmLengthInOut = 0;
  581.    DataLengthInOut = sizeof(com_error);
  582.    rc = DosDevIOCtl( com_handle,
  583.                      IOCTL_ASYNC,
  584.                      ASYNC_GETCOMMERROR,
  585.                      NULL,
  586.                      0L,
  587.                      &ParmLengthInOut,
  588.                      (PVOID) &com_error,
  589.                      sizeof(com_error),
  590.                      &DataLengthInOut);
  591.  
  592. #else
  593.  
  594.    rc = DosDevIOCtl( &com_error,
  595.                      FAR_NULL,
  596.                      ASYNC_GETCOMMERROR ,
  597.                      IOCTL_ASYNC,
  598.                      com_handle);
  599.  
  600. #endif
  601.  
  602.    if (rc )
  603.    {
  604.       printOS2error( "ASYNC_GETCOMMERROR", rc );
  605.    } /*if */
  606.    else if ( com_error )
  607.       ShowError( com_error );
  608.  
  609. /*--------------------------------------------------------------------*/
  610. /*                 Determine when to stop processing                  */
  611. /*--------------------------------------------------------------------*/
  612.  
  613.    if ( timeout == 0 )
  614.    {
  615.       stop_time = 0;
  616.       now = 1;                /* Any number greater than stop time   */
  617.    }
  618.    else {
  619.       time( & now );
  620.       stop_time = now + timeout;
  621.    }
  622.  
  623. /*--------------------------------------------------------------------*/
  624. /*            Try to read any needed data into the buffer             */
  625. /*--------------------------------------------------------------------*/
  626.  
  627.    do {
  628.       USHORT needed =  (USHORT) wanted - commBufferUsed;
  629.  
  630.       USHORT portTimeout;
  631.  
  632. #ifdef __OS2__
  633.       ULONG received = 0;
  634. #else
  635.       USHORT received = 0;
  636. #endif
  637.  
  638. /*--------------------------------------------------------------------*/
  639. /*                     Handle an aborted program                      */
  640. /*--------------------------------------------------------------------*/
  641.  
  642.       if ( raised )
  643.          return 0;
  644.  
  645.       if ( terminate_processing )
  646.       {
  647.          static boolean recurse = FALSE;
  648.          if ( ! recurse )
  649.          {
  650.             printmsg(2,"nsread: User aborted processing");
  651.             recurse = TRUE;
  652.          }
  653.          return 0;
  654.       }
  655.  
  656. /*--------------------------------------------------------------------*/
  657. /*           Compute a new timeout for the read, if needed            */
  658. /*--------------------------------------------------------------------*/
  659.  
  660.       if ((stop_time <= now ) || firstPass )
  661.       {
  662.          portTimeout = 0;
  663.          firstPass = FALSE;
  664.       }
  665.       else {
  666.          portTimeout = (USHORT) (stop_time - now) / needed * 100;
  667.          if (portTimeout < 100)
  668.             portTimeout = 100;
  669.       } /* else */
  670.  
  671.       if ( portTimeout != com_dcbinfo.usReadTimeout )
  672.       {
  673.          com_dcbinfo.usReadTimeout = portTimeout;
  674.  
  675. #ifdef __OS2__
  676.  
  677.          ParmLengthInOut = sizeof(com_dcbinfo);
  678.          DataLengthInOut = 0;
  679.          rc = DosDevIOCtl( com_handle,
  680.                            IOCTL_ASYNC,
  681.                            ASYNC_SETDCBINFO,
  682.                            (PVOID) &com_dcbinfo,
  683.                            sizeof(com_dcbinfo),
  684.                            &ParmLengthInOut,
  685.                            NULL,
  686.                            0L,
  687.                            &DataLengthInOut);
  688.  
  689. #else
  690.  
  691.          rc = DosDevIOCtl(FAR_NULL,
  692.                           &com_dcbinfo,
  693.                           ASYNC_SETDCBINFO,
  694.                           IOCTL_ASYNC,
  695.                           com_handle);
  696.  
  697. #endif
  698.          if ( rc )
  699.          {
  700.             printOS2error( "ASYNC_SETDCBINFO", rc );
  701.             panic();
  702.          } /* if */
  703.       } /* if */
  704.  
  705. #ifdef UDEBUG
  706.       printmsg(15,"nsread: Port time out is %ud seconds/100",
  707.                portTimeout);
  708. #endif
  709.  
  710. /*--------------------------------------------------------------------*/
  711. /*                 Read the data from the serial port                 */
  712. /*--------------------------------------------------------------------*/
  713.  
  714.       rc = DosRead( com_handle,
  715.                     commBuffer + commBufferUsed,
  716.                     portTimeout ? needed : commBufferLength - commBufferUsed,
  717.                     &received );
  718.  
  719.       if ( rc == ERROR_INTERRUPT)
  720.       {
  721.          printmsg(2,"Read Interrupted");
  722.          return 0;
  723.       }
  724.       else if ( rc != 0 )
  725.       {
  726.          printmsg(0,"nsread: Read from comm port for %d bytes failed.",
  727.                   needed);
  728.          printOS2error( "DosRead", rc );
  729.          commBufferUsed = 0;
  730.          return 0;
  731.       }
  732.  
  733. #ifdef UDEBUG
  734.       printmsg(15,"nsread: Want %d characters, received %d, total %d in buffer",
  735.                   (int) wanted,
  736.                   (int) received,
  737.                   (int) commBufferUsed + received);
  738. #endif
  739.  
  740. /*--------------------------------------------------------------------*/
  741. /*                    Log the newly received data                     */
  742. /*--------------------------------------------------------------------*/
  743.  
  744.       traceData( commBuffer + commBufferUsed, (unsigned) received, FALSE );
  745.  
  746. /*--------------------------------------------------------------------*/
  747. /*            If we got the data, return it to the caller             */
  748. /*--------------------------------------------------------------------*/
  749.  
  750.       commBufferUsed += received;
  751.       if ( commBufferUsed >= wanted )
  752.       {
  753.          memcpy( output, commBuffer, wanted );
  754.          commBufferUsed -= wanted;
  755.          if ( commBufferUsed )   /* Any data left over?              */
  756.             memmove( commBuffer, commBuffer + wanted, commBufferUsed );
  757.  
  758.          return wanted;
  759.  
  760.       } /* if */
  761.  
  762. /*--------------------------------------------------------------------*/
  763. /*                 Update the clock for the next pass                 */
  764. /*--------------------------------------------------------------------*/
  765.  
  766.       if (stop_time > 0)
  767.          time( &now );
  768.  
  769.    } while (stop_time > now);
  770.  
  771. /*--------------------------------------------------------------------*/
  772. /*         We don't have enough data; report what we do have          */
  773. /*--------------------------------------------------------------------*/
  774.  
  775.    return commBufferUsed;
  776.  
  777. } /*nsread*/
  778.  
  779. /*--------------------------------------------------------------------*/
  780. /*    n s w r i t e                                                   */
  781. /*                                                                    */
  782. /*    Write to the serial port                                        */
  783. /*--------------------------------------------------------------------*/
  784.  
  785. int nswrite(const char *input, unsigned int len)
  786. {
  787.  
  788.    char *data = (char *) input;
  789.  
  790. #ifdef __OS2__
  791.     ULONG bytes;
  792. #else
  793.    size_t bytes;
  794. #endif
  795.  
  796.    APIRET rc;
  797.  
  798.    hangupNeeded = TRUE;      /* Flag that the port is now dirty  */
  799.  
  800. /*--------------------------------------------------------------------*/
  801. /*         Write the data out as the queue becomes available          */
  802. /*--------------------------------------------------------------------*/
  803.  
  804.    rc = DosWrite( com_handle, data , len, &bytes);
  805.    if (rc)
  806.    {
  807.       printOS2error( "DosWrite", rc );
  808.       return bytes;
  809.    } /*if */
  810.  
  811. /*--------------------------------------------------------------------*/
  812. /*                        Log the data written                        */
  813. /*--------------------------------------------------------------------*/
  814.  
  815.    traceData( data, len, TRUE);
  816.  
  817. /*--------------------------------------------------------------------*/
  818. /*            Return bytes written to the port to the caller          */
  819. /*--------------------------------------------------------------------*/
  820.  
  821.    return len;
  822.  
  823. } /* nswrite */
  824.  
  825. /*--------------------------------------------------------------------*/
  826. /*    n s s e n d b r k                                               */
  827. /*                                                                    */
  828. /*    send a break signal out the serial port                         */
  829. /*--------------------------------------------------------------------*/
  830.  
  831. void nssendbrk(unsigned int duration)
  832. {
  833.  
  834. #ifdef __OS2__
  835.    ULONG ParmLengthInOut;
  836.    ULONG DataLengthInOut;
  837. #endif
  838.  
  839.    USHORT com_error;
  840.  
  841. #ifdef UDEBUG
  842.    printmsg(12, "ssendbrk: %d", duration);
  843. #endif
  844.  
  845. #ifdef __OS2__
  846.  
  847.    ParmLengthInOut = 0;
  848.    DataLengthInOut = sizeof(com_error);
  849.    DosDevIOCtl( com_handle,
  850.                 IOCTL_ASYNC,
  851.                 ASYNC_SETBREAKON,
  852.                 NULL,
  853.                 0L,
  854.                 &ParmLengthInOut,
  855.                 (PVOID) &com_error,
  856.                 sizeof(com_error),
  857.                 &DataLengthInOut);
  858.  
  859. #else
  860.  
  861.    DosDevIOCtl( &com_error,
  862.                 FAR_NULL,
  863.                 ASYNC_SETBREAKON,
  864.                 IOCTL_ASYNC,
  865.                 com_handle);
  866.  
  867. #endif
  868.  
  869.    if ( com_error )
  870.       ShowError( com_error );
  871.  
  872.    ddelay( duration == 0 ? 200 : duration);
  873.  
  874. #ifdef __OS2__
  875.    ParmLengthInOut = 0;
  876.    DataLengthInOut = sizeof(com_error);
  877.    DosDevIOCtl( com_handle,
  878.                 IOCTL_ASYNC,
  879.                 ASYNC_SETBREAKOFF,
  880.                 NULL,
  881.                 0L,
  882.                 &ParmLengthInOut,
  883.                 (PVOID) &com_error,
  884.                 sizeof(com_error),
  885.                 &DataLengthInOut);
  886.  
  887. #else
  888.    DosDevIOCtl( &com_error,
  889.                 FAR_NULL,
  890.                 ASYNC_SETBREAKOFF,
  891.                 IOCTL_ASYNC,
  892.                 com_handle);
  893. #endif
  894.  
  895.    if ( com_error )
  896.       ShowError( com_error );
  897.  
  898. } /*nssendbrk*/
  899.  
  900. /*--------------------------------------------------------------------*/
  901. /*    n c l o s e l i n e                                             */
  902. /*                                                                    */
  903. /*    Close the serial port down                                      */
  904. /*--------------------------------------------------------------------*/
  905.  
  906. void ncloseline(void)
  907. {
  908.    APIRET rc;
  909.    USHORT com_error;
  910.  
  911. #ifdef __OS2__
  912.    ULONG ParmLengthInOut;
  913.    ULONG DataLengthInOut;
  914. #endif
  915.  
  916.  
  917.    if ( ! portActive )
  918.    {
  919.       printmsg(0,"ncloseline: Internal error, port already closed");
  920.       return;
  921.    }
  922.  
  923.    portActive = FALSE; /* flag port closed for error handler  */
  924.    hangupNeeded = FALSE;  /* Don't fiddle with port any more  */
  925.  
  926. /*--------------------------------------------------------------------*/
  927. /*                             Lower DTR                              */
  928. /*--------------------------------------------------------------------*/
  929.  
  930.    com_signals.fbModemOn  = 0x00;
  931.    com_signals.fbModemOff = DTR_OFF;
  932.  
  933.    printmsg(2,"Restoring port attributes and speed %lu",
  934.                (unsigned long) saveSpeed );
  935.  
  936. #ifdef __OS2__
  937.  
  938.    ParmLengthInOut = sizeof(com_signals);
  939.    DataLengthInOut = sizeof(com_error);
  940.  
  941.    rc = DosDevIOCtl( com_handle,
  942.                      IOCTL_ASYNC,
  943.                      ASYNC_SETMODEMCTRL,
  944.                      (PVOID)&com_signals,
  945.                      sizeof(com_signals),
  946.                      &ParmLengthInOut,
  947.                      (PVOID) &com_error,
  948.                      sizeof(com_error),
  949.                      &DataLengthInOut);
  950.  
  951. #else
  952.  
  953.    rc = DosDevIOCtl( &com_error,
  954.                      &com_signals,
  955.                      ASYNC_SETMODEMCTRL,
  956.                      IOCTL_ASYNC,
  957.                      com_handle);
  958.  
  959. #endif
  960.  
  961.    if ( rc )
  962.       printOS2error( "ASYNC_SETMODEMCTRL", rc );
  963.    else if ( com_error )
  964.       ShowError( com_error );
  965.  
  966. #ifdef __OS2__
  967.  
  968.    ParmLengthInOut = sizeof(save_com_attrib);
  969.    DataLengthInOut = 0;
  970.    rc = DosDevIOCtl( com_handle,
  971.                      IOCTL_ASYNC,
  972.                      ASYNC_SETLINECTRL,
  973.                      (PVOID) &save_com_attrib,
  974.                      sizeof(save_com_attrib),
  975.                      &ParmLengthInOut,
  976.                      NULL,
  977.                      0L,
  978.                      &DataLengthInOut);
  979.  
  980. #else
  981.  
  982.    rc = DosDevIOCtl( FAR_NULL,
  983.                      &save_com_attrib,
  984.                      ASYNC_SETLINECTRL,
  985.                      IOCTL_ASYNC,
  986.                      com_handle);
  987. #endif
  988.  
  989.    if (rc)
  990.       printOS2error( "ASYNC_SETLINECTRL", rc );
  991.  
  992. /*--------------------------------------------------------------------*/
  993. /*               Restore original modem DCB information               */
  994. /*--------------------------------------------------------------------*/
  995.  
  996. #ifdef __OS2__
  997.  
  998.    ParmLengthInOut = sizeof(save_com_dcbinfo);
  999.    DataLengthInOut = 0;
  1000.    rc = DosDevIOCtl( com_handle,
  1001.                      IOCTL_ASYNC,
  1002.                      ASYNC_SETDCBINFO,
  1003.                      (PVOID) &save_com_dcbinfo,
  1004.                      sizeof(save_com_dcbinfo),
  1005.                      &ParmLengthInOut,
  1006.                      NULL,
  1007.                      0L,
  1008.                      &DataLengthInOut);
  1009.  
  1010. #else
  1011.  
  1012.    rc = DosDevIOCtl( FAR_NULL,
  1013.                      &save_com_dcbinfo,
  1014.                      ASYNC_SETDCBINFO,
  1015.                      IOCTL_ASYNC,
  1016.                      com_handle);
  1017.  
  1018. #endif
  1019.  
  1020.    if ( rc )
  1021.       printOS2error( "ASYNC_SETDCBINFO", rc );
  1022.  
  1023. /*--------------------------------------------------------------------*/
  1024. /*                    Restore original port speed                     */
  1025. /*--------------------------------------------------------------------*/
  1026.  
  1027.    SIOSpeed( saveSpeed );
  1028.  
  1029. /*--------------------------------------------------------------------*/
  1030. /*                      Actually close the port                       */
  1031. /*--------------------------------------------------------------------*/
  1032.  
  1033.    rc = DosClose( com_handle );
  1034.  
  1035.    if ( rc != 0 )
  1036.       printOS2error( "DosClose", rc );
  1037.  
  1038. /*--------------------------------------------------------------------*/
  1039. /*                   Stop logging the data to disk                    */
  1040. /*--------------------------------------------------------------------*/
  1041.  
  1042.    traceStop();
  1043.  
  1044. } /* ncloseline */
  1045.  
  1046. /*--------------------------------------------------------------------*/
  1047. /*    n h a n g u p                                                   */
  1048. /*                                                                    */
  1049. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  1050. /*    many compatibles.                                               */
  1051. /*--------------------------------------------------------------------*/
  1052.  
  1053. void nhangup( void )
  1054. {
  1055.  
  1056. #ifdef __OS2__
  1057.    ULONG ParmLengthInOut;
  1058.    ULONG DataLengthInOut;
  1059. #endif
  1060.  
  1061.    USHORT com_error;
  1062.    APIRET rc;
  1063.  
  1064.    if (!hangupNeeded)
  1065.       return;
  1066.  
  1067.    hangupNeeded = FALSE;
  1068.  
  1069. /*--------------------------------------------------------------------*/
  1070. /*                              Drop DTR                              */
  1071. /*--------------------------------------------------------------------*/
  1072.  
  1073.    com_signals.fbModemOn  = 0x00;
  1074.    com_signals.fbModemOff = DTR_OFF;
  1075.  
  1076. #ifdef __OS2__
  1077.  
  1078.    ParmLengthInOut = sizeof(com_signals);
  1079.    DataLengthInOut = sizeof(com_error);
  1080.  
  1081.    rc = DosDevIOCtl( com_handle,
  1082.                      IOCTL_ASYNC,
  1083.                      ASYNC_SETMODEMCTRL,
  1084.                      (PVOID)&com_signals,
  1085.                      sizeof(com_signals),
  1086.                      &ParmLengthInOut,
  1087.                      (PVOID) &com_error,
  1088.                      sizeof(com_error),
  1089.                      &DataLengthInOut);
  1090.  
  1091. #else
  1092.  
  1093.    rc = DosDevIOCtl( &com_error,
  1094.                      &com_signals,
  1095.                      ASYNC_SETMODEMCTRL,
  1096.                      IOCTL_ASYNC,
  1097.                      com_handle);
  1098.  
  1099. #endif
  1100.  
  1101.    if ( rc )
  1102.    {
  1103.       printmsg(0,"hangup: Unable to lower DTR for comm port");
  1104.       printOS2error( "ASYNC_SETMODEMCTRL", rc );
  1105.    } /*if */
  1106.    else if ( com_error )
  1107.          ShowError( com_error );
  1108.  
  1109. /*--------------------------------------------------------------------*/
  1110. /*                  Wait for the telephone to hangup                  */
  1111. /*--------------------------------------------------------------------*/
  1112.  
  1113.    printmsg(3,"hangup: Dropped DTR");
  1114.    carrierDetect = FALSE;  /* Modem is not connected                 */
  1115.    ddelay(500);            /* Really only need 250 milliseconds        */
  1116.  
  1117. /*--------------------------------------------------------------------*/
  1118. /*                          Bring DTR back up                         */
  1119. /*--------------------------------------------------------------------*/
  1120.  
  1121.    com_signals.fbModemOn = DTR_ON;
  1122.    com_signals.fbModemOff = 0xff;
  1123.  
  1124. #ifdef __OS2__
  1125.  
  1126.    ParmLengthInOut = sizeof(com_signals);
  1127.    DataLengthInOut = sizeof(com_error);
  1128.  
  1129.    rc = DosDevIOCtl( com_handle,
  1130.                      IOCTL_ASYNC, ASYNC_SETMODEMCTRL,
  1131.                      (PVOID)&com_signals,
  1132.                      sizeof(com_signals),
  1133.                      &ParmLengthInOut,
  1134.                      (PVOID) &com_error,
  1135.                      sizeof(com_error),
  1136.                      &DataLengthInOut);
  1137.  
  1138. #else
  1139.  
  1140.    rc = DosDevIOCtl( &com_error,
  1141.                      &com_signals,
  1142.                      ASYNC_SETMODEMCTRL,
  1143.                      IOCTL_ASYNC,
  1144.                      com_handle);
  1145.  
  1146. #endif
  1147.  
  1148.    if ( rc )
  1149.    {
  1150.       printmsg(0,"hangup: Unable to raise DTR for comm port");
  1151.       printOS2error( "ASYNC_SETMODEMCTRL", rc );
  1152.    } /*if */
  1153.    else if ( com_error )
  1154.       ShowError( com_error );
  1155.  
  1156.    ddelay(2000);           /* Now wait for the poor thing to recover   */
  1157.  
  1158. } /* nhangup */
  1159.  
  1160. /*--------------------------------------------------------------------*/
  1161. /*    n S I O S p e e d                                               */
  1162. /*                                                                    */
  1163. /*    Re-specify the speed of an opened serial port                   */
  1164. /*                                                                    */
  1165. /*    Dropped the DTR off/on calls because this makes a Hayes drop    */
  1166. /*    the line if configured properly, and we don't want the modem    */
  1167. /*    to drop the phone on the floor if we are performing             */
  1168. /*    autobaud.                                                       */
  1169. /*                                                                    */
  1170. /*    (Configured properly = standard method of making a Hayes        */
  1171. /*    hang up the telephone, especially when you can't get it into    */
  1172. /*    command state because it is at the wrong speed or whatever.)    */
  1173. /*--------------------------------------------------------------------*/
  1174.  
  1175. void nSIOSpeed(BPS portSpeed)
  1176. {
  1177.    APIRET rc;
  1178.  
  1179. #ifdef __OS2__
  1180.  
  1181.    ULONG ParmLengthInOut;
  1182.    ULONG DataLengthInOut;
  1183.  
  1184.    struct
  1185.    {
  1186.       ULONG portSpeed;  /* this structure is needed to set the extended  */
  1187.       BYTE fraction;    /* port speed using function 41h DosDevIOCtl  */
  1188.    } comPortSpeed;
  1189.  
  1190. #else
  1191.  
  1192.    USHORT speed = (USHORT) portSpeed;
  1193.  
  1194. #endif
  1195.  
  1196. #ifdef UDEBUG
  1197.    printmsg(15,"SIOSpeed: Setting port speed to %lu",
  1198.                (unsigned long) portSpeed);
  1199. #endif
  1200.  
  1201. #ifdef __OS2__
  1202.  
  1203.    comPortSpeed.portSpeed = portSpeed;
  1204.    comPortSpeed.fraction = 0;
  1205.    ParmLengthInOut = sizeof(comPortSpeed);
  1206.    DataLengthInOut = 0;
  1207.  
  1208.    rc = DosDevIOCtl( com_handle,
  1209.                     IOCTL_ASYNC,
  1210.                     ASYNC_SETBAUDRATE,
  1211.                     (PVOID) &comPortSpeed,
  1212.                     sizeof(comPortSpeed),
  1213.                     &ParmLengthInOut,
  1214.                     NULL,
  1215.                     0L,
  1216.                     &DataLengthInOut);
  1217.  
  1218. #else
  1219.    rc = DosDevIOCtl( FAR_NULL,
  1220.                      &speed,
  1221.                      ASYNC_SETBAUDRATE,
  1222.                      IOCTL_ASYNC,
  1223.                      com_handle);
  1224. #endif
  1225.  
  1226.    if (rc)
  1227.    {
  1228.       printmsg(0,"SIOSPeed: Unable to set port speed for port to %lu",
  1229.                portSpeed);
  1230.       printOS2error( "ASYNC_SETBAUDRATE", rc );
  1231.       panic();
  1232.    } /*if */
  1233.  
  1234.    currentSpeed = (unsigned short) portSpeed;
  1235.  
  1236. } /* nSIOSpeed */
  1237.  
  1238. /*--------------------------------------------------------------------*/
  1239. /*    n f l o w c o n t r o l                                         */
  1240. /*                                                                    */
  1241. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  1242. /*--------------------------------------------------------------------*/
  1243.  
  1244. void nflowcontrol( boolean flow )
  1245. {
  1246.    APIRET rc;
  1247.  
  1248. #ifdef __OS2__
  1249.    ULONG ParmLengthInOut;
  1250.    ULONG DataLengthInOut;
  1251. #endif
  1252.  
  1253.    if ( flow )
  1254.        com_dcbinfo.fbFlowReplace = (char)
  1255.             (com_dcbinfo.fbFlowReplace |
  1256.             (MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE));
  1257.    else
  1258.       com_dcbinfo.fbFlowReplace = (char)
  1259.             (com_dcbinfo.fbFlowReplace &
  1260.             (0xff - MODE_AUTO_TRANSMIT - MODE_AUTO_RECEIVE));
  1261.  
  1262. #ifdef __OS2__
  1263.  
  1264.    ParmLengthInOut = sizeof(com_dcbinfo);
  1265.    DataLengthInOut = 0;
  1266.    rc = DosDevIOCtl( com_handle,
  1267.                      IOCTL_ASYNC,
  1268.                      ASYNC_SETDCBINFO,
  1269.                      (PVOID) &com_dcbinfo,
  1270.                      sizeof(com_dcbinfo),
  1271.                      &ParmLengthInOut,
  1272.                      NULL,
  1273.                      0L,
  1274.                      &DataLengthInOut);
  1275.  
  1276. #else
  1277.  
  1278.    rc = DosDevIOCtl( FAR_NULL,
  1279.                      &com_dcbinfo,
  1280.                      ASYNC_SETDCBINFO,
  1281.                      IOCTL_ASYNC,
  1282.                      com_handle);
  1283.  
  1284. #endif
  1285.  
  1286.    if ( rc )
  1287.    {
  1288.       printOS2error( "ASYNC_SETDCBINFO", rc );
  1289.       panic();
  1290.    } /*if */
  1291.  
  1292. } /* nflowcontrol */
  1293.  
  1294. /*--------------------------------------------------------------------*/
  1295. /*    n G e t S p e e d                                               */
  1296. /*                                                                    */
  1297. /*    Report current speed of communications connection               */
  1298. /*--------------------------------------------------------------------*/
  1299.  
  1300. BPS nGetSpeed( void )
  1301. {
  1302.    APIRET rc;
  1303.  
  1304. #ifdef __OS2__
  1305.  
  1306.    ULONG ParmLengthInOut;
  1307.    ULONG DataLengthInOut;
  1308.  
  1309.    struct
  1310.    {
  1311.       ULONG portSpeed;  /* this structure is needed to set the extended  */
  1312.       BYTE fraction;    /* port speed using function 41h DosDevIOCtl  */
  1313.    } comPortSpeed;
  1314.  
  1315.    BPS speed;
  1316.  
  1317. #else
  1318.  
  1319.    USHORT speed;
  1320.  
  1321. #endif
  1322.  
  1323. /*--------------------------------------------------------------------*/
  1324. /*                      Save original port speed                      */
  1325. /*--------------------------------------------------------------------*/
  1326.  
  1327. #ifdef __OS2__
  1328.  
  1329. /*--------------------------------------------------------------------*/
  1330. /*       OS/2 2.x Format of call for DosDevIOCtl accepts portSpeed    */
  1331. /*       rates greater than 19200.                                    */
  1332. /*--------------------------------------------------------------------*/
  1333.  
  1334.    DataLengthInOut = sizeof(comPortSpeed);
  1335.    ParmLengthInOut = 0;
  1336.  
  1337.    rc = DosDevIOCtl( com_handle,
  1338.                     IOCTL_ASYNC,
  1339.                     ASYNC_GETBAUDRATE,
  1340.                     NULL,
  1341.                     0L,
  1342.                     &ParmLengthInOut,
  1343.                     (PVOID) &comPortSpeed,
  1344.                     sizeof(comPortSpeed),
  1345.                     &DataLengthInOut);
  1346.  
  1347.    speed = comPortSpeed.portSpeed;
  1348.  
  1349. #else
  1350.    rc = DosDevIOCtl( &speed,
  1351.                      FAR_NULL,
  1352.                      ASYNC_GETBAUDRATE,
  1353.                      IOCTL_ASYNC,
  1354.                      com_handle);
  1355.  
  1356. #endif
  1357.  
  1358.    if (rc)
  1359.    {
  1360.       printOS2error( "ASYNC_GETBAUDRATE", rc );
  1361.       panic();
  1362.    } /*if */
  1363.  
  1364. /*--------------------------------------------------------------------*/
  1365. /*            Return speed of port to caller upon success             */
  1366. /*--------------------------------------------------------------------*/
  1367.  
  1368.    return speed;
  1369.  
  1370. } /* nGetSpeed */
  1371.  
  1372. /*--------------------------------------------------------------------*/
  1373. /*   n C D                                                            */
  1374. /*                                                                    */
  1375. /*   Return status of carrier detect                                  */
  1376. /*--------------------------------------------------------------------*/
  1377.  
  1378. boolean nCD( void )
  1379. {
  1380.    boolean previousCarrierDetect = carrierDetect;
  1381.    APIRET rc;
  1382.  
  1383. #ifdef __OS2__
  1384.    ULONG ParmLengthInOut;
  1385.    ULONG DataLengthInOut;
  1386. #endif
  1387.  
  1388.    BYTE status;
  1389.    static BYTE oldstatus = (BYTE) 0xDEAD;
  1390.  
  1391. #ifdef __OS2__
  1392.    ParmLengthInOut = 0;
  1393.    DataLengthInOut = sizeof(status);
  1394.    rc = DosDevIOCtl( com_handle,
  1395.                      IOCTL_ASYNC,
  1396.                      ASYNC_GETMODEMINPUT,
  1397.                      NULL,
  1398.                      0L,
  1399.                      &ParmLengthInOut,
  1400.                      (PVOID) &status,
  1401.                      sizeof(status),
  1402.                      &DataLengthInOut);
  1403. #else
  1404.  
  1405.    rc = DosDevIOCtl( &status,
  1406.                      0L,
  1407.                      ASYNC_GETMODEMINPUT,
  1408.                      IOCTL_ASYNC,
  1409.                      com_handle );
  1410.  
  1411. #endif
  1412.  
  1413.    if ( rc )
  1414.    {
  1415.       printOS2error( "ASYNC_GETMODEMINPUT", rc );
  1416.    } /*if */
  1417.  
  1418.    if ( status != oldstatus )
  1419.    {
  1420.       ShowModem( status );
  1421.       oldstatus = status;
  1422.    }
  1423.  
  1424. /*--------------------------------------------------------------------*/
  1425. /*    If we previously had carrier detect but have lost it, we        */
  1426. /*    report it was lost.  If we do not yet have carrier detect,      */
  1427. /*    we return success because we may not have connected yet.        */
  1428. /*--------------------------------------------------------------------*/
  1429.  
  1430.    carrierDetect = status && DCD_ON;
  1431.  
  1432.    if (previousCarrierDetect)
  1433.       return carrierDetect;
  1434.    else
  1435.       return (status && DSR_ON);
  1436.  
  1437. } /* nCD */
  1438.  
  1439. /*--------------------------------------------------------------------*/
  1440. /*    S h o w M o d e m                                               */
  1441. /*                                                                    */
  1442. /*    Report current modem status                                     */
  1443. /*--------------------------------------------------------------------*/
  1444.  
  1445. #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
  1446.  
  1447. static void ShowModem( const BYTE status )
  1448. {
  1449.    if ( debuglevel < 4 )
  1450.       return;
  1451.  
  1452.    printmsg(0, "ShowModem: %#02x%s%s%s%s",
  1453.       (int) status,
  1454.       mannounce(DCD_ON,   status, "  Carrier Detect"),
  1455.       mannounce(RI_ON,    status, "  Ring Indicator"),
  1456.       mannounce(DSR_ON,   status, "  Data Set Ready"),
  1457.       mannounce(CTS_ON,   status, "  Clear to Send"));
  1458.  
  1459. } /* ShowModem */
  1460.  
  1461. /*--------------------------------------------------------------------*/
  1462. /*    S h o w E r r o r                                               */
  1463. /*                                                                    */
  1464. /*    Report modem error bits in English (more or less)               */
  1465. /*--------------------------------------------------------------------*/
  1466.  
  1467. static void ShowError( const USHORT status )
  1468. {
  1469.    printmsg(2, "Port Error: %#04x%s%s%s%s",
  1470.       (int) status,
  1471.       mannounce(RX_QUE_OVERRUN,      status, "  Queue Overrrun"),
  1472.       mannounce(RX_HARDWARE_OVERRUN, status, "  Hardware Overrun"),
  1473.       mannounce(PARITY_ERROR,        status, "  Parity Error"),
  1474.       mannounce(FRAMING_ERROR,       status, "  Framing Error"));
  1475.  
  1476. } /* ShowError */
  1477.  
  1478. /*--------------------------------------------------------------------*/
  1479. /*          n G e t C o m H a n d l e                                 */
  1480. /*                                                                    */
  1481. /*          Return handle to open port                                */
  1482. /*--------------------------------------------------------------------*/
  1483.  
  1484. int nGetComHandle( void )
  1485. {
  1486.  
  1487.    return (int) com_handle;
  1488.  
  1489. }  /* nGetComHandle */
  1490.