Release of TCA Version 8.1 Summary: ======== This minor release fixes several important bugs. 1) Several important bug fixes: a) A memory leak was fixed that could cause TCA central to grow without bound. b) Fixed a problem that occurred when centrally generated messages were queued. c) Fixed problem that occurred when a module needed to try several times to send a buffer (because the buffer was full). Previously, it would send some of the same parts of the buffer over again. d) Fixed a problem with sending a structure of doubles from one machine to another machine of the same type. e) Fixed a problem with direct connections that would cause TCA to crash when a command or goal message was sent from an inform or a query. As part of that fix, all command and goal messages that are sent from informs or queries are now added to the root node of the task tree (since informs and queries are not part of the task tree, previously the command and goal nodes were left unattached to any part of the task tree). 2) Brought the LISP version of TCA back into sync with the C version. Almost all relevant TCA functions (except mainly for the memory management functions) are now available in LISP. 3) Added a functional interface to devUtils. The devUtils library provides a utilities for handling asynchronous input from a number of sources. It provides support for tty devices, TCA, X11 and stdin. It also has facilities to support hardware simulators that connect via TCP/IP to simulate devices that use RS232 connections. Details: ======== DevUtils -------- The device utilities library provides methods for creating and managing interfaces to hardware devices and other "IO" devices like X11, TCA and stdin. It provides more robust error and interrupt handling to improve the robustness of your TCA programs. Most event driven programs, such as TCA programs, are written around a main event loop. Both TCA and X11 provide main event loops, as well as functions for handling single events. Most main event loops are created using a "select" call with a timeout. There are three ways to integrate TCA and X11 into an event loop. The program can have its own "home grown" event loop that calls the appropriate TCA and X11 routines. The X11 main event loop can be used, with the TCA inputs added as extra inputs with their own handlers, or the device utils main event loop can be used. The advantage of using the devUtils loop is that it is better able to deal with exceptions and broken pipes. It also has per device timers and supports polling and simple data parsing. Examples of how to use each type of event loop can be found in the tutorial/simulator directory. sim.c pro Below is a description of the Main functions in the devUtils library. The general way to use the library is to create some devices, connect them and then call the devMainLoop. devCreateDev: Create a device data structure and initialize it. The first parameter is a string that gives the name of the device. This is followed by a variable length list of parameter name, parameter value pairs. The list is terminated with a NULL parameter. For example myDev = devCreateDev("myDev" DEV_OUTPUTHND, myOutputHnd, NULL); Unset parameters are the to their defaults, usually NULL. DEV_PTR devCreateDev(const char *name, ...); devCreateTTYDev: Same as devCreateDev, except that the defaults are set for a device that opens a tty port for I/O. DEV_PTR devCreateTTYDev(const char *name, ...); devSetParameters: Set parameters for a device. The first parameter is the device data structure. This is followed by a variable length list of parameter name, parameter value pairs. The list is terminated with a NULL parameter. For example devSetParameters(myDev DEV_OUTPUTHND, myOutputHnd, NULL); Unset parameters are left unchanged. void devSetParameters(DEV_PTR device, ...); devSetParameter: Set a parameter for a device. The first parameter is the device data structure. This is followed by a parameter name, parameter value pair. For example devSetParameter(myDev DEV_OUTPUTHND, myOutputHnd); Unset parameters are left unchanged. void devSetParameter(DEV_PTR device, DEV_PARAM_TYPE param, void *value); functions for setting the parameter values one at at time. void devSetUseSimulator(DEV_PTR device, BOOLEAN useSim); void devSetSimMachine(DEV_PTR device, const char *machine); void devSetPort(DEV_PTR device, int port); void devSetBaudRate(DEV_PTR device, int baudRate); void devSetListening(DEV_PTR device, LISTENING_TYPE listen); void devSetDebug(DEV_PTR device, BOOLEAN debug); void devSetDebugFile(DEV_PTR device, FILE *); void devSetOutputHnd(DEV_PTR device, DEVICE_OUTPUT_HND hnd); void devSetSignalHnd(DEV_PTR device, void (* hnd)(DEV_PTR)); void devSetDisconnectHnd(DEV_PTR device, void (* hnd)(DEV_PTR)); void devSetReconnectHnd(DEV_PTR device, void (* hnd)(DEV_PTR)); functions for getting the parameter values one at at time. const char *devGetName(DEV_PTR device); fd_set *devGetFds(DEV_PTR device); BOOLEAN devGetUseSimulator(DEV_PTR device); const char *devGetSimMachine(DEV_PTR device); int devGetPort(DEV_PTR device); int devGetBaudRate(DEV_PTR device); LISTENING_TYPE devGetListening(DEV_PTR device); BOOLEAN devGetDebug(DEV_PTR device); FILE *devGetDebugFile(DEV_PTR device); DEVICE_OUTPUT_HND devGetOutputHnd(DEV_PTR device); DEVICE_HANDLER devGetSignalHnd(DEV_PTR device); DEVICE_HANDLER devGetDisconnectHnd(DEV_PTR device); DEVICE_HANDLER devGetReconnectHnd(DEV_PTR device); devConnect: connect the device according the the parameter settings. void devConnect(DEV_PTR device); devMainLoop: Loop for ever processing events and dispatching them to the correct handlers for each device. void devMainLoop(void); devProcessDevices: Process events for up to maxTime time. If the timeout is NULL, the maximum time to process is infinite. Note that this function will return after 1 or more events have been processed, even if the max allowed time has not elapsed. void devProcessDevices(struct timeval *maxTime); devStartPolling: call the polling routine every interval usecs. Note that because the operating system is not a real time system, the delay in calling the polling routine maybe arbitrarily long. void devStartPolling(DEV_PTR dev, struct timeval *interval, Handler handler, void *data); devStopPolling: stop calling the polling routine. void devStopPolling(DEV_PTR dev); devIsPolling: Returns true if the device is being polled. BOOLEAN devIsPolling(DEV_PTR dev); devSetAlarm: Set an alarm to go off at a specific time. The handler function is called if the alarm goes off. void devSetAlarm(DEV_PTR dev, struct timeval *timeoutTime, Handler timeoutHnd, void *data); devSetTimer: Set an alarm to go off at a delay time from now. The handler function is called if the alarm goes off. void devSetTimer(DEV_PTR dev, struct timeval *delay, Handler timeoutHnd, void *data); devCancelTimeout: remove a timeout set either with setTimeout or setTimer. void devCancelTimeout(DEV_PTR dev); Routines for parsing characters from a device. LINE_BUFFER_POINTER: private structure used to keep track of partial lines and other parsing information. typedef struct _dev_line_buffer_type *DEV_LINE_BUFFER_PTR; devCreateLineBuffer: Create a data structure to keep track of information needed to parse output from a device and dispatch it to a routine for processing. This handles partial lines and more than one line ready for input. The parameters specify how to recognize a "line" processRoutine: function to call when a complete line is recognized. lineLimit: maximum number of characters that can be in a line. For fixed length lines, set this to the expected length. delimChar: Characters that delimit the end of the line. If any character in this string is found it the input, it is taken to be the end of the line. replaceDelimit: Should the delimit character be replaced with '\0' before the parse routine is called? partialLines: Should incomplete lines also be passed to the parser. DEV_LINE_BUFFER_PTR devCreateLineBuffer(int lineLimit, char *delimChar, void (*processRoutine)(char *, void *), BOOLEAN replaceDelimit, BOOLEAN partialLines, void *clientData); devProcessOutput: routine to read characters from the device, parse the input and call the parse routine. void devProcessOutput(DEV_PTR device, int fd, DEV_LINE_BUFFER_PTR lineBuffer, int chars_available); devWaitForResponse: Process events and wait for some event that sets the doneFlage. If timeout time expires first, the return false. BOOLEAN devWaitForResponse(DEV_PTR dev, int *doneFlag, long timeout); #define devExitFromWait(doneFlag) doneFlag = NOT_WAITING; devShutDown: shutdown all devices. void devShutdown(void); I/O functions. devWriteN : Write n characters from a buffer to a given device. Handle pipe brakes and interrupted system calls. BOOLEAN devWriteN(int fd, const char *buf, int nChars); devReadN: Read nchars of data from sd into buf. Continue to read until nchars have been read. Return 0 if end of file reached and -1 if there was an error. Handle pipe breaks. int devReadN(DEV_PTR dev, int fd, char *buf, int nchars); devCharsAvailable : Find out how many characters are available to be read. long devCharsAvailable(int sd); devFlushChars: Flush any characters from the input file descriptor. void devFlushChars(DEV_PTR dev);