home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / S12626.ZIP / COBCOM
Text File  |  1990-07-16  |  16KB  |  437 lines

  1. How to Do Serial Communications in OS/2 COBOL Program       
  2.  
  3. Summary:
  4.  
  5. Microsoft COBOL versions 3.00 and 3.00a protected mode programs can
  6. perform serial communications by calling the following OS/2 API
  7. functions:
  8.  
  9.    Function        Use
  10.    --------        ---
  11.  
  12.    DosOpen()       Opens a file or device
  13.    DosDevIOCtl()   Issues device specific commands (set baud rate, etc.)
  14.    DosRead()       Reads from a file or device
  15.    DosWrite()      Writes to a file or device
  16.    DosClose()      Closes a file or device
  17.  
  18. This information applies to Microsoft COBOL Compiler versions 3.00 and
  19. 3.00a for MS OS/2.
  20.  
  21. More Information:
  22.  
  23. Microsoft COBOL versions 3.00 and 3.00a can call OS/2 API functions
  24. directly with the CALL statement by preceding the name of the function
  25. with a double underscore (__) and linking with the PCOBOL.LIB and
  26. DOSCALLS.LIB libraries. Because API functions use a calling convention
  27. that is the reverse of COBOL's, any parameters must be passed in the
  28. reverse order.
  29.  
  30. The sample program below, TERMNAL.CBL, demonstrates how a protected
  31. mode COBOL program can call the API functions mentioned above to
  32. perform serial communications. When run on two computers connected
  33. with a null-modem cable, TERMNAL.CBL will take any keyboard input and
  34. send it to the other computer via the serial port. It will also read
  35. any input from the serial port and display it on the screen.
  36.  
  37. TERMNAL.CBL calls five other programs: INITCOM.CBL, COMSIZE.CBL,
  38. READCOM.CBL, WRITECOM.CBL and CLOSECOM.CBL (shown further below).
  39. Compile each of these programs (including TERMNAL.CBL) with the
  40. following command:
  41.  
  42.   pcobol <program>;
  43.  
  44. When all the programs have been compiled successfully, enter the
  45. following LINK command (enter the second line after the linker prompts
  46. for .OBJ files):
  47.  
  48.   link /nop
  49.   termnal initcom comsize readcom writecom closecom,,,pcobol doscalls;
  50.  
  51. IMPORTANT NOTE: While TERMNAL.EXE can be made into a bound application
  52. using the BIND.EXE utility, an error may be generated when the program
  53. (run in OS/2 real mode) attempts to set the baud rate, data bits,
  54. parity, or stop bits. This is because the DOS driver for the device
  55. may not support those functions. In that case, direct output to the
  56. serial port would be necessary (bypassing the operating system),
  57. instead of treating the port as a file.
  58.  
  59. For more information on calling OS/2 API functions from COBOL, see
  60. the file OS2API.DOC included with COBOL 3.00a.
  61.  
  62. For more information on the API functions mentioned above, see Pages
  63. 506, 510, 537-539, 553-554, 572, and 621-622 of "Advanced OS/2
  64. Programming" by Ray Duncan (Microsoft Press, 1989).
  65.  
  66. Code Example (in five separate source files)
  67. ------------
  68.  
  69. TERMNAL.CBL
  70. -----------
  71.  
  72.       $SET ANS85
  73.  
  74.       * "Termnal" had to be used instead of "Terminal" because the
  75.       * latter is a reserved word. It is better abbreviated than
  76.       * misspelled (such as "Termenal").
  77.        IDENTIFICATION DIVISION.
  78.        PROGRAM-ID.   Termnal.
  79.  
  80.        DATA DIVISION.
  81.        WORKING-STORAGE SECTION.
  82.  
  83.       *   Name of device to open, terminated with an ASCII 0.
  84.       *   You can specify COM1 or COM2 if port is available.
  85.        01 Port.
  86.           05 ComName     PIC X(4)        VALUE "COM1".
  87.           05 ASCIIZ      PIC X           VALUE X"00".
  88.  
  89.       *   Desired baud rate.
  90.        01 BaudRate       PIC 9(4) COMP-5 VALUE 300.
  91.       *   Specifies to write 1 character at a time.
  92.        01 BytesToWrite   PIC 9(4) COMP-5 VALUE 1.
  93.       *   Receives how many characters were actually written.
  94.        01 BytesWritten   PIC 9(4) COMP-5.
  95.       *   Receives how many characters were actually read.
  96.        01 BytesRead      PIC 9(4) COMP-5.
  97.       *   Receives how many characters are waiting to be read.
  98.        01 CharsWaiting   PIC 9(4) COMP-5.
  99.       *   Handle to the serial device.
  100.        01 Handle         PIC 9(4) COMP-5.
  101.       *   Used to check if key is waiting to be read.
  102.        01 KeyWaiting     PIC 99   COMP-X.
  103.       *   Contains the character to send out the serial port.
  104.        01 Buffer         PIC X.
  105.  
  106.       *   Line characteristics (8 data bits, no parity, 1 stop bit).
  107.        01 LineSpecs.
  108.           05 DataBits    PIC 99   COMP-5 VALUE 8.
  109.           05 Parity      PIC 99   COMP-5 VALUE 0.
  110.           05 StopBits    PIC 99   COMP-5 VALUE 0.
  111.           05 Unused      PIC 99   COMP-5.
  112.  
  113.        PROCEDURE DIVISION.
  114.  
  115.       *    Clear the screen and initialize the serial port.
  116.            CALL X"E4".
  117.            CALL "InitCom" USING Port, Handle, BaudRate, LineSpecs.
  118.  
  119.       *    Loop until the escape key (ASCII 27) is pressed.
  120.            PERFORM UNTIL Buffer = X"1B"
  121.  
  122.       *       Check if key is waiting to be read.
  123.               MOVE 0 TO KeyWaiting
  124.               CALL X"D9" USING KeyWaiting
  125.  
  126.       *       If key read in, send it out the serial port.
  127.               IF KeyWaiting NOT = 0 THEN
  128.                  CALL X"83" USING Buffer
  129.                  CALL "WriteCom" USING Handle, BytesToWrite,
  130.                                        BytesWritten, Buffer
  131.               END-IF
  132.  
  133.       *       Get number of characters waiting in serial buffer.
  134.               CALL "ComSize" USING Handle, CharsWaiting
  135.  
  136.               IF CharsWaiting > 0 THEN
  137.  
  138.       *          Read one character at a time.
  139.                  MOVE 1 TO CharsWaiting
  140.                  CALL "ReadCom" USING Handle, CharsWaiting, BytesRead,
  141.                                       Buffer
  142.  
  143.       *          If a carriage return was read in, advance a line. If
  144.       *          not, display the character on the same line. If it's
  145.       *          a backspace, erase the previous character and
  146.       *          reposition the cursor to that spot.
  147.                  IF Buffer = X"0D" THEN
  148.                     DISPLAY Buffer
  149.                  ELSE
  150.                     DISPLAY Buffer WITH NO ADVANCING
  151.                     IF Buffer = X"08" THEN
  152.                        DISPLAY " " WITH NO ADVANCING
  153.                        DISPLAY Buffer WITH NO ADVANCING
  154.                     END-IF
  155.                  END-IF
  156.  
  157.               END-IF
  158.  
  159.            END-PERFORM.
  160.  
  161.       *    Close the port and end the program.
  162.            CALL "CloseCom" USING Handle.
  163.            STOP RUN.
  164.  
  165. INITCOM.CBL
  166. -----------
  167.  
  168.       $SET ANS85
  169.       $SET OSVS
  170.  
  171.       * InitCom initializes the serial port. It opens the device (via
  172.       * DosOpen) and sets the desired baud rate, data bits, parity,
  173.       * and stop bits (via DosDevIOCtl).
  174.        IDENTIFICATION DIVISION.
  175.        PROGRAM-ID.   InitCom IS INITIAL.
  176.  
  177.        DATA DIVISION.
  178.  
  179.        WORKING-STORAGE SECTION.
  180.  
  181.       *   Parameters of DosOpen function.
  182.  
  183.        01 Reserved      PIC 9(8) COMP-5 VALUE 0.
  184.       *   Specifies read/write mode with no sharing.
  185.        01 OpenMode      PIC 9(4) COMP-5 VALUE 18.
  186.       *   Specifies to open device if it exists, fail if it doesn't.
  187.        01 OpenFlag      PIC 9(4) COMP-5 VALUE 1.
  188.       *   Serial device has no special file attributes.
  189.        01 Attribute     PIC 9(4) COMP-5 VALUE 0.
  190.       *   Specifies no initial file allocation for device.
  191.        01 Allocation    PIC 9(8) COMP-5 VALUE 0.
  192.       *   Receives 1 if device found and opened successfully.
  193.        01 Action        PIC 9(4) COMP-5.
  194.  
  195.       *   Parameters of DosDevIOCtl function.
  196.  
  197.       *   Specifies serial category of operations.
  198.        01 Category      PIC 9(4) COMP-5 VALUE 1.
  199.       *   Specifies function to set baud rate.
  200.        01 Function      PIC 9(4) COMP-5 VALUE 65.
  201.       *   Functions 65 and 66 data buffer format is a null pointer.
  202.        01 NullSegment   PIC 9(4) COMP-5 VALUE 0.
  203.        01 NullOffset    PIC 9(4) COMP-5 VALUE 0.
  204.  
  205.        LINKAGE SECTION.
  206.  
  207.       *   Name of device to open (COMn, where n is 1-4).
  208.        01 Port          PIC X(5).
  209.       *   Handle to refer to device in later operations.
  210.        01 Handle        PIC 9(4) COMP-5.
  211.       *   Desired baud rate.
  212.        01 BaudRate      PIC 9(4) COMP-5.
  213.  
  214.       *   Desired line characteristics.
  215.        01 LineSpecs.
  216.           05 DataBits   PIC 99   COMP-5.
  217.           05 Parity     PIC 99   COMP-5.
  218.           05 StopBits   PIC 99   COMP-5.
  219.           05 Unused     PIC 99   COMP-5.
  220.  
  221.        PROCEDURE DIVISION USING Port, Handle, BaudRate, LineSpecs.
  222.  
  223.       *    Open the device.
  224.            CALL "__DosOpen" USING BY VALUE     Reserved,
  225.                                   BY VALUE     OpenMode,
  226.                                   BY VALUE     OpenFlag,
  227.                                   BY VALUE     Attribute,
  228.                                   BY VALUE     Allocation,
  229.                                   BY REFERENCE Action,
  230.                                   BY REFERENCE Handle,
  231.                                   BY REFERENCE Port.
  232.  
  233.       *    If no error occurred, set the baud rate.
  234.            IF RETURN-CODE = 0 THEN
  235.               CALL "__DosDevIOCtl" USING BY VALUE     Handle,
  236.                                          BY VALUE     Category,
  237.                                          BY VALUE     Function,
  238.                                          BY REFERENCE BaudRate,
  239.                                          BY VALUE     NullSegment,
  240.                                          BY VALUE     NullOffset
  241.            ELSE
  242.               CALL X"E5"
  243.               DISPLAY "ERROR opening port - " RETURN-CODE
  244.               STOP RUN
  245.            END-IF.
  246.  
  247.       *    Specifies function to set line characteristics.
  248.            MOVE 66 TO Function.
  249.  
  250.       *    If no error occurred, set line characteristics.
  251.            IF RETURN-CODE = 0 THEN
  252.               CALL "__DosDevIOCtl" USING BY VALUE     Handle,
  253.                                          BY VALUE     Category,
  254.                                          BY VALUE     Function,
  255.                                          BY REFERENCE LineSpecs,
  256.                                          BY VALUE     NullSegment,
  257.                                          BY VALUE     NullOffset
  258.            ELSE
  259.               CALL X"E5"
  260.               DISPLAY "ERROR setting baud rate - " RETURN-CODE
  261.               STOP RUN
  262.            END-IF.
  263.  
  264.       *    Report if error occurred setting line characteristics.
  265.            IF RETURN-CODE NOT = 0 THEN
  266.               CALL X"E5"
  267.               DISPLAY "ERROR setting line specs - " RETURN-CODE
  268.               STOP RUN
  269.            END-IF.
  270.  
  271.            EXIT PROGRAM.
  272.  
  273. COMSIZE.CBL
  274. -----------
  275.  
  276.       $SET ANS85
  277.       $SET OSVS
  278.  
  279.       * ComSize obtains the number of bytes waiting to be read from
  280.       * the serial port (via DosDevIOCtl).
  281.        IDENTIFICATION DIVISION.
  282.        PROGRAM-ID.   ComSize IS INITIAL.
  283.  
  284.        DATA DIVISION.
  285.  
  286.        WORKING-STORAGE SECTION.
  287.  
  288.       *   Specifies serial category of operations.
  289.        01 Category          PIC 9(4) COMP-5 VALUE 1.
  290.       *   Specifies function to get number of characters in queue.
  291.        01 Function          PIC 9(4) COMP-5 VALUE 104.
  292.       *   Function 104 parameter buffer format is a null pointer.
  293.        01 NullSegment       PIC 9(4) COMP-5 VALUE 0.
  294.        01 NullOffset        PIC 9(4) COMP-5 VALUE 0.
  295.  
  296.       *   Receives number of characters in queue and size of queue.
  297.        01 QueueInfo.
  298.           05 CharsInQueue   PIC 9(4) COMP-5.
  299.           05 QueueSize      PIC 9(4) COMP-5.
  300.  
  301.        LINKAGE SECTION.
  302.  
  303.       *   Handle to the serial device.
  304.        01 Handle            PIC 9(4) COMP-5.
  305.       *   Receives number of characters waiting to be read.
  306.        01 CharsWaiting      PIC 9(4) COMP-5.
  307.  
  308.        PROCEDURE DIVISION USING Handle, CharsWaiting.
  309.  
  310.            CALL "__DosDevIOCtl" USING BY VALUE     Handle,
  311.                                       BY VALUE     Category,
  312.                                       BY VALUE     Function,
  313.                                       BY VALUE     NullSegment,
  314.                                       BY VALUE     NullOffset,
  315.                                       BY REFERENCE QueueInfo.
  316.  
  317.       *    Report if error occurred.
  318.            IF RETURN-CODE NOT = 0 THEN
  319.               CALL X"E5"
  320.               DISPLAY "ERROR getting port size - " RETURN-CODE
  321.            END-IF.
  322.  
  323.            MOVE CharsInQueue TO CharsWaiting.
  324.            EXIT PROGRAM.
  325.  
  326. READCOM.CBL
  327. -----------
  328.  
  329.       $SET ANS85
  330.       $SET OSVS
  331.  
  332.       * ReadCom attempts to read the desired number of bytes from the
  333.       * serial port (via DosRead). It returns the number of bytes
  334.       * actually read.
  335.        IDENTIFICATION DIVISION.
  336.        PROGRAM-ID.   ReadCom.
  337.  
  338.        DATA DIVISION.
  339.        LINKAGE SECTION.
  340.  
  341.       *   Handle to the serial device.
  342.        01 Handle        PIC 9(4)   COMP-5.
  343.       *   Number of characters desired to be read.
  344.        01 BytesToRead   PIC 9(4)   COMP-5.
  345.       *   Actual number of characters read.
  346.        01 BytesRead     PIC 9(4)   COMP-5.
  347.       *   Receives the characters read, assumes 512 byte buffer.
  348.        01 Buffer        PIC X(512).
  349.  
  350.        PROCEDURE DIVISION USING Handle, BytesToRead, BytesRead,
  351.                                 Buffer.
  352.  
  353.            CALL "__DosRead" USING BY REFERENCE BytesRead,
  354.                                   BY VALUE     BytesToRead,
  355.                                   BY REFERENCE Buffer,
  356.                                   BY VALUE     Handle.
  357.  
  358.       *    Report if error occurred.
  359.            IF RETURN-CODE NOT = 0 THEN
  360.               CALL X"E5"
  361.               DISPLAY "ERROR reading from port - " RETURN-CODE
  362.               STOP RUN
  363.            END-IF.
  364.  
  365.            EXIT PROGRAM.
  366.  
  367. WRITECOM.CBL
  368. ------------
  369.  
  370.       $SET ANS85
  371.       $SET OSVS
  372.  
  373.       * WriteCom attempts to write the desired amount of bytes to the
  374.       * serial port (via DosWrite). It returns the number of bytes
  375.       * actually written.
  376.        IDENTIFICATION DIVISION.
  377.        PROGRAM-ID.   WriteCom.
  378.  
  379.        DATA DIVISION.
  380.        LINKAGE SECTION.
  381.  
  382.       *   Handle to the serial device.
  383.        01 Handle         PIC 9(4)   COMP-5.
  384.       *   Number of characters to write.
  385.        01 BytesToWrite   PIC 9(4)   COMP-5.
  386.       *   Receives number of characters actually written.
  387.        01 BytesWritten   PIC 9(4)   COMP-5.
  388.       *   Contains the characters to write, assumes 512 byte buffer.
  389.        01 TheData        PIC X(512).
  390.  
  391.        PROCEDURE DIVISION USING Handle, BytesToWrite, BytesWritten,
  392.                                 TheData.
  393.  
  394.            CALL "__DosWrite" USING BY REFERENCE BytesWritten,
  395.                                    BY VALUE     BytesToWrite,
  396.                                    BY REFERENCE TheData,
  397.                                    BY VALUE     Handle.
  398.  
  399.       *    Report if error occurred.
  400.            IF RETURN-CODE NOT = 0 THEN
  401.               CALL X"E5"
  402.               DISPLAY "ERROR writing to port - " RETURN-CODE
  403.               STOP RUN
  404.            END-IF.
  405.  
  406.            EXIT PROGRAM.
  407.  
  408. CLOSECOM.CBL
  409. ------------
  410.  
  411.       $SET ANS85
  412.       $SET OSVS
  413.  
  414.       * CloseCom closes the serial port, relinquishing the handle and
  415.       * deallocating buffer.
  416.        IDENTIFICATION DIVISION.
  417.        PROGRAM-ID.   CloseCom.
  418.  
  419.        DATA DIVISION.
  420.        LINKAGE SECTION.
  421.  
  422.       *   Handle to the serial device.
  423.        01 Handle   PIC 9(4) COMP-5.
  424.  
  425.        PROCEDURE DIVISION USING Handle.
  426.  
  427.            CALL "__DosClose" USING BY VALUE Handle.
  428.  
  429.       *    Report if error occurred.
  430.            IF RETURN-CODE NOT = 0 THEN
  431.               CALL X"E5"
  432.               DISPLAY "ERROR closing port - " RETURN-CODE
  433.               STOP RUN
  434.            END-IF.
  435.  
  436.            EXIT PROGRAM.
  437.