Windows Eiffel Library Communications Library

Purpose
This library wraps the Win32 APIs applicable to I/O through a communications device such as a serial port or a modem.

What's missing?
Not much.  See the Comm Properties section for some ideas.

Basic use
The main class is WEL_COMM.  Clients should create the object with the name of the communications resource such as "COM1", or "LPT1".  The device is opened in the make procedure because the client can do very little until the device is opened.

Here is an example of initializing a serial port:

comm: WEL_COMM is
	-- Communications resource connected to COM1
once
	create Result.make ("COM1", True)
	Result.set_control_string ("9600,n,8,1")
	Result.set_rx_threshold (10)
end

"9600,n,8,1" = 9600 baud, no parity, 8 data bits, 1 stop bit

In this example the client knows serial data will come in packets of 10 bytes, so rx_threshold is set to 10.  The client will then poll the `readable' property of comm.  When  `readable' is true there are at least 10 bytes of data in the input buffer.

Blocking
Blocking, also known as non-overlapped or synchronous mode, is useful for fast I/O operations or when the client need not perform any other work while the operation is pending.  Personally I prefer to use blocking calls in a thread devoted solely to servicing the communications resource.  However single-threaded applications can utilize this functionality by placing a poll in the main loop.

When blocking is false, I/O operations will return immediately.  If the operation is pending, `is_io_pending' will be true.  During this time the client is free to do other work, but may not perform any other I/O operations on the same resource until the last one completes.

Testing
I only tested the cluster for use with a serial port.  But I've been cognizant of its potential uses, and have tried not to be restrictive.  Generally, if it's possible in the Win32 API, it should be possible in these classes.

The WEL_COMM_VERIFIER class is my repository for features developed to test WEL_COMM.  It may seem a little short of functionality.  Rest assured this does not because of a lack of object verification.  Rather it is because I began saving my work after most of the testing was completed.

Exceptions
The WIN32 API doest not define its specification as stringently as Design by Contract would dictate.  It was impossible to know a priori if an Eiffel wrapper met the complete specification of the wrapped API call through assertions.  Only after the API call could the pass/fail determination be made by inspecting the return value.  Therefore many of the Eiffel features will throw exceptions when the underlying API call fails.  Ignoring the function's return value seemed unacceptable.  Throwing an exception seemed a viable option as failures will generally fall into either initialization failures or catastrophic runtime failures.

A client need not catch every read and write exception, as these will most likely be caused by an unrecoverable error, such as a hardware failure.  Initialization exceptions will most likely be caused by invalid settings because not all invalid values could be trapped in preconditions.  If I were writing a client, I would probably not catch any exceptions thrown by WEL_COMM except to gracefully quit.

Comm properties
While on the subject of preconditions and valid settings, you may notice there is a lot of parameter checking capability in WEL_COMM_PROPERTIES (e.g. is_valid_baud) that was not utilized in WEL_COMM.  WEL_COMM_PROPERTIES contains lots of useful information about the device's settable parameters.  This could theoretically be used to test input parameters to various WEL_COMM features.  The only two I used were in `set_rx_buffer_size' and `set_tx_buffer _size', checking to make sure the requested size was not greater than the device's maximum.  I intended to use all the parameter checking capability, but soon became concerned that a parameter might fail the precondition and pass the API call.  In other words, the parameter checking might be more restrictive than the device.  Furthermore, parameter checking is performed by the API calls and failures are returned as an exception.

Persistence
I've implemented a work around for persistence suggested by Emmanuel Stapf.  Perhaps one day I'll implement a prettier version.

More Information
See http://msdn.microsoft.com/library/en-us/devio/base/communications_resources.asp for Windows documentation.

Updates
[25 October, 2002]
Initial release

[5 November, 2002]
WEL_COMM_PROPERTIES now inherits from WEL_BIT_OPERATIONS and uses its facilities.
WEL_COMM_EVENT_MASK also inherits from WEL_BIT_OPERATIONS.
Added event mask and low-level control facilities to WEL_COMM.
Added the ability to wait for an event defined in the event mask.
Added the WEL_COMM_VERIFIER class

[13 November, 2002]
Fixed some errors in this read_me file.
Removed WEL_COMM_ESCAPE_CONSTANTS and placed the necessary constants within WEL_COMM to cut down on facility inheritance.

[20 December, 2002]
{WEL_COMM}.put_string used to always send a null character at the end of a string.  This disrupted binary transfers so I changed put_string to account for plain_text_mode.
{WEL_COMM}.read_stream would not read NULL characters because {STRING}.make_from_c was used.  This was fixed by using {STRING}.from_c_substring instead

[13 March, 2003]
Added precondition `not_waiting' to feature {WEL_COMM}.wait_for_event. A non-blocking call can be made to `wait_for_event'. The client should poll `is_io_pending' until False indicating the event has triggered. A second call to `wait_for_event' while the first is pending is not allowed.
Changed the postcondition in `is_io_pending' from "only_pending_when_blocking: Result implies blocking" to "only_when_not_blocking: Result implies not blocking". Blocking calls are those that do not return until finished. There can never be an io operation pending during blocking operation. I don't know what I was thinking.

Contact
Feel free to contact me for suggestions or complaints

Brian E. Heilig
e-mail: MY_FIRST_NAME@MY_LAST_NAME.net
