User Reports


C Communications Toolkit

Comments By Victor R. Volkman


Victor R. Volkman received a bachelor's degree in computer science from Michigan Technological University. He is a software engineer at Cimage Corporation, Ann Arbor, Michigan, and can be reached at the HAL 9000 BBS, 313-663-4173, 1200/2400/9600 baud or via Usenet as vrv@cimage.com.

The C Communications Toolkit (hereafter CCT or toolkit) from Magna Carta Software (Garland, TX) is a comprehensive package providing everything from low-level UART register manipulation to batch file-transfer protocols. It also supplies data translation and ANSI terminal emulation facilities. The CCT is shipped with libraries compiled for Turbo C, Watcom C, Microsoft C, and Mix Power C. Each of the libraries includes versions built for the small, medium, and large memory models. The toolkit includes all the source code you need to port to an unsupported memory model or compiler. It retails for $150. Magna Carta backs its product with a 30-day money-back guarantee.

I received version 1.00B of the toolkit, which was dated 06/09/90. The entire install set was squeezed onto three 5 360K disks using LZH compression. Installation consists of uncompressing the .LIB, .C, and .H files into the directories of your choice. The tookit should work fine with any PC (from 8088 to 80486) on any version of DOS (3.0 or later).

The CCT supports a variety of communications hardware. The primary emphasis is on the INS8250 family of Universal Asynchronous Receiver/Transmitters (UART) chips. The INS8250 family, which has been the PC standard for almost a decade, includes NS16450 and NS16550A compatible chips as well. Special support is provided for the FIFO buffer and interrupt threshold features of the NS16550A. This toolkit also supports the Zilog Z-80 SIO communications chip. The SIO provides both synchronous and asynchronous communications, but it is normally found only on 3270 terminal emulation adapters. Because there is no standard hardware interface for the SIO on the PC, the CCT implementation is only guaranteed to work with AST's 3270 adapters.

The toolkit also supports the Intel Connection Coprocessor using the Communication Applications Standard (CAS). The CAS interface is a high-level mechanism for scheduling file and facsimile transmissions.

Initializing Communications

The CCT supports both polled and interrupt-driven communications for receiving and transmitting data. The init_port function can initialize each of these four cases. Once a port is initialized, it is available to begin transmitting and receiving characters. An example invocation is:

init_port(&port1, COM1, 1200L, DATABITS8,
   PARITY_NONE, STOPBITS1, txbuf, rxbuf);
The first argument is a pointer to a mostly uninitialized COMM_PORT data structure. The second argument is the base address of the serial port to be initialized. The next four parameters set up the basic configuration of the serial link (1,200 baud, 8N1). The last two arguments specify optional transmit and receive buffering.

If the rxbuf argument is not a null pointer, then init_port sets up an interrupt-handler for receiving characters into the buffer. If the txbuf argument is not a null pointer, then the function sets up a similar handler for transmitting characters. If both rxbuf and txbuf are null, then all I/O takes place in polled mode.

The default transmitter and receiver buffer sizes are set to 1,024 bytes and 2,048 bytes respectively. If these are inappropriate, then you must either change the #defines in COMM.H or call the lower-level c_open function. For c_open to work correctly, you must initialize several more fields in the COMM_PORT data structure in advance.

Ports And Modems

The CCT keeps track of everything related to a given communications session in a COMM_PORT data structure. This all-encompassing data structure contains more than 150 members to describe the state of the session. COMM_PORT conforms to the guidelines set forth by Campbell (1987) for writing UART-independent communications programs. Both the COMM_PORT and MODEM data structures closely parallel Campbell's definitions. The CCT does not use Campbell's "virtual UART" model, but it does capably isolate UART-specific registers by incorporating a union pointer in COMM_PORT. The utype member of COMM_PORT tags the UART union being used. A UART union appears as:

typedef union uart {
   UART8250 u8250; /* Intel */
   UARTZ80SIO uz80sio; /* Zilog */
   } UART;
The other members of COMM_PORT define parameters for buffers, flow control, RS-232C inputs and outputs, line characteristics, receiver and transmitter data translation, and physical port characteristics. In addition to the session-specific parameters, COMM_PORT also includes more than two dozen function pointers. Last, COMM_PORT contains a pointer to a MODEM structure.

The COMM_PORT function pointers designate Interrupt Service Routines (ISRs), low-level UART-specific services, and callback functions. The ISR function pointers in the COMM_PORT structure keep track of which ISRs belong to a given port. Generally, each communications port on the PC requires a dedicated Interrupt Request (IRQ) line. The PC architecture dictates that each IRQ line must have its own ISRs. The function pointers for low-level UART-specific services transmit and receive characters without requiring every function to be intimately familar with how UART works. The callback function pointers enable the CCT functions to better serve your application's environment. For example, you can transparently send a copy of the communications stream to your printer by pointing the p_out member to your own printer echoing function.

As mentioned earlier, the COMM_PORT data structure also contains a pointer to a MODEM data structure. The MODEM data structure holds all of the data needed to initialize a modem before connection. Nearly 100 initialization parameters can be set if desired. MODEM is composed almost entirely of Hayes Smartmodem command strings. For example, the dial_cmd member typically contains the ATDT dialing prefix. Nearly all modems manufactured within the last five years understand at least a subset of these commands.

The CCT provides several functions to take advantage of the MODEM information. Each of these functions locates a MODEM structure via a COMM_PORT. The modem_init function sends the initialization strings in MODEM. The modem_dial function takes a telephone number string and performs the dialing for you. The modem_hangup function hangs up the phone immediately. The general purpose modem_scmd function sends a command to the modem and returns a pointer to the reply buffer. For example, you use the following sequence to turn off the modem speaker:

strcpy(my_port->modem.speaker, "MO");
reply = modem_scmd(my_port,
   my_port->modem.speaker, BUF_SIZE);
if (strcmp(reply,"OK") != 0)
printf("Error: modem not responding!\n");

Data Translation

The toolkit provides extensive support for translation on both received and transmitted data. The CCT data translation functions govern character echoing, newline handling, programmable delays, and flow control issues. The parameters for data translation can be changed at any time via the set_rx_xlat and set_tx_xlat functions. Both of these functions take three arguments. The first is the COMM_PORT to be affected. The last two tell which translation item to set and to which value to set it. For example, to enable printer echoing you would call the function:

set_rx_xlat(&myport, PRINTER_ECHO, ON);
The data translation functions enable you to control when and where characters will be echoed. The LOCAL_ECHO, REMOTE_ECHO, PRINTER_ECHO, and CAPTURE_BUFFER_ECHO flags control echoing. The LOCAL_ECHO flag tells whether characters should be displayed as they are read or written. On receive, the REMOTE_ECHO flag tells whether received characters should be echoed back. On transmit, REMOTE_ECHO tells whether you should wait for a return echo before transmitting the next character. The PRINTER_ECHO flag allows received and/or transmitted characters to be logged to a printer. Last, CAPTURE_BUFFER_ECHO permits received or transmitted characters to be simultaneously copied to a memory buffer.

The CCT data translation functions also give you extensive control over newline handling. Special newline handling is often needed for communicating with mainframe hosts and UNIX workstations. As with other translations, newline handling can be independently specified for receiving and transmitting. The nine different options available include Linefeed to Carriage-Return (LF2CR) and Carriage-Return Linefeed to Linefeed (CRLF2LF).

Although programmable delays are not strictly a data translation, the same CCT functions enable them as well. The INTERBYTE_DELAY and TRAILINGBYTE_DELAY flags control delays. On receive, INTERBYTE_DELAY allows you to specify a timeout value to wait for each incoming character. On transmit, INTERBYTE_DELAY specifies a pause between each outgoing character. This is handy for communications sessions with mainframe hosts, which have notoriously poor receive buffering. TRAILINGBYTE_DELAY allows for extra time after the newline is transmitted or received.

Last, the translation functions also set up the flow control parameters. Flow control prevents overrunning the receive buffer when data is coming in faster than it can be processed. The C Communications Toolkit supports RTS/CTS, DTR/DSR, and XON/XOFF handshaking. For XON/XOFF control, you must also designate the characters used to represent these conditions. Some of the flow control techniques can be combined.

File Transfers

The CCT has high-level functions to send and receive files using several popular protocols. Specifically, CCT supports the XModem, XModem-CRC, XModem-1K, YModem, Y- Modem-G, and Kermit protocols. With the CCT, receiving a file can be as simple as calling freceive with the appropriate parameters. A sample invocation of freceive is:

ret = freceive(&myport, &xinfo, protocol,
   10*1024L, transfer_progress);
The first argument to freceive is the COMM_PORT structure pointer. The next is a pointer to an unitialized XFER structure. An XFER structure consists of about two dozen members that describe every aspect of the file transfer. The third argument to freceive specifies the suggested protocol to use. Under certain circumstances, freceive can change the protocol in midstream if it discovers that the sender is using a different protocol. The next argument tells how large the receive buffer should be. The receive buffer is dynamically allocated within freceive and will be automatically reduced if insufficient heap space is available. The last parameter is a pointer to a callback function for progress reports. The progress report function must receive parameters for the COMM_PORT, status, and bytes received so far. Typically, a progress report function formats and displays status messages in a screen window.

With the CCT, sending a file is only slightly more complicated than receiving one. The primary difference is that files must be enqueued before sending them, even if only one file is going to be sent. The fqueue function takes a pointer to an XFER structure and a string containing the filename to enqueue. For multiple-file (a.k.a. batch) protocols, each invocation of fqueue adds another file to the list. The fsend function does the actual work of sending the file:

fqueue(&xinfo, "HAL_9000.ZIP");
fqueue (&xinfo, "TOOLKIT.DOC");
ret = fsend(&myport, &xinfo, YMODEM, transfer_progress);
The arguments to fsend are similar to those described for freceive, except fsend uses a smaller fixed-size buffer for transmission. fsend can also change the protocol in midstream to any XModem or YModem variant if it detects the receiver using a different protocol.

The CCT makes the normally unwieldly Kermit protocol easy to use. To send or receive via Kermit, you need only add a call to init_kermit just before the actual freceive or fsend. init_kermit initializes a KERMIT_PARMS structure containing about 40 members. By modifying the KERMIT_PARMS structure, you can fine-tune the Kermit protocol parameters.

Although you can implement file transfer protocols that are not supported by CCT, it might be a daunting task to do so. The source code for the supplied protocols is heavily tailored toward the eccentricities of the XModem variants. However, you could still use the library source as a model for new protocol development.

Terminal Emulation

The CCT also provides VT-52/100 and ANSI X3.64 terminal protocol emulation. These two emulations together account for nearly all character-based terminals used today. The init_term function selects and installs terminal emulation. init_term requires three arguments. The two supported invocations of init_term are:

t = init_term(&myport,
   vt100_write, vt100_conoutc);
t = init_term(&myport,
   ibmansi_write, ibmansi_conoutc);
The first argument is the COMM_PORT for which terminal emulation will be enabled. The next argument is a pointer to the function that will process serial output. The final argument is a pointer to the function that will handle screen output. Although the documentation makes much ado about how new terminal drivers can be added in a "cookbook fashion," there are barely two pages devoted to writing an alternate terminal emulation.

Unfortunately, the CCT terminal emulations use the BIOS video INT 10h for all output. The INT 10h interface is an order of magnitude slower than writing directly to memory, which will undoubtedly reduce throughput on high speed (9,600 baud or greater) links.

Performance

The best measure of a communications library is how well it performs versus other applications. I compared the example programs supplied with the CCT against TTYTALK and ProcommPlus v1.0. I developed TTYTALK, a complete terminal program for the IBM PC written with C, in 1988 (see bibliography). TTYTALK supports a subset of the command language found in the popular CROSSTALK XVI package by DCA. TTYTALK features input/output filtering, data translation, and send and capture of ASCII files. The CCT example program #8 most closely matches the capabilities of TTYTALK. My comparison indicated that the size of the source files for TTYTALK and CCT example #8 were roughly equal (23K vs. 18K). When built with Microsoft C 5.1 small model, the executable size for CCT example #8 was only about 32K larger than TTYTALK.EXE (which was 17K). See Figure 1. Since the entire CCT large model library is less than 100K, the library imposes little overhead.

For the second stage of performance evaluation, I benchmarked the CCT examples #9 and #10 against the ProcommPlus v1.0. I designed this test to match their file transfer capabilities on XModem-1K at both 2,400 and 9,600 baud (v.32). I ran all tests on a 25MHz 80386 computer with a NS16550A UART chip and a Hayes ULTRA 96 v.32 modem. The programs were run in a DESQview v2.26 DOS window with 340K RAM available. On the other end of the communications link, I used a Telebit T2500 v.32 modem in conjunction with a 10MHz 80286 computer. The connections uniformly used the LAP-M link protocol and v.42bis data compression to transmit .ZIP files. The host BBS software used was PCBoard v14.5/E3 with internal protocols. The PCBoard host software reported the effective file transfer rates. My results show the "best case" transfer rates that I obtained after at least four trials.

The results of testing at 2,400 baud showed no significant differences between ProcommPlus and the CCT (see Figure 2) . The file transfer efficiency was within expected norms for the X-Modem-1K protocol. However, at 9,600 baud I had some problems with the CCT application. The XModem-1K sent reported errors on several occasions and aborted the transfer. When the file sends were successful, the CCT application performed at the same level as ProcommPlus (see Figure 3) . Although I had no difficulty receiving files with the CCT at 9,600 baud, the transfer rates were consistently about 100 characters per second (cps) behind ProcommPlus. The XModem family of protocols often has difficulty at high speeds. For this reason, most highspeed modem users prefer Zmodem when at 9,600 baud and above.

Documentation

The CCT documentation consists of a single 600-page paperback reference and tutorial book. Approximately half the book is devoted to a tutorial of basic communications concepts including transmission modes, the RS-232 standard, UART register sets, the Hayes standard "AT" command set, file transfer protocols, and terminal emulation. The rest of the manual describes header files and gives an alphabetical list of functions, parameters, and return codes. The manual could easily be improved in two regards. First, it lacks a glossary of communications terminology. Second, the index should contain entries for all of the CCT functions.

The CCT takes a gentle approach to demonstrating typical communications applications and how they can be solved. The tutorial book presents a series of 17 complete mini-applications in order of increasing complexity from a polling dumb-terminal to a full transmit/receive interrupt-driven terminal. Along the way, the book shows capabilities such as terminal emulation and file transfer protocols. None of the tutorial programs demonstrates how to use the advanced features of the NS16550A UART.

The documentation discusses the Hayes command set and individually covers specifics of the Smartmodem 300, 1,200, and 2,400 baud models. The Hayes V-series is also mentioned, although the Hayes ULTRA 96 v.32 modem is not covered. The manual also ignores the differences between the Smartmodem 1200 and 1200EF (Extended Features) products. Although the CCT contains vendor-specific support for Telebit series modems, the manual does not list the Telebit extensions to the Hayes command set.

The manual precisely describes the XModem file transfer protocol. The authors correctly indicate all of XModem's faults, variants, and workarounds. All of the popular Xmodem extensions including XModem-CRC, XModem-1K, YModem, and YModem-G protocols are summarized. The Kermit file transfer protocol is treated the same as the Xmodem protocol. The documentation also describes the Kermit 8th-bit quoting and Run-Length Encoding (RLE) extensions that the CCT offers.

The function reference section groups the function calls by category. The functions are then presented alphabetically within each category. The notes for each function indicate its purposes, arguments, and return values. Additionally, the notes mention the header file in which it is declared, any hardware limitations it might have, and all of the lower-level functions that it might call.

One area of communications ignored by the tutorial programs and text is development of host (e.g. BBS) software with the toolkit. Although many of the issues are the same for both host and terminal modes, a novice could benefit from such a discussion. Topics for host support would include ring detection and answering, loss of carrier detection, line settings, and Hayes register settings for the host.

The manual does contain some typographical errors, but these are easily overlooked given the clarity of the explanations. There are also a few references to nonexistent figures and tables.

Support

Magna Carta Software provides technical support via telephone and Bulletin Board System (BBS). However, you must mail in the registration form to obtain a serial number before you can obtain any technical support. The Magna Carta BBS consists of a single 2,400 baud modem line running OPUS software. The BBS is frequented by Andrew Chalk, the principal developer and president of Magna Carta Software. In addition to communication utilities and specifications, the BBS also has the latest beta test version of the CCT. During my product testing, I downloaded CCT v1.00D from the Magna Carta BBS. Most support questions posted on the BBS are answered within 24 hours.

The back cover of the CCT manual and all of the advertising indicates that several intelligent multi-port serial boards are supported, including models from AST, CommTech, Digiboard, and Arnet. An intelligent multi-port serial board usually includes an onboard CPU, such as an Intel 80186. These boards typically cost more than the motherboard on your computer. A multi-port board may contain 4, 8, 16, or even 32 serial ports. These adapters often include onboard EPROM and RAM areas. The adapter RAM may be either privately transferred via DMA or mapped through a window in high DOS memory (like video RAM).

A thorough search of the documentation and source code revealed no references to any of these multi-port boards. After scouring the Magna Carta BBS, I discovered supplemental source code for the CommTech and Digiboard products which had been omitted from the CCT. I asked Andrew Chalk about this apparent support discrepancy. He said the CommTech and Digiboard drivers would be distributed in the future starting with CCT v1.01. Chalk also said that drivers for Star Gate ACL/II and the AST CC-832 adapters were currently being developed. The release dates for these drivers have not yet been announced at the time of this writing.

Support for the CommTech FASTCOMM4 board consists of 200 lines of C allowing it to be addressed as an array of serial ports. Support for the DigiBoard DigiCHANNEL COM/4i and COM/8i is much more extensive than for the CommTech board. The DigiCHANNEL driver provides methods to download communications functions and execute them on the adapter's own CPU. Special board-specific functions manipulate the command and data queues for each port. The CCT functions modified for the DigiCHANNEL board all have an xi_ prefix added to them. For example, the set_speed function is renamed xi_set_speed for the DigiCHANNEL. This function naming convention would seem to make it difficult for an application programmer to maintain a single set of device-independent source modules. An application programmer would most likely need to resort to #ifdefs to work around this naming convention.

If you are using a multi-port board that the CCT does not currently support, Magna Carta Software will consider adding support under an exchange agreement. If you are willing to loan the board to Magna Carta for 30 days, they will consider writing the drivers for you. In return, Magna Carta retains the rights to distribute the drivers in subsequent releases of CCT.

Both data structures and functions of the CCT have been revised since release 1.00 in May 1990. The revisions leading up to v1.00D require changes at the source code level to applications written with the initial version of CCT. These changes are fully documented in the release notes and are mainly oriented toward removing hardware-dependent code at the UART level — an admirable goal. The source-level interface should remain stable in future releases.

The Competition

Magna Carta's CCT compares favorably in both price and functionality against competing DOS communications libraries. Some other packages do not support the Z-80 SIO USART or VT-100 emulation. Most DOS communications libraries offer support for the same file-transfer protocols, flow-control mechanisms, UARTS, and multi-port serial boards. In addition, many libraries are including full library source code at no extra charge.

With a list price of $150, the C Communications Toolkit is the least expensive of the libraries I have seen. Other packages, such as the C Asynch Manager by Blaise Computing ($189), C Asynch Library by SilverWare ($250), and Essential Communications by South Mountain Software ($329), provide similar functionality but with a higher cost.

The CCT file transfer protocol suite is only missing ZModem capability. Z-Modem is by far the most efficient file transfer protocol available. ZModem offers CRC-32 error detection, dynamically negotiated block sizes, and the ability to restart aborted file transfers (Forsberg 1990). The Solid Link communications library by Solid Software ($199) is the only competitor that includes the ZModem protocol. However, the source code for Solid Link is optional and costs significantly more than the package itself.

Conclusion

The C Communications Toolkit is one of the most comprehensive packages I've come across. The CCT price compares well with other packages, and the tutorial text and example programs are sufficient for even a novice C programmer. The function set is adequate for developing a commercial quality terminal program and includes full library source. In file-transfer protocols, the CCT performs as well as existing communications programs such as ProcommPlus. If you plan to use an intelligent multi-port serial board, be sure to contact the vendor to determine exactly what level of support is available. For many communication applications, the C Communications Toolkit may be all the help you need.

Bibliography

Campbell, Joe. C Programmer's Guide to Serial Communications. Indianapolis: Howard W. Sams & Co., 1987. This text is loaded with useful commentary on Hayes Smartmodem programming, UART control, XModem file transfer, and CRC calculations. Its hallmark is a device-independent library of serial I/O functions. Campbell is also the author of The RS-232 Solution.

Forsberg, Chuck. DSZ — a ZMODEM-90TM File Transfer Program. Portland, OR: Omen Technology Inc., 1990. This is the user's manual for Forsberg's implementation of the Z-Modem protocol. This file is available in the file DSZ1190.ZIP on my BBS.

Volkman, Victor. "TTYTALK: How Serial Telecommunication Works." The C Gazette (Summer 1988): pp 4-27. This article introduces TTYTALK, a C program CROSSTALK XVI compatible terminal program in C. Features include filtering, ASCII file transfer, command language, and dialing. Complete source code for this program is available in the file CGAZV3N1.ZIP on my BBS.

Acknowledgements

PCBoard is a registered trademark of Clark Development Corporation. ProcommPlus is registered trademark of Data-Storm Technologies, Inc. DESQview is a registered trademark of Quarterdeck Office Systems, Inc.

Magna Carta Software, Inc.
P.O. Box 475594
Garland, TX 75047-5594
Phone: (214) 226-6909
BBS: (214) 226-8088 (1200/2400 baud)