home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 307_01 / rs232.c < prev    next >
C/C++ Source or Header  |  1990-03-20  |  6KB  |  284 lines

  1. /*
  2. HEADER:     ;
  3. TITLE:        INT 0x14 glue routines for COMX driver;
  4. VERSION:    1.0;
  5.  
  6. DESCRIPTION:    "Binding routines to access COMX device driver through
  7.         the BIOS emulation entry point";
  8.  
  9. KEYWORDS:    Serial communications;
  10. SYSTEM:     MS-DOS v2 or later;
  11. FILENAME:    RS232.C;
  12.  
  13. SEE-ALSO:    COMX.C, RS232.H;
  14. AUTHORS:    Hugh Daschbach;
  15. COMPILERS:    Microsoft v5.0,v5.1;
  16. */
  17. /*----------------------------------------------------------------------*/
  18. /* rs232.c: int 14h (RS232) glue routines for COMX driver
  19.  */
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <dos.h>
  23. #include "rs232.h"
  24. #include "comx.h"
  25.  
  26. static int speed_tbl[] = {
  27.     11, 15, 30, 60, 120, 240, 480, 960, 1920, 3840
  28. };
  29. /*----------------------------------------------------------------------*/
  30. /*             Low level RS232 glue routines            */
  31. /*----------------------------------------------------------------------*/
  32.  
  33. /*
  34.  * Initialize channel.
  35.  */
  36. void rs232_init(int chan, long speed, char parity, int stopbit, int wordlen)
  37. {
  38.     union REGS    ir, or;
  39.     int   sti;                /* speed table index        */
  40.  
  41.     ir.h.al = (char) ((stopbit > 1 ? 4 : 0 ) + (wordlen == 8 ? 3 : 2));
  42.     if ((parity = tolower(parity)) == 'e')
  43.     ir.h.al += 0x18;
  44.     else if (parity == 'o')
  45.     ir.h.al += 0x08;
  46.     speed /= 10;
  47.     for (sti = 0; sti < num_entries(speed_tbl); sti++)
  48.     if ((int) speed == speed_tbl[sti])
  49.         break;
  50.     ir.h.al += (char) (sti << 5);
  51.     ir.h.ah = INIT_232;
  52.     ir.x.dx = chan;
  53.     int86(0x14, &ir, &or);
  54.     if (sti > 8)
  55.     {
  56.     ir.h.ah = SETSPEED_232;
  57.     ir.x.cx = sti;
  58.     int86(0x14, &ir, &or);
  59.     }
  60. }
  61.  
  62. /*
  63.  * Put a single character.  Return value less than zero indicates character
  64.  * not tramitted because buffer was full.
  65.  */
  66. int  rs232_putc(int chan, int c)
  67. {
  68.     union REGS    ir, or;
  69.  
  70.     ir.h.ah = PUTC_232;
  71.     ir.h.al = (char) c;
  72.     ir.x.dx = chan;
  73.     int86(0x14, &ir, &or);
  74.     return(or.x.ax);
  75. }
  76.  
  77. /*
  78.  * Get a single character.  Return character in low byte, line status register
  79.  * in high byte.  Returned value less than zero indicates no data available.
  80.  */
  81. int  rs232_getc(chan)
  82. {
  83.     union REGS    ir, or;
  84.  
  85.     ir.h.ah = GETC_232;
  86.     ir.x.dx = chan;
  87.     int86(0x14, &ir, &or);
  88.     return(or.x.ax);
  89. }
  90.  
  91. /*
  92.  * Get status.    The first call after rs232_read() indicates an error will
  93.  * return the status at the time of the error, otherwise it returns line
  94.  * status in high byte, and modem status in low byte.
  95.  */
  96. int  rs232_status(int chan)
  97. {
  98.     union REGS    ir, or;
  99.  
  100.     ir.h.ah = STAT_232;
  101.     ir.x.dx = chan;
  102.     int86(0x14, &ir, &or);
  103.     return(or.x.ax);
  104. }
  105.  
  106. /*
  107.  * Write string.  Returns byte transfer count with bit 15 set if output
  108.  * buffer full.
  109.  */
  110. rs232_write(int chan, char *s, int n)
  111. {
  112.     union  REGS  ir, or;
  113.     struct SREGS sr;
  114.     char   far    *cfp;
  115.  
  116.     cfp = (char far *) s;
  117.     segread(&sr);
  118.     sr.es   = FP_SEG(cfp);
  119.     ir.h.ah = WRITE_232;
  120.     ir.x.bx = FP_OFF(cfp);
  121.     ir.x.cx = n;
  122.     ir.x.dx = chan;
  123.     int86(0x14, &ir, &or);
  124.     return(or.x.ax);
  125. }
  126.  
  127. /*
  128.  * Read string.  Returns count of bytes transfered without error.  If bit 15
  129.  * is set an error was encountered (overrun, parity error, framing error,
  130.  * or break) during reception.    rs232_status() will return the line status
  131.  * register at the time of the error.
  132.  */
  133. rs232_read(int chan, char *s, int n)
  134. {
  135.     union  REGS  ir, or;
  136.     struct SREGS sr;
  137.     char   far    *cfp;
  138.  
  139.     cfp = (char far *) s;
  140.     segread(&sr);
  141.     sr.es   = FP_SEG(cfp);
  142.     ir.h.ah = READ_232;
  143.     ir.x.bx = FP_OFF(cfp);
  144.     ir.x.cx = n;
  145.     ir.x.dx = chan;
  146.     int86(0x14, &ir, &or);
  147.     return(or.x.ax);
  148. }
  149.  
  150. /*
  151.  * Get character ready count.  Returns byte count of data in receive buffer.
  152.  */
  153. rs232_icount(int chan)
  154. {
  155.     union REGS    ir, or;
  156.  
  157.     ir.h.ah = ICOUNT_232;
  158.     ir.x.dx = chan;
  159.     int86(0x14, &ir, &or);
  160.     return(or.x.ax);
  161. }
  162.  
  163. /*
  164.  * Get output buffer available count.
  165.  */
  166. rs232_ocount(int chan)
  167. {
  168.     union REGS    ir, or;
  169.  
  170.     ir.h.ah = OCOUNT_232;
  171.     ir.x.dx = chan;
  172.     int86(0x14, &ir, &or);
  173.     return(or.x.ax);
  174. }
  175.  
  176. /*
  177.  * Set channel protocol.  Enables XON/XOFF processing for either input or
  178.  * output.
  179.  */
  180. void rs232_prot(int chan, int prot)
  181. {
  182.     union REGS ir, or;
  183.  
  184.     ir.h.ah = SETPROT_232;
  185.     ir.h.al = (char) prot;
  186.     ir.x.dx = chan;
  187.     int86(0x14, &ir, &or);
  188. }
  189.  
  190. /*
  191.  * Change line speed.
  192.  */
  193. void rs232_speed(int chan, long speed)
  194. {
  195.     union REGS ir, or;
  196.     int   sti;
  197.  
  198.     speed /= 10;
  199.     for (sti = 0; sti < num_entries(speed_tbl); sti++)
  200.     if ((int) speed == speed_tbl[sti])
  201.         break;
  202.     ir.h.ah = SETSPEED_232;
  203.     ir.x.cx = (char) sti;
  204.     ir.x.dx = chan;
  205.     int86(0x14, &ir, &or);
  206.     if (or.h.ah & 0x80)
  207.     fprintf(stderr, "rs232_speed(): Invalid line speed - %d\n", speed);
  208. }
  209.  
  210. /*----------------------------------------------------------------------*/
  211. /*         Test program for glue routines and comx driver        */
  212. /*----------------------------------------------------------------------*/
  213.  
  214. #if 0
  215.  
  216. #include <conio.h>
  217.  
  218. static int chan = 0;
  219.  
  220. static void wait_putc(chan, c)
  221. {
  222.     while (rs232_putc(chan, c) < 0)
  223.     ;
  224. }
  225.  
  226. main(int argc, char *argv[])
  227. {
  228.     int     i, j, n;
  229.     char    *cp, buf[128];
  230.  
  231.     if (argc > 1)
  232.     chan = atoi(argv[1]);
  233.     rs232_init(chan, 9600, 'n', 1, 8);
  234.     rs232_prot(chan, PROT_XOUT);
  235. #if 0
  236.     rs232_speed(chan, 9600);
  237. #endif
  238. #if 1                /* read test                */
  239.     do
  240.     {
  241.     while (!kbhit())
  242.         ;
  243.     if ((n = rs232_icount(chan)) <= 0)
  244.         printf("%d characters available ???\n", n);
  245.     else
  246.     {
  247.         if ((i = rs232_read(chan, buf, n)) != n)
  248.         printf("read %d, expected %d\n", i, n);
  249.         write(1, buf, i);
  250.     }
  251.     } while (getch() != 'q');
  252. #endif
  253. #if 0                /* write test                */
  254.     for (i = 32; i < 128; i++)
  255.     {
  256.     cp = buf;
  257.     for (j = i; j < i + 80; j++)
  258.         *cp++ = j < 128 ? j : j - 128 + 32;
  259.     *cp++ = '\r';
  260.     *cp++ = '\n';
  261.     printf("%4d ", rs232_ocount(chan));
  262.     for (j = 0; j < cp - buf; j += n & 0x7fff)
  263.         n = rs232_write(chan, buf + j, cp - buf - j);
  264.     }
  265. #endif
  266. #if 0                /* put/get test             */
  267.     for (i = 32; i < 128; i++)
  268.     {
  269.     for (j = i; j < i + 80; j++)
  270.         wait_putc(chan, j < 128 ? j : j - 128 + 32);
  271.     wait_putc(chan, '\r');
  272.     wait_putc(chan, '\n');
  273.     }
  274.     do
  275.     {
  276.     while ((i = rs232_getc(chan)) < 0)
  277.         ;
  278.     putchar(i);
  279.     }
  280.     while ((i & 0xff) != 'q');
  281. #endif
  282. }
  283. #endif
  284.