home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / os2tools / bnklysrc / async.c next >
Encoding:
C/C++ Source or Header  |  1989-07-08  |  10.2 KB  |  511 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <conio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #define INCL_DOS
  7. #define INCL_DOSDEVICES
  8. #include <os2.h>
  9. #include "bink.h"
  10. #include "com.h"
  11.  
  12. /*--------------------------------------------------------*
  13.  * This file contains the operating system specific       *
  14.  * serial communications routines for OS/2.               *
  15.  *                                                          *
  16.  * (C) Copyright Peter Fitzsimmons Sun    04-16-1989          *
  17.  *                                                          *
  18.  * Add-ins for BinkleyTerm on Sat  05-06-1989              *
  19.  *--------------------------------------------------------*/
  20.  
  21. #define DEBUG
  22.  
  23.  
  24. #ifndef OS_2
  25. #error This Module For OS/2
  26. #else
  27.  
  28. static void zap_zbuf(void);
  29.  
  30. /* Private data */
  31. static HFILE hfComHandle = -1;        /* handle from DosOpen() */
  32.  
  33. /* transmitter stuff : */
  34. #define TSIZE 2048
  35. static ULONG WriteSem = 0;
  36.  
  37. /* receiver stuff : */
  38. #define RSIZE 1024
  39. static unsigned char rbuf[RSIZE];
  40. static int rpos = 0;
  41. static USHORT Rbytes = 0;
  42.  
  43. #ifdef DEBUG
  44.  
  45. #define debug_msg(m,c)    printf(m,c)
  46. #define IOCtl(func, data, parm)  _ioctl(#func, func, data, parm)
  47.  
  48. static int _ioctl(char *funcname, int func, void far * data, void far * parm)
  49. {
  50.     int i;
  51.  
  52.     if (i = DosDevIOCtl(data, parm, func, SERIAL, hfComHandle)) {
  53.     printf("ioctl(%s) err(%d)\n", funcname, i);
  54.     }
  55.     return (i);
  56. }
  57.  
  58. #else
  59. #define debug_msg(m,c)
  60. #define IOCtl(func, data, parm) DosDevIOCtl(data, parm, func, SERIAL, hfComHandle)
  61. #endif
  62.  
  63. static int com_getDCB(struct _DCBINFO * dcb);
  64. static int com_setDCB(struct _DCBINFO * dcb);
  65. static void com_kick(void);
  66.  
  67.  
  68. /* com_init() : Intialize communications port. Baud rate is preserved.
  69.  *              int port    : Hardware port (0 based) to init
  70.  *      -OR-    char *unc    : Full UNC \\networkId\modemId to init.
  71.  *
  72.  * if unc==NULL, port is used. if unc != NULL, unc is used
  73.  */
  74. int com_init(int port, char *unc)
  75. {
  76.     char str[10];
  77.     USHORT ActionTaken;         /* action: returned by OS/2 */
  78.     USHORT stat;
  79.     DCBINFO sDCB;
  80.  
  81.     cputs("\033[1;33mOS/2 Fossill emulator for Binkley Term by Peter Fitzsimmons 1:250/628\033[0m\r\n");
  82.     sprintf(str, "COM%d", port + 1);
  83.     if (!unc)
  84.     unc = str;
  85.     stat = DosOpen(unc, &hfComHandle, &ActionTaken, 0L, 0, 0x0001, 0x4012, 0L);
  86.     if (stat) {
  87.     hfComHandle = -1;
  88.     printf("com_init() : DosOpen() error %d on '%s'\n", stat, unc);
  89.     return (FALSE);
  90.     }
  91.     DosSemClear(&WriteSem);
  92.     com_XON_disable();
  93.  
  94.  
  95.     com_getDCB(&sDCB);
  96.     sDCB.bFlags1 = 0x01;        /* raise DTR */
  97.     sDCB.bFlags2 = 0x40;        /* enable RTS, flow control off,
  98.                      * error replacement off, null
  99.                      * stripping off, break replacement
  100.                      * off */
  101.     sDCB.bFlags3 = 0x07;                /* set write timeout strategies to
  102.                      * INFINITE, read timeout to NO
  103.                      * WAIT */
  104.     sDCB.usReadTimeout = 100;
  105.     sDCB.usWriteTimeout = 10;
  106.     com_setDCB(&sDCB);
  107.  
  108.     return (!stat);
  109. }
  110.  
  111. void com_DTR_on(void)
  112. {
  113.     DCBINFO sDCB;
  114.  
  115.     com_getDCB(&sDCB);
  116.     sDCB.bFlags1 |= 0x01;        /* raise DTR */
  117.     com_setDCB(&sDCB);
  118. }
  119.  
  120. void com_DTR_off(void)
  121. {
  122.     DCBINFO sDCB;
  123.  
  124.     com_getDCB(&sDCB);
  125.     sDCB.bFlags1 &= ~0x01;        /* lower DTR */
  126.     com_setDCB(&sDCB);
  127. }
  128.  
  129. /* close communications channel. Baud rate is preserved. */
  130. int com_fini(void)
  131. {
  132.     int stat;
  133.  
  134.     com_wait();
  135.     com_clear_in();
  136.     com_clear_out();
  137.     if (stat = DosClose(hfComHandle)) {
  138.     hfComHandle = -1;
  139.     debug_msg("DosClose error %d\n", stat);
  140.     return (FALSE);
  141.     }
  142.     hfComHandle = -1;
  143. }
  144.  
  145.  
  146. long com_cur_baud(void)
  147. {
  148.     USHORT rate = 0;
  149.  
  150.     IOCtl(ASYNC_GETBAUDRATE, &rate, 0L);
  151.     return ((long) rate);
  152. }
  153.  
  154. /* com_set_baud() :
  155.  *
  156.  *    rate = 110..19200
  157.  *    parity = N, E, O, M, S (none,even, odd, mark, space)
  158.  *    databits = 5..8
  159.  *    stopbits = 1..2
  160.  *
  161.  */
  162.  
  163. int com_set_baud(long rate, char parity, int databits, int stopbits)
  164. {
  165.     int stat;
  166.     struct _LINECONTROL {
  167.     BYTE bDataBits;
  168.     BYTE bParity;
  169.     BYTE bStopBits;
  170.     BYTE fbTransBreak;
  171.     } lc;
  172.  
  173.     stat = IOCtl(ASYNC_SETBAUDRATE, 0L, &rate);
  174.     if (stat) {
  175.     return (FALSE);
  176.     }
  177.     lc.bDataBits = (BYTE) databits;
  178.     switch (stopbits) {
  179.     case 1:
  180.         lc.bStopBits = 0;
  181.         break;
  182.     case 2:
  183.         lc.bStopBits = 2;
  184.         break;
  185.     default:
  186.         if (databits == 5)
  187.         lc.bStopBits = 1;
  188.     }
  189.     lc.fbTransBreak = 0;
  190.     switch (toupper(parity)) {
  191.     case 'N':
  192.         lc.bParity = 0;
  193.         break;
  194.     case 'O':
  195.         lc.bParity = 1;
  196.         break;
  197.     case 'E':
  198.         lc.bParity = 2;
  199.         break;
  200.     case 'M':
  201.         lc.bParity = 3;
  202.         break;
  203.     case 'S':
  204.         lc.bParity = 4;
  205.         break;
  206.     default:
  207.         debug_msg("Bad parity '%c'\n", parity);
  208.         return (FALSE);
  209.     }
  210.     stat = IOCtl(ASYNC_SETLINECTRL, 0L, &lc);
  211.     if (stat) {
  212.     return (FALSE);
  213.     }
  214.     return (TRUE);
  215. }
  216.  
  217.  
  218.  
  219. static int com_getDCB(DCBINFO * dcb)
  220. {
  221.     int stat;
  222.  
  223.     stat = IOCtl(ASYNC_GETDCBINFO, dcb, 0L);
  224.     return (!stat);
  225. }
  226.  
  227. static int com_setDCB(DCBINFO * dcb)
  228. {
  229.     int stat;
  230.  
  231.     stat = IOCtl(ASYNC_SETDCBINFO, 0L, dcb);
  232.     return (!stat);
  233. }
  234.  
  235. void com_XON_disable(void)
  236. {
  237.     DCBINFO sDCB;
  238.  
  239.     if (com_getDCB(&sDCB)) {
  240.     sDCB.bFlags2 &= ~0x03;        /* disable auto Xmit and recv flow
  241.                      * control */
  242.     com_setDCB(&sDCB);
  243.     }
  244. }
  245.  
  246. void com_XON_enable(void)
  247. {
  248.     DCBINFO sDCB;
  249.  
  250.     if (com_getDCB(&sDCB)) {
  251.     sDCB.bFlags2 |= 0x03;        /* enable auto Xmit and recv flow
  252.                      * control */
  253.     com_setDCB(&sDCB);
  254.     }
  255. }
  256.  
  257.  
  258.  
  259. /* nuke receive buffer */
  260. void com_clear_in(void)
  261. {
  262.     int stat;
  263.     char FlushParm = 0;         /* param to flush IOCTL function */
  264.  
  265.     Rbytes = rpos = 0;
  266.     stat = DosDevIOCtl(0L, &FlushParm, FLUSHINPUT, GENERIC, hfComHandle);
  267.     if (stat) {
  268.     debug_msg("FLUSHINPUT err %d\n", stat);
  269.     }
  270. }
  271.  
  272.  
  273. /* com_getchar() : return negative value if error */
  274. int com_getchar(void)
  275. {
  276.     int stat;
  277.  
  278.     if (rpos == Rbytes) {
  279.     rpos = 0;
  280.     do {
  281.         stat = DosRead(hfComHandle, rbuf, RSIZE, &Rbytes);
  282.     } while (!stat && !Rbytes);
  283.     if (stat || !Rbytes) {
  284.         debug_msg("DosRead() error %d\n", stat);
  285.         return (-1);
  286.     }
  287.     }
  288.     return ((int) rbuf[rpos++]);
  289. }
  290.  
  291. /*non destructive read ahead; no wait */
  292. int com_peek(void)
  293. {
  294.     int c;
  295.  
  296.     if (!com_char_avail())
  297.     c = -1;
  298.     else {
  299.     c = com_getchar();
  300.     rpos--;
  301.     }
  302.     return (c);
  303. }
  304.  
  305. /* return number of chars in input buffer */
  306. int com_char_avail(void)
  307. {
  308.     RXQUEUE q;
  309.  
  310.     if (rpos != Rbytes)
  311.     return (TRUE);
  312.     if (!IOCtl(ASYNC_GETINQUECOUNT, &q, 0L))
  313.     return ((int) q.cbChars);
  314.     else
  315.     return (FALSE);
  316. }
  317.  
  318.  
  319. /* return non 0 value if carrier detected */
  320. bool com_online(void)
  321. {
  322.     int stat;
  323.     BYTE msr;
  324.  
  325.     stat = IOCtl(ASYNC_GETMODEMINPUT, &msr, 0L);
  326.     if (stat) {
  327.     return (FALSE);
  328.     }
  329.     return (msr & RLSD);
  330. }
  331.  
  332.  
  333. /* com_break() : start break if on==TRUE, stop break if on==FALSE */
  334.  
  335. void com_break(int on)
  336. {
  337.     int cmd;
  338.     USHORT comerr;
  339.  
  340.     cmd = (on) ? ASYNC_SETBREAKON : ASYNC_SETBREAKOFF;
  341.     IOCtl(cmd, &comerr, 0L);
  342. }
  343.  
  344. /* com_out_empty() : return TRUE if output buffer is empty */
  345. bool com_out_empty(void)
  346. {
  347.     int stat;
  348.     RXQUEUE q;
  349.  
  350.     if (!DosSemWait(&WriteSem, 0L)) {
  351.     stat = IOCtl(ASYNC_GETOUTQUECOUNT, &q, 0L);
  352.     if (stat)
  353.         return (TRUE);        // don't want someone waiting to get stuck if general error
  354.         return ((bool) (q.cbChars == 0));
  355.     }
  356.     else {
  357.     return (FALSE);
  358.     }
  359. }
  360.  
  361.  
  362. /* nuke transmit buffer */
  363. void com_clear_out(void)
  364. {
  365.     char FlushParm = 0;         /* param to flush IOCTL function */
  366.     int stat;
  367.  
  368.     zap_zbuf();
  369.     stat = DosDevIOCtl(0L, &FlushParm, FLUSHOUTPUT, GENERIC, hfComHandle);
  370.     if (stat) {
  371.     debug_msg("FLUSHOUTPUT err %d\n", stat);
  372.     }
  373.     DosSemClear(&WriteSem);
  374. }
  375.  
  376. /* com_putc_now() : disregard any buffering and send a byte now damnit! */
  377. /* this function should be called only during emergencies...like when
  378.  * trying to cancel a file transfer
  379.  */
  380. int com_putc_now(int c)
  381. {
  382.     return (!IOCtl(ASYNC_TRANSMITIMM, 0L, &c));
  383. }
  384.  
  385. /* com_putc() : output to com port */
  386. /* This function is very slow..where possile, write to com port in blocks
  387.  * using com_write() instead...especially above 2400 bps
  388.  */
  389. void com_putc(int c)
  390. {
  391.     static USHORT bytes;
  392.     int stat;
  393.  
  394.     DosSemWait(&WriteSem, -1L);
  395.  
  396.     /*
  397.      * DosWriteAsync() didn't work here. After being idle for a while,
  398.      * calling this function repeatedly to send a string (like "ATZ") would
  399.      * somehow loose the first character. I have speant hours trying to
  400.      * debug this, and Microsoft was no help. Basically, os/2's handling of
  401.      * output buffering sucks for the com ports. I give up...(for now).
  402.      * NOTE that this appeared to only happen when writting one byte; that
  403.      * is why com_write() still uses DosWriteAsync().
  404.      */
  405.     if (stat = DosWrite(hfComHandle, &c, 1, &bytes))
  406.     debug_msg("DosWrite() err %d\n", stat);
  407. }
  408.  
  409. /* com_write() : buffered block write */
  410. void com_write(char *buf, int num)
  411. {
  412.     static USHORT err, bytes;
  413.     static char tbuf[TSIZE];
  414.     int stat, pos = 0;
  415.  
  416.     DosSemRequest(&WriteSem, -1L);    /* if sem set, wait. If clear, set. */
  417.     while (num - pos > TSIZE) {
  418.     if (stat = DosWrite(hfComHandle, buf + pos, TSIZE, &bytes))
  419.         debug_msg("DosWrite() err %d\n", stat);
  420.     pos += bytes;
  421.     }
  422.     memcpy(tbuf, buf + pos, num - pos);
  423.     DosWriteAsync(hfComHandle, &WriteSem, &err, tbuf, num - pos, &bytes);
  424. }
  425.  
  426. /* wait for output buffer to empty */
  427. void com_wait(void)
  428. {
  429.     DosSemWait(&WriteSem, -1L);
  430.     while (!com_out_empty())
  431.     DosSleep(0L);
  432. }
  433.  
  434. #ifdef BINKLEY
  435. /* Binkley specifics : */
  436.  
  437. extern unsigned int baud;
  438. extern unsigned int comm_bits;
  439. extern unsigned int parity;
  440. extern unsigned int stop_bits;
  441. extern struct baud_str btypes[];
  442.  
  443. void MDM_ENABLE(int ignore)
  444. {
  445.     long rate;
  446.     char _parity;
  447.     int databits;
  448.     int stopbits;
  449.  
  450.     ignore;             /* keep /W3 happy */
  451.     com_clear_out();
  452.     com_clear_in();
  453.     rate = atol(btypes[baud].str);
  454.     databits = 7 + (comm_bits == BITS_8);
  455.     stopbits = 1 + (stop_bits == STOP_2);
  456.     switch (parity) {
  457.     case NO_PARITY:
  458.         _parity = 'N';
  459.         break;
  460.     case ODD_PARITY:
  461.         _parity = 'O';
  462.         break;
  463.     case EVEN_PARITY:
  464.         _parity = 'E';
  465.         break;
  466.     }
  467.     com_set_baud(rate, _parity, databits, stopbits);
  468. }
  469.  
  470. void MDM_DISABLE(void)
  471. {
  472.     if (hfComHandle == -1)
  473.     return;
  474.     com_clear_out();
  475.     com_clear_in();
  476.     com_fini();
  477. }
  478.  
  479. /* zsend.c uses BUFFER_BYTE and UNBUFFER_BYTES...good idea. */
  480. static unsigned char zTxBuf[TSIZE];
  481. static int zpos = 0;
  482. void BUFFER_BYTE(unsigned char ch)
  483. {
  484.     if( zpos == TSIZE )
  485.         UNBUFFER_BYTES();
  486.     zTxBuf[zpos++]    = ch;
  487. }
  488.  
  489. void UNBUFFER_BYTES(void)
  490. {
  491.     com_write(zTxBuf, zpos);
  492.     zpos = 0;
  493. }
  494.  
  495. static void zap_zbuf(void)
  496. {
  497.     zpos = 0;
  498. }
  499.  
  500. int Cominit(int port)
  501. {
  502.     if (hfComHandle != -1)
  503.     com_fini();
  504.     if (com_init(port, NULL))
  505.     return (0x1954);
  506.     else
  507.     return (0);
  508. }
  509. #endif /* BINKLEY */
  510. #endif /* OS_2 */
  511.