\subsection{Object interfaces}\label{inter} In order to present themselves to the system SICS objects need to adhere to certyain interfaces. These interfaces are described in this section. Thus this section is one of the most important sections of theis document, read carefully! A first requirement was that it must be possible to inquire the capabilities of an object at run time. A second one was that the system should be extendable. This means it should be possible to add new interfaces or modify them as the need arises. In order to achieve this the idea of the interface datastructure (INDS) was conceived. An INDS contains all the variables and functions which make up an interface. Then it is possible to create such a datastructure and pass it around. Each object can now be requested to pass an INDS of a certain type on demand. What is still needed is a standard way of asking a SICS object for such a datastructure. This is achieved by the means of the object descriptor. This is a datastructure which contains everything necessary to identify an object to SICS. This requires a convention which is that {\em each SICS objects has to have a pointer to an object descriptor as first element of its own datastructure.} All this probably gets clearer once the actual datastructures have been discussed. As usual, functions return 1 on success and 0 on failure. \subsubsection{The object descriptor} Let's start with the objectdescriptor: \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap1} $\langle$obdes {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@/*--------------------------------------------------------------------------@\\ \mbox{}\verb@ In SICS there is the to find out what an@\\ \mbox{}\verb@ object is capable of at runtime. If this has been done a general@\\ \mbox{}\verb@ way to access those capabilities is needed. In order to do all@\\ \mbox{}\verb@ this each SICS-object is required to carry an object descriptor@\\ \mbox{}\verb@ struct as first parameter in its class/object struct. Additionslly@\\ \mbox{}\verb@ it is required to initialize this struct to something sensible.@\\ \mbox{}\verb@ @\\ \mbox{}\verb@ This file defines this struct. Additionally a few functions of@\\ \mbox{}\verb@ general use are prototyped.@\\ \mbox{}\verb@ @\\ \mbox{}\verb@ Mark Koennecke, June, 1997@\\ \mbox{}\verb@ @\\ \mbox{}\verb@ copyrigth: see implementation file @\\ \mbox{}\verb@----------------------------------------------------------------------------*/@\\ \mbox{}\verb@#ifndef SICSDESCRIPTOR@\\ \mbox{}\verb@#define SICSDESCRIPTOR@\\ \mbox{}\verb@#include @\\ \mbox{}\verb@#include @\\ \mbox{}\verb@#include @\\ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ char *name;@\\ \mbox{}\verb@ int (*SaveStatus)(void *self, char *name,FILE *fd);@\\ \mbox{}\verb@ void *(*GetInterface)(void *self, int iInterfaceID);@\\ \mbox{}\verb@ IPair *pKeys;@\\ \mbox{}\verb@ pHdb parNode;@\\ \mbox{}\verb@ } ObjectDescriptor, *pObjectDescriptor;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ /*---------------------------------------------------------------------------*/@\\ \mbox{}\verb@ pObjectDescriptor CreateDescriptor(char *name);@\\ \mbox{}\verb@ void DeleteDescriptor(pObjectDescriptor self);@\\ \mbox{}\verb@ pObjectDescriptor FindDescriptor(void *pData);@\\ \mbox{}\verb@ @\\ \mbox{}\verb@/*============================================================================@\\ \mbox{}\verb@ Objects which do not carry data need a dummy descriptor. Otherwise@\\ \mbox{}\verb@ drive or scan will protection fault when trying to drive something@\\ \mbox{}\verb@ which should not be driven. This is defined below.@\\ \mbox{}\verb@*/@\\ \mbox{}\verb@@\\ \mbox{}\verb@typedef struct {@\\ \mbox{}\verb@ pObjectDescriptor pDescriptor;@\\ \mbox{}\verb@ }Dummy, *pDummy;@\\ \mbox{}\verb@ @\\ \mbox{}\verb@@\\ \mbox{}\verb@ pDummy CreateDummy(char *name);@\\ \mbox{}\verb@ void KillDummy(void *pData); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ int iHasType(void *pData, char *Type);@\\ \mbox{}\verb@ @\\ \mbox{}\verb@#endif @\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} The first element of the object descriptor is a {\bf name} which is better described as a type identifier. This specifies the type of the object. The function {\bf SaveStatus} will be called automatically by SICS when the server is closing down or a status backup is requested. Each object is meant to print the commands necessary to configure it back into its current state into the file passed as a parameter. The idea is that by executing the file thus created the system gets back into the state before closedown. The heart of the interface system is the {\bf GetInterface} function. It takes as arguments a pointer to the datastructure on which it is called and an integer ID for the interface. These ID's are defined in the file interface.h. This function is meant to return a pointer to the apropriate interface datastructure after this call. If the object does not implement the interface requested, this function should return NULL. New interfaces can be added into the scheme by defining new ID's, interfaces and objects which implement them. It is {\bf important} to note, that the objects themselves are responsible for allocating and freeing memory for the interface structures. Client never should need to worry how to dispose of these structures. Moreover this scheme ensures that changes to the interface due to some command given to the object are immediatetly visible through the whole system. Additionally this header file defines a few relatively uninteresting functions for object descriptor maintainance. Slightly more interesting is the Dummy structure, which will be used to find the object descriptor in a given objects data structure. \subsubsection{The drivable interface} As first example of an interface the drivable interface will be given. This interface is implemented by all devices or varaibles which can be driven to a value. Most notable example are motors, but composite variables and environment controllers fit this bill as well. \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap2} $\langle$driv {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ int ID;@\\ \mbox{}\verb@ int (*Halt)(void *self);@\\ \mbox{}\verb@ int (*CheckLimits)(void *self, float fVal, @\\ \mbox{}\verb@ char *error, int iErrLen);@\\ \mbox{}\verb@ long (*SetValue)(void *self, SConnection *pCon,@\\ \mbox{}\verb@ float fVal);@\\ \mbox{}\verb@ int (*CheckStatus)(void *self, SConnection *pCon);@\\ \mbox{}\verb@ float (*GetValue)(void *self, SConnection *pCon); @\\ \mbox{}\verb@ int iErrorCount;@\\ \mbox{}\verb@ int drivableStatus;@\\ \mbox{}\verb@ } IDrivable, *pIDrivable;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ pIDrivable GetDrivableInterface(void *pObject); @\\ \mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\ \mbox{}\verb@ float *fPos);@\\ \mbox{}\verb@@\\ \mbox{}\verb@ long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);@\\ \mbox{}\verb@@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} The first member of this structure is an ID which can be used in order to check if the right datastructure has been obtained. The second field is a pointer to a {\bf Halt} function. This function will be called in an emergency and is meant to send a stop command to the device. The third field is a pointer to the {\bf CheckLimits} function. This function is given a float value as second parameter. This is the new value the device should go to. CheckLimits checks if this position is permitted. If so it returns 1 else 0. The {\bf SetValue} member is a pointer to a function which actually makes the object start to move to its new position. The {\bf CheckStatus} function will be called in order to check for the current status of the device during operation. Possible return values are: \begin{itemize} \item OKOK if everything is OK. \item HWIdle if the device is idle i. e. doing nothing. \item HWFault if the device is in trouble. \item HWBusy if the device is still running. \item HWPosFault when the device is principally OK but has not reached the position specified, for instance because somebody has put a slab of concrete into the instruments way. \end{itemize} The last function which makes up this interface is {\bf GetValue} which is meant to return the current position of the device. {\bf iErrorCount} is the number of number of failed driving commands on this drivable item. This can be used by motors to check and abort the experiment if there are to many errors. This is to stop a scan command hammer at a blocked motor a hundred times. {\bf GetDrivableInterface} is a convenience function which checks object pData for the existence of a drivable interface. If it exists a pointer to it will be returned. NEVER free this pointer. If no drivable interface exists, NULL will be returned. {\bf GetDrivablePosition retrieves the position of the drivabel object. If the device is a motor corrections for zero points and signs will be applied. Returns 1 on success and 0 on failure} {\bf StartDriveTask starts a drivable in a new task. If the task can be started, its task ID is returned. -1 is returned on failure. } \subsubsection{The Countable Interface} This is an interface for interacting with anything which counts. \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap3} $\langle$count {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ int ID;@\\ \mbox{}\verb@ int running;@\\ \mbox{}\verb@ int (*Halt)(void *self);@\\ \mbox{}\verb@ void (*SetCountParameters)(void *self, float fPreset,@\\ \mbox{}\verb@ CounterMode eMode);\@\\ \mbox{}\verb@ int (*StartCount)(void *self, SConnection *pCon);@\\ \mbox{}\verb@ int (*CheckCountStatus)(void *self, SConnection *pCon);@\\ \mbox{}\verb@ int (*Pause)(void *self, SConnection *pCon);@\\ \mbox{}\verb@ int (*Continue)(void *self, SConnection *pCon);@\\ \mbox{}\verb@ int (*TransferData)(void *self, SConnection *pCon);@\\ \mbox{}\verb@ } ICountable, *pICountable;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICountable GetCountableInterface(void *pObject); @\\ \mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\ \mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\ \mbox{}\verb@ int isRunning(pICountable self);@\\ \mbox{}\verb@ long StartCountTask(void *self, SConnection *pCon, char *name);@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} {\bf running } Is a flag which says if the counter is operating or not. {\bf Halt and StartCount} are self explaining, they just do what they say. Please note, that counting configuration must have happened before usage of this interface. {\bf Pause} pauses a data aquisition. It does NOT abort it. {\bf Continue} continues a paused data aquisition. {\bf CheckCountStatus} works much like CheckStatus in the IDrivable interface described above. However, there is an additional return code: HWNoBeam. This is retuned if a monitor is below a certain threshold, i. e. the beam is off. {\bf TransferData} will be called at the end of each counting operation and is meant to update the internal datastructures of the counter. Some counters choose to keep the last count in their own datastructure, some such as histogram memories might choose to leave them in the hardware. This function has been conceived in order to ensure that the first type of counters is supported. {\bf GetCountableInterface} is a convenience function which checks object pData for the existence of a countable interface. If it exists a pointer to it will be returned. NEVER free this pointer. If no countable interface exists, NULL will be returned. {\bf GetCountLock} will try to set the running flag. If it is already running, an error is printed to pCon and 0 is returned. {\bf ReleaseCountLock} release the count lock. {\bf isRunning} returns the running flag. {\bf StartCountTask starts a countable in a new task. If the task can be started, its task ID is returned. -1 is returned on failure. } \subsubsection{The Callback Interface} The Callback Interface is SICS suport for component behaviour for objects. Consider objects A and B. A now is able to generate certain events when it's state changes. For instance if A is a variable that its value is changed. B may then choose to register a function with A which gets automatically called whenever A generates the apropriate event. B is thus automatically notified about A's status change and can act accordingly to it. In contrast to the interfaces defined above, this interface is defined in terms of a set of functions which manipulate the interface and not as a data structure of overloadable functions. The first thing to define for such an interface is the type of the callback function: \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap4} $\langle$callfunc {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ typedef void (*KillFuncIT)(void *pData);@\\ \mbox{}\verb@ typedef int (*SICSCallBack)(int iEvent, void *pEventData, @\\ \mbox{}\verb@ void *pUserData);@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} The callback function is meant to return 0 for failure or 1 for success. This infomation may be needed by an event invoking object if to continue an operation or not. The first parameter passed to {\bf SICSCallBack} is the id of the generated event. Clearly the communicating objects need to agree on these event. In SICS events types will be held in an header file event.h. The next parameter to SICSCallBack is a pointer to void. The event generating object may choose to pass additional data along with the event. Suitable event datastructures are also defined in event.h. The last parameter to SICSCallBack is a pointer to a datastructure defined by the owner of the callback routine when registering the callback. {\bf pKill} is a function which will be called automatically when the callback is deleted and whose sole task is to delete pUserData properly. Then there are the functions needed to interface with the callback interface: \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap5} $\langle$cifunc {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct __ICallBack *pICallBack;@\\ \mbox{}\verb@ @\\ \mbox{}\verb@ /* event source side */@\\ \mbox{}\verb@ pICallBack CreateCallBackInterface(void);@\\ \mbox{}\verb@ void DeleteCallBackInterface(pICallBack self);@\\ \mbox{}\verb@ int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ /* callback client side */@\\ \mbox{}\verb@ long RegisterCallback(pICallBack pInterface, @\\ \mbox{}\verb@ int iEvent, SICSCallBack pFunc,@\\ \mbox{}\verb@ void *pUserData, KillFuncIT pKill);@\\ \mbox{}\verb@ int RemoveCallback(pICallBack pInterface, long iID);@\\ \mbox{}\verb@ int RemoveCallback2(pICallBack pInterface, void *pUserData);@\\ \mbox{}\verb@ int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);@\\ \mbox{}\verb@@\\ \mbox{}\verb@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICallBack GetCallbackInterface(void *pData); @\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} The callback interface has two parts: A part the event generating object has to deal with and a part the interested object has to use. There is no way of enforcing this convention. However, SICS programmers should stick to it, otherwise weird things may happen. The first two functions just deal with creating and deleting the callback interface data structure. {\bf CreateCallBackInterface} returns NULL if the request fails, or a pointer on success. {\bf InvokeCallBack} is responsible for invoking the registered callback functions and will be called only by the source object for the event. This function will scan the list of registered callback function for callback function which are registered for the event ID specified as second parameter. Each of them will be invoked with the event data given as third parameter. If any of the callback functions returns Failure this function will do so as well. Else 1 is returned. The event data structure belongs to the object invoking the callback. It should never be deleted in callback functions. The next functions deal with the client side of the callback interface. {\bf RegisterCallBack} registers a callback function with the interface. The first parameter is the interface to register the callback with. The second parameter is the event ID for which this callback is defined. pFunc is the pointer to the actual callback function. Finally pUserData is a pointer to some user defined data structure which shall be passed as pUserData when the callback is called. RegisterCallback retuns a long value which server as an identifier for the callback registration. If the registration fails, this function returns 0. {\bf RemoveCallBack} is used to delete a registered callback. The first parameter is the interface to act upon, the second is the callback ID as returned by RegisterCallBack. {\bf RemoveCallback2} is another variant for removing callbacks. This time the search key for deletion is the pointer to user data. All callbacks related to this user data in the interface specified will be removed. {\bf RemoveCallbackCon} is another variant for removing callbacks. This time the search key for deletion is the pointer to user data which must be a connection object. All callbacks related to this connection in the interface specified will be removed. This is a convenience function for removing interest callbacks in SICS. {\bf CallbackScript} allows to connect callbacks to scripts. Please note, that those scripts will have a dummy connection to clients only and will not be able to write to clients. All output occurring in these scripts will be directed to stdout though, in order to support debugging. All these functions are implemented in the file callback.c. \subsubsection{The Environment Interface} This interface is used by the environment monitor in order to monitor the status of a environment controller. The interface looks like this: \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap6} $\langle$envir {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ int iID;@\\ \mbox{}\verb@ EVMode (*GetMode)(void *self);@\\ \mbox{}\verb@ int (*IsInTolerance)(void *self);@\\ \mbox{}\verb@ int (*HandleError)(void *self);@\\ \mbox{}\verb@ } EVInterface, *pEVInterface;@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} The enum {\bf EVMode} describes the mode a environment controller can be in. The default is Idle, no action necessary. EVDrive means that the controller is currently being driven to a new value and the device executor has control. EVMonitor means that the environment monitor has to take care of the controller. EVError is set if the controller is out of tolerances. {\bf GetMode} retrieves the current operation mode of the controller. {\bf IsInTolerance} returns 1 if the controller is still within tolerances, 0 otherwise. {\bf HandleError} will be automatically called when IsInTolerance returns 0. Its purpose is to implemnt the error handling startegy for the controller in question. The environment interface has just one function associated with it: \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap7} $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ pEVInterface CreateEVInterface(void);@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} \begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} \item Macro referenced in scrap ?. \end{list} \end{minipage}\\[4ex] \end{flushleft} {\bf CreateEVInterface} just creates an environment interface. \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap8} \verb@"obdes.h"@ {\footnotesize ? }$\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@@$\langle$obdes {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@/*--------------------------------------------------------------------------*/@\\ \mbox{}\verb@/* Additional properties used by the ANSTO site to provide more information@\\ \mbox{}\verb@ * about each object instance, especially devices.@\\ \mbox{}\verb@ */@\\ \mbox{}\verb@ void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value);@\\ \mbox{}\verb@ void SetDescriptorGroup(pObjectDescriptor self, char *group);@\\ \mbox{}\verb@ void SetDescriptorDescription(pObjectDescriptor self, char *description);@\\ \mbox{}\verb@ char * GetDescriptorKey(pObjectDescriptor self, char *keyName);@\\ \mbox{}\verb@ char * GetDescriptorGroup(pObjectDescriptor self);@\\ \mbox{}\verb@ char * GetDescriptorDescription(pObjectDescriptor self);@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] \end{flushleft} \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap9} \verb@"interface.h"@ {\footnotesize ? }$\equiv$ \vspace{-1ex} \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@/*---------------------------------------------------------------------------@\\ \mbox{}\verb@ I N T E R F A C E S@\\ \mbox{}\verb@@\\ \mbox{}\verb@ Any object in SICS has to adhere to the object descriptor interface (see@\\ \mbox{}\verb@ file obdes.h). Furthermore SICS objects may choose to support other@\\ \mbox{}\verb@ interfaces as well. These interfaces are defined.@\\ \mbox{}\verb@@\\ \mbox{}\verb@ Mark Koennecke, June 1997@\\ \mbox{}\verb@@\\ \mbox{}\verb@ For more documentation see interface.w, interface.tex@\\ \mbox{}\verb@@\\ \mbox{}\verb@ copyright: see SICS impelementation files@\\ \mbox{}\verb@---------------------------------------------------------------------------*/@\\ \mbox{}\verb@@\\ \mbox{}\verb@#ifndef SICSINTERFACES@\\ \mbox{}\verb@#define SICSINTERFACES@\\ \mbox{}\verb@#include "commandcontext.h"@\\ \mbox{}\verb@@\\ \mbox{}\verb@/* interface ID's used to recognize an interface */@\\ \mbox{}\verb@#define DRIVEID 513@\\ \mbox{}\verb@#define COUNTID 713@\\ \mbox{}\verb@#define CALLBACKINTERFACE 947@\\ \mbox{}\verb@#define ENVIRINTERFACE 949@\\ \mbox{}\verb@@\\ \mbox{}\verb@/* ----------------------- The drivable interface -----------------------*/@\\ \mbox{}\verb@@$\langle$driv {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@\\ \mbox{}\verb@ pIDrivable CreateDrivableInterface(void);@\\ \mbox{}\verb@@\\ \mbox{}\verb@/* ------------------------ The countable interface ---------------------*/@\\ \mbox{}\verb@@$\langle$count {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICountable CreateCountableInterface(void);@\\ \mbox{}\verb@@\\ \mbox{}\verb@/* ------------------------- The CallBack Interface --------------------*/@\\ \mbox{}\verb@@$\langle$callfunc {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@$\langle$cifunc {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@/*---------------------- The Environment Interface --------------------*/@\\ \mbox{}\verb@@$\langle$envir {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@$\langle$envfunc {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] \end{flushleft} \subsection{More interfaces} For completeness it should be mentioned that besides these interfaces there exist further important interfaces in SICS. This includes the interface to the SICS interpreter defined in \ref{scinter}. Furthermore the data structures defined for the various types of drivers within SICS may be considered interfaces as well. Then there is the interface to the client as defined by the functions of the connection interface.