Privacy and Security Notice

CDEV Documentation



A CDEV Tutorial

Techniques for using the Control Device Interface

Chip Watson, Jie Chen, Danjin Wu, Walt Akers

Version 1.5 - December 9, 1996

TJNAF - Thomas Jefferson National Accelerator Facility




Table of Contents

1.
Developing CDEV Applications

Overview

Steps in Developing a CDEV Application
2.
Developing Device Definition Language Files

Device Definition Language (DDL) File Overview

Service Definitions

Class Definitions

Verb Definitions

Class Inheritance

Attribute Definitions

Attribute Service Data

Message Definitions

Device Instances

Device Name Substitution

Device Name Aliasing

Defining cdevCollections

#include Directive

Sample DDL
3.
Using the cdevSystem Object

Overview of the cdevSystem Class

Public Functions of the cdevSystem Class

attachRef

attachPtr

defaultSystem

getDevice

getRequestObject

name

prefix

prefix

flush

poll

pend

pend

getFd

addFdChanged Callback

autoErrorOn

autoErrorOff

reportError

setErrorHandler

setThreshold

Sample Code
4.
Using the cdevDevice Object

Overview of the cdevDevice Class

Public Functions of the cdevDevice Class

attachRef

attachPtr

detach

detach

getRequestObject

name

system

setContext

getContext

setPrivate

getPrivate

send

sendNoBlock

sendCallback

Sample Code

Attaching to a cdevDevice Object

Getting and Setting Context for a cdevDevice

Sending Messages to a Device Synchronously

Sending Messages to a Device Asynchronously

Using sendNoBlock

Managing sendNoBlock Messages with the cdevSystem object

Grouping sendNoBlock Messages with cdevGroup

Using deferred groups for repeating lists of operations

Using sendCallback
5.
Using the cdevRequestObject Object

Overview of the cdevRequestObject Class

Public Member Functions of the cdevRequestObject Class

attachRef

attachRef

attachPtr

attachPtr

detach

detach

message

device

system

service

getState

getAccess

setContext

getContext

getPrivate

setPrivate

send

sendNoBlock

sendCallback

Sample Code

Attaching to a cdevRequestObject Object

Getting and Setting Context for a cdevRequestObject

Sending Messages to a Device Synchronously

Sending Messages to a Device Asynchronously

Using sendNoBlock

Managing sendNoBlock Messages with the cdevSystem object

Grouping sendNoBlock Messages with cdevGroup

Using deferred groups for repeating lists of operations

Using sendCallback
6.
Using the cdevData Object

Overview of the cdevData Class

cdevData Tags

XDR Packaging of cdevData Objects

Public Functions of the cdevData Class

tagC2I

tagI2C

insertTag

operator =

Cast operators

asciiDump

xdrSize

xdrExport

xdrExport

xdrImport

remove

changeTag

getType

getDim

getElems

getBounds

setBounds

insert (scalar)

insert (array)

insert (character string)

get

get (character string)

find

Sample Code
7.
Using the cdevDirectory Device

cdevDirectory Device

Attaching to the cdevDirectory

Messages Supported by cdevDirectory

"query"

"queryClass"

"queryAttributes"

"queryMessages"

"queryVerbs"

"service"

"serviceData"

"update"

"validate"
8.
Default Service Behavior for Standard Messages

Overview

"get" Message

"set" Message

"monitorOn" Message

CDEV_SUCCESS:

CDEV_DISCONNECTED:

CDEV_RECONNECTED:

CDEV_ERROR:

CDEV_INVALIDOBJ:

CDEV_INVALIDARG:

CDEV_INVALIDSVC:

CDEV_NOTCONNECTED:

CDEV_IOFAILED:

CDEV_CONFLICT:

CDEV_NOTFOUND:

CDEV_TIMEOUT:

CDEV_CONVERT:

CDEV_OUTOFRANGE:

CDEV_NOACCESS:

CDEV_ACCESSCHANGED:

"monitorOff" Message

device

attribute

function

userarg



List of Figures

Figure 1: Service definitions in the CDEV DDL file
Figure 2: CDEV DDL class definition containing a list of verbs
Figure 3: CDEV DDL class definition using inheritance
Figure 4: CDEV DDL class definition containing a list of attributes
Figure 5: CDEV DDL class definition containing a list of messages
Figure 6: CDEV DDL class definition to instantiate a list of devices
Figure 7: Implementing device name substitution in a CDEV DDL file
Figure 8: Implementing device name aliasing in a CDEV DDL file
Figure 9: cdevCollection Definition in the CDEV DDL File
Figure 10: Using the #include directive in a CDEV DDL file
Figure 11: Sample complete DDL file
Figure 12: Methods for obtaining a cdevSystem object
Figure 13: Installing a user specified error handler
Figure 14: Return codes generated by the send method
Figure 15: Attaching to a cdevDevice object
Figure 16: Altering the context of a cdevDevice object
Figure 17: Using the send method of a cdevDevice object
Figure 18: Using sendNoBlock to communicate with a cdevDevice
Figure 19: Using the sendCallback method of a cdevDevice object
Figure 20: Return codes generated by the send method
Figure 21: Obtaining a cdevRequestObject from a cdevDevice object
Figure 22: Altering the context of a cdevRequestObject object
Figure 23: Using the send method of a cdevRequestObject object
Figure 24: Using sendNoBlock to communicate with a cdevRequestObject
Figure 25: Using the sendCallback method of a cdevRequestObject object
Figure 26: Using insertTag to add a new tag
Figure 27: Using tagC2I and tagI2C to determine cdevData tag identifiers
Figure 28: Inserting and retrieving scalar data items using a cdevData object
Figure 29: Using the changeTag method of the cdevData object
Figure 30: Using one-dimensional arrays with cdevData objects
Figure 31: Using multi-dimensional arrays with cdevData objects
Figure 32: Using character strings with cdevData objects
Figure 33: Using character string arrays with cdevData objects
Figure 34: Using the find method of the cdevData object
Figure 35: Attaching to the cdevDirectory device
Figure 36: cdevData Input/Output associated with a "query" message
Figure 37: Using the "query" Message with a cdevDirectory device
Figure 38: cdevData input/output associated with a "queryClass" message
Figure 39: Using the "queryClass" message with a cdevDirectory device
Figure 40: cdevData input/output associated with a "queryAttributes" message
Figure 41: Using the "queryAttributes" message with a cdevDirectory device
Figure 42: cdevData input/output associated with a "queryMessages" message
Figure 43: Using the "queryMessages" message with a cdevDirectory device
Figure 44: cdevData input/output associated with a "queryVerbs" message
Figure 45: Using the "queryVerbs" message with a cdevDirectory device
Figure 46: cdevData input/output associated with a "service" message
Figure 47: Using the "service" message with a cdevDirectory device
Figure 48: cdevData input/output associated with a "serviceData" message
Figure 49: Using the "serviceData" message with a cdevDirectory device
Figure 50: cdevData input/output associated with a "update" message
Figure 51: Using the "update" message with a cdevDirectory device
Figure 52: cdevData input/output associated with a "validate" message
Figure 53: Using the "update" message with a cdevDirectory device
Figure 54: Default behavior of the "get" and "set" messages
Figure 55: Default behavior of the "monitorOn" and "monitorOff" messages



1.

Developing CDEV Applications

Overview

The purpose of this section is to describe the steps that a CDEV user must perform in order to effectively develop a CDEV application. This section assumes that the user is either using one of the CDEV services provided in the CDEV distribution, or has a local or third party developed CDEV service with which the application will communicate.

Steps in Developing a CDEV Application

1.

Construct a CDEV device definition file. The CDEV device definition file is the roadmap that CDEV uses to define services and determine which device and message combinations are associated with those services. This file should be constructed and defined in the CDEVDDL environment variable prior to executing a CDEV application. Check with the CDEV adminstrator to determine if this file already exists on your system.

2.

Design and write your source code. This step is intentional broad in scope because the capabilities provided by various CDEV services may be completely dissimilar in nature. The primary capability that CDEV provides is standardization of the interface between any application and any underlying CDEV service.

3.

Compile and link application with the CDEV library. This step requires the source code to include the necessary CDEV C++ header files and linking with the libcdev.sl or libcdev.a libraries.

4.

Set any required environment variables. The primary environment variables required by CDEV are CDEVSHOBJ and CDEVDDL. CDEVSHOBJ is used to located shared objects, and cdevddl is used to specify the complete path to the CDEV device definition file. Individual services may have additional requirements.

5.

Execute your application.

Note: Applications linked with the archive library are not capable of loading dynamically loadable CDEV services.

2.

Developing Device Definition Language Files

Device Definition Language (DDL) File Overview

The Device Definition Language File or DDL File is the roadmap that CDEV uses to associate certain device and message combinations with a CDEV service. The DDL file provides the mechanism for defining service definitions, class definitions and instance definitions.

Service Definitions

The service definition is used to publicly define the existence of a CDEV service. The service definition declares the name of the service and the names of any special cdevData tags that the service will use. The following is a simple service definition.

Figure 1: Service definitions in the CDEV DDL file

/* 
 * Definition of service X 
 */
service x
   {
   tags { tag1, tag2 }
   }
 
/* 
 * Definition of service y
 */
service y
   {
   tags {}
   }
			

The service definition above defines the service "x" and service "y". During the execution of a CDEV application, when a device and message combination is related to the "x" service, CDEV will attempt to load the dynamic library for the service. By convention the name of the library will be "xService.so", where "x" is the name of the service within the DDL file.

The service definition also defines the tags "tag1" and "tag2" in conjunction with service "x". These tags will be used later to define special service data that is related to a specific device attribute. Service "y" has no special tags associated with it.

This example also illustrates the formats of comments within the DDL file. The syntax of the DDL file accommodates the use of C style multi-line comments.

Class Definitions

The class definition is used within the DDL file to declare a collection of verbs, attributes or messages that may be applied to one or more CDEV device instances.

Verb Definitions

The following examples shows the syntax for declaring a class definition that contains only a list of verbs.

Figure 2: CDEV DDL class definition containing a list of verbs

 
 
class stdio
   {
   verbs { get, set, monitorOn, monitorOff }
   }
			

In the above example, the "stdio" class is defined and it is declared to contain four verbs: get, set, monitorOn and monitorOff. Any other class that is derived from this class, or any device that is instantiated from this class will inherit these four verbs.

Class Inheritance

The CDEV DDL file supports the notion of inheriting one class from another class. The pre-existing class is called the super-class, while the class that is inheriting from the pre-existing class is called the sub-class. To specify inheritance within the CDEV DDL file, the syntax is similar to the syntax used in C++. The name of the new class is followed by a colon, which is followed by the name of the super-class.

In order to support the possibility of a colon as a character in the class name, a space must separate the name of the class and the colon.

In the next example, the "magnetIO" class is defined. This class inherits from the "stdio" class, and receives the verbs get, set, monitorOn, and monitorOff. To this list of verbs, it adds a new verb: "reset".

Figure 3: CDEV DDL class definition using inheritance

class stdio
   {
   verbs { get, set, monitorOn, monitorOff }
   }
 
class magnetIO : stdio
   {
   verbs { reset }
   }
			

Attribute Definitions

Class definitions are also used to define attributes. An attribute is a component of a CDEV device that can be combined with a verb to define a message. When an attribute is declared within a class, CDEV will assume that the attribute supports each of the verbs that exist within the class.

Attribute Service Data

When the attribute is defined, the user must define the name of the service that will receive the messages associated with it, and any service data that is associated with it. This service data is defined using the tag names that are declared in the tags section of the service definition.

The following example declares the class "element". This class inherits its verbs from the "stdio" class. Each attribute is associated with a service name and is followed by service data.

Figure 4: CDEV DDL class definition containing a list of attributes

/***************************** 
 * Definition of service X 
 *****************************/
service x
   {
   tags { tag1, tag2 }
   }
 
/*****************************
 * Definition of stdio class
 *****************************/
class stdio
   {
   verbs { get, set, monitorOn, monitorOff }
   }
 
/*****************************
 * Definition of element class
 *****************************/
class element : stdio
   {
   attributes 
      {
      value1 x {tag1=1.0, tag2=Value};
      }
   }
			

Service data also supports the notion of expression replacement. If the character string "<>" appears in the service data, it will be replaced with the instance name of the device that is instantiated from this class.

Message Definitions

A message definition can be declared within a CDEV DDL class definition to define one word atomic commands. Unlike attributes and verbs, a message is a stand-alone instruction that can be sent to a device.

The structure of a message definition is similar to the attribute definition. The entries in this section contain the name of the service and special service data that is associated with the message.

The following example shows a class that contains a single message definition. Note that the class does not define any verbs or attributes.

Figure 5: CDEV DDL class definition containing a list of messages

/***************************** 
 * Definition of service X 
 *****************************/
service x
   {
   tags { tag1, tag2 }
   }
 
/*****************************
 * Definition of element class
 *****************************/
class element
   {
   messages 
      {
      on x {tag1=<>.Val, tag2=Text};
      }
   }
			

Device Instances

The device instances section is where devices are created from class definitions. Each device that is instantiated from a class inherits all of the verbs, attributes and messages from that class, as well as from each class that it inherits from.

The syntax for instantiating a device is as follows: the name of the class, followed by a colon, followed by the list of device names that are being defined. The following figure shows the syntax for defining a list of devices of the "element" class.

Figure 6: CDEV DDL class definition to instantiate a list of devices

/*****************************
 * Instantiation of devices
 *****************************/
 
element :
   device1
   device2
   device3;
			


 
	
Device Name Substitution

As described earlier, angle braces "<>" in the service data definition for an attribute will be replaced with the name of its associated device. A name substitution technique is available that allows the DDL writer to specify that a different device name should be inserted. The substitution device name is specified in conjunction with the actual device name when the device is instanciated.

The following example illustrates the syntax for instantiating a device and specifing a substitute name for it. In this example, the string "device1" will be substituted wherever the string "dev1" would normally be used.

Figure 7: Implementing device name substitution in a CDEV DDL file

/*****************************
 * Device name substitution
 *****************************/
 
element :
   dev1 {device1}
   device2
   device3;
			

Device Name Aliasing

Device name aliasing is a more powerful alternative to device name substitution. A device's alias may be used in applications to obtain and communicate with its corresponding device. Device name aliases are specified in the DDL file on an individual basis by using the alias keyword.

The syntax for adding an alias to a device is illustrated in the example below. In this example, the alias "dev1" can be used interchangably with the actual device name "device1".

Figure 8: Implementing device name aliasing in a CDEV DDL file

/*****************************
 * Device name aliasing
 *****************************/
 
 
 
 
alias dev1 device1
			


 
	
Defining cdevCollections

A cdevCollection device can be implemented in one of two ways; the developer can create an empty cdevCollection dynamically and add devices to it, or a collection entry can be placed in the CDEV DDL file that identifies the collection and its constituent devices. The syntax for defining a cdevCollection device in the CDEV DDL file is as follows.

Figure 9: cdevCollection Definition in the CDEV DDL File

collection cDevice1 : 
device0, 
device1, 
device2 
;
 
collection cDevice2 : 
device3 
device4 
device5
;
			

In the example above two cdevCollections are defined. A cdevCollection definition is started by using the keyword "collection", followed by a space and then the name of the collection. Note that the name of the collection must be unique and cannot be shared with any other device in the CDEV system.

The device name is followed by a white space character (which is required), and then a colon, followed by another white space character and then the list of devices. The device names that are in the list may be separated by either white space of a comma delimiter. The list of devices is terminated by a semicolon.

The current implementation of the CDEV DDL is order dependent. Because of this, the developer should place the collection definitions after the definitions of all devices and aliases.

#include Directive

The #include directive is supported within the CDEV DDL file syntax. This directive is used to include the contents of another DDL file within the current DDL file. The syntax is the same as its C language counterpart.

Figure 10: Using the #include directive in a CDEV DDL file

#include "filename.ddl"
			


 
	

Sample DDL

The following sample DDL file demonstrates all current features of the Device Definition Language.

Figure 11: Sample complete DDL file

/*****************************************************************
 * Service Definitions:
 * This section contains the definitions for individual services.
 *****************************************************************/
 
/*****************************************************************
 * ca Service (channel access)
 * The library caService.so will be loaded and called whenever a
 * call to this service needs to be executed.
 *
 * This services support the following special tags:
 *   PV       = Process Variable: this tag is used to specify the
 *              actual name of the attribute that is being 
 *              defined.
 *   READONLY = This is a logical tag that indicates if the 
 *              attribute is readonly (1) or read/write (0).
 *****************************************************************/
service ca {
   tags { PV, READONLY }
   }
 
/*****************************************************************
 * Class Definitions
 * This section contains the definition for individual classes.
 *****************************************************************/
 
/*****************************************************************
 * stdio Class:
 * This class defines the basic set of verbs that will be 
 * supported by all other classes in this DDL file.  The verbs
 * declared in this class are:
 *     get        = Get the value of an attribute of a device
 *     set        = Set the value of an attribute of a device
 *     monitorOn  = Monitor changes of an attribute's value
 *     monitorOff = End monitoring changes of an attribute's value
 *****************************************************************/
class stdio {
   verbs { get, set, monitorOn, monitorOff }
   }
 
			

Figure 11: Sample complete DDL file (continued)

/*****************************************************************
 * magnet Class:
 * This class inherits its list of verbs from the stdio class.  It
 * then adds a list of attributes that these verbs may operate
 * on.  The following attributes are specified.
 *
 *    current  : The current attribute will be serviced by ca.
 *    bdl      : The bdl attribute will be serviced by ca.
 *    length   : The length attribute will be serviced by ca.
 *
 * This class also supports the messages "on" and "off".  For 
 * illustration purposes, these messages will operate on the val
 * field, and therefore, have the same service data.
 *****************************************************************/
class magnet : stdio
   {
   attributes {
      current ca {PV=<>.VAL, READONLY=0};
      bdl     ca {PV=BDL_<>.VAL, READONLY=0};
      length  ca {PV=LEN_<>.VAL, READONLY=1};
      }
   messages {
      on  ca {PV=<>.VAL, READONLY=0};
      off ca {PV=<>.VAL, READONLY=0};
      }   
   }
 
/*****************************************************************
 * Device Instances:
 * This section contains the instantiations of individual devices.
 *****************************************************************/
 
/*****************************************************************
 * The following is a list of devices that are memebers of the
 * magnet class.  That means that each of these devices supports
 * all of the attributes, verbs and messages that are defined by 
 * the magnet class and the stdio class that it inherits from.
 *****************************************************************/
magnet :
   MQB1S01
   MQB1S02
   MQB1S03
   MQB1S04
 
/*****************************************************************
 * End of Device Definition File
 *****************************************************************/
			

3.

Using the cdevSystem Object

Overview of the cdevSystem Class

The cdevSystem C++ class can be described as a communications junction between a CDEV application and CDEV services. The cdevSystem object is responsible for interpreting the device definition file, dynamically loading CDEV services upon request, detecting and responding to I/O events, and providing a mechanism for polling services for updates.

Currently, only the default cdevSystem object may be used within an application. Ultimately, multiple cdevSystem objects may be created, and each of them will maintain individual copies of CDEV services and devices within them.

Most CDEV classes that are accessed directly by applications have static factories (special constructors). Any CDEV object that is constructed by one of these factories is automatically a member of the default cdevSystem.

Public Functions of the cdevSystem Class

attachRef

static cdevSystem& attachRef(char *name, char *prefix);

Obtains a reference to a new or existing cdevSystem object that has the specified name. The prefix parameter is optional, but, if provided will be prepended to the name of each device that is requested through the named cdevSystem object before it is found in the device definition file.

attachPtr

static cdevSystem* attachPtr(char *name, char *prefix);

Obtains a pointer to a new or existing cdevSystem object that has the specified name. The prefix parameter is optional, but, if provided will be prepended to the name of each device that is requested through the named cdevSystem object before it is found in the device definition file.

defaultSystem

static cdevSystem &defaultSystem (void);

Obtains a reference to the default cdevSystem object. In most applications this mechanism is used to access the cdevSystem object.

getDevice

cdevDevice* getDevice (char *device);

Retrieves a pointer to a cdevDevice object by name. The object that is returned by this function will be owned and controlled by the cdevSystem object that created it. This means that flush, poll and pend commands must be routed through the owning cdevSystem object in order to effect this cdevDevice object.

getRequestObject

int getRequestObject ( char *device, char *msg,

cdevRequestObject &req);

Retrieves a reference to a cdevRequestObject from a specified device name and message name. The object that is produced by this function will be owned and controlled by the cdevSystem object that created it. This means that flush, poll and pend commands must be routed through the owning cdevSystem object in order to effect this cdevRequestObject. Returns CDEV_SUCCESS or an enumerated error code.

name

char *name (void);

Returns the name of this cdevSystem object.

prefix

char *prefix (void);

Retrieves a pointer to the prefix string that is currently being used by the cdevSystem object. See the attachPtr entry for a description of the prefix string.

prefix

void prefix (char *pre);

Changes the prefix string that is being used by the cdevSystem object. See the attachPtr entry for a description of the prefix string.

flush

int flush (void);

Flushes any pending outbound requests to their respective services.

poll

int poll (void);

Directly polls each of the cdevSystem's underlying services for activity, and delivers any asynchronous callbacks that are ready.

pend

int pend (int fd);

Waits for a default period of time for the specified file descriptor to have an I/O event. If the fd parameter is not provided, the cdevSystem object will wait for an I/O event on any of its contained file descriptors. When an event occurs on one of the file descriptors, the cdevSystem object will call the respective cdevService to process the event and dispatch any asynchronous callbacks that are ready.

pend

int pend (double seconds, int fd);

Processes all I/O events that occur on the file descriptor during the specified period of time. If the fd parameter is not provided, the cdevSystem object will wait for I/O events on all of its contained file descriptors. When an event occurs on one of the file descriptors, the cdevSystem object will call the respective cdevService to process the event and dispatch any asynchronous callbacks that are ready.

getFd

int getFd (int fd[], int &numFD);

Retrieves a list of file descriptors that are contained within the cdevSystem object. The fd array must be preallocated, and the maximum number of elements should be specified in the numFD parameter. Upon completion, the fd array will be populated with the list of file descriptors, and the numFD parameter will contain the actual count.

addFdChanged Callback

int addFdChangedCallback (cdevFdChangedCallback cbk,

void*userarg)

Adds a new function to be called each time a service announces to the system that it has opened or closed a file descriptor. The function will be called with 3 arguments:

void (*cdevFdChangedCallback) (int fd, int opened,

void *userarg)

The first argument specifies the file descriptor, the second is 1 for opened, 0 for closed, and the last argument is the user specified argument.

autoErrorOn

int autoErrorOn (void);

Informs the cdevSystem object that it should use its internal default error handler to process any error messages that are generated by objects within its control. This is the default operating condition for the cdevSystem object.

autoErrorOff

int autoErrorOff (void);

Informs the cdevSystem object that it should use the user supplied error handling function to process any error messages that are generated by objects within its control.

reportError

int reportError ( int severity, char *name,

cdevRequestObject *obj,

char *formatString,...);

Emits an error message. The severity field indicates the severity of the error, the name string identifies the object that generated the error, the obj parameter is the cdevRequestObject that was in use when the error occurred, and the formatString and additional parameters (...) should be formatted in the same manner as the parameters used by printf.

The integer used by severity should have one of the following values indicating the severity of the error that has occurred.

CDEV_SEVERITY_INFO:

No error.

CDEV_SEVERITY_WARN:

An error occurred that should not impact continued processing.

CDEV_SEVERITY_ERROR:

An error occurred and should be corrected before continuing.

CDEV_SEVERITY_SEVERE:

A severe or fatal error has occurred and CDEV cannot continue normal execution.

setErrorHandler

void setErrorHandler (cdevErrorHandler handler);

Used to to install a user specified error handler. This error handler will be called when an error occurs if the autoErrorOff method has been used to disable the default error handler. The user provided error handler should have the following prototype:

void handler (int severity, char *text, cdevRequestObject *obj);

The severity parameter will contain one of the integers specified in the reportError documentation, the text parameter will contain the text of the error, and the obj parameter will contain the cdevRequestObject that was in use when the error occurred.

setThreshold

void setThreshold (int errorThreshold);

Used to specify the level of severity at which errors should be submitted to the error handler. The value of errorThreshold should be one of the severity levels specified in the reportError method.

Sample Code

The following sample application shows the use of the three methods for obtain a cdevSystem object. For examples of how to use the flush, poll and pend methods, see the documentation for the cdevDevice object.

Figure 12: Methods for obtaining a cdevSystem object

#include <cdevSystem.h>
 
void main()
   {
   // ************************************************************
   // * The first and most common approach is to directly request
   // *   a reference to the default cdevSystem.
   // ************************************************************
   cdevSystem & default = cdevSystem::defaultSystem();
   
   // ************************************************************
   // * Get a pointer to the name of the default cdevSystem.
   // ************************************************************
   char * sysName = default.name();
 
   // ************************************************************
   // * Use the attachRef method to obtain a reference to the 
   // * default cdevSystem by name.
   // ************************************************************
   cdevSystem & default2 = cdevSystem::attachRef(sysName);
 
   // ************************************************************
   // * Finally, use the attachPtr method to obtain a pointer to
   // * the default cdevSystem by name.  Additionally, set the
   // * prefix for the default system to "TEST".
   // ************************************************************
   cdevSystem * default3 = cdevSystem::attachPtr(sysName, "TEST");
   
   // ************************************************************
   // * Output the name and prefix for all three systems.
   // ************************************************************
   printf("%s:%s\\n", default.name(), default.prefix());
   printf("%s:%s\\n", default1.name(), default1.prefix());   
   printf("%s:%s\\n", default2->name(), default2->prefix());
   }
			

The following sample application illustrates how to install a user specified error handler into the default cdevSystem object.

Figure 13: Installing a user specified error handler

#include <cdevSystem.h>
 
// ****************************************************************
// * This the default error handler.  It simply outputs the error.
// ****************************************************************
void myHandler(int severity, char *text, cdevRequestObject &obj)
   {
   if(severity>0)
      {
      fprintf(stderr, "ERROR (%i): %s\\n", severity, text);
      }   
   else    fprintf(INFORMATION: %s\\n", text);
   }
 
void main()
   {
   // ************************************************************
   // * Obtain a reference to the default cdevSystem.
   // ************************************************************
   cdevSystem & default = cdevSystem::defaultSystem();
   
   // ************************************************************
   // * Call the setErrorHandler method to install the new
   // * errorHandler.
   // ************************************************************
   default.setErrorHandler(myHandler);
 
   // ************************************************************
   // * Turn off auto error handling to tell the system to use
   // * the new user specified error handing function.
   // ************************************************************
   default.autoErrorOff();
   }
			

4.

Using the cdevDevice Object

Overview of the cdevDevice Class

The cdevDevice C++ class is the user's primary interface to CDEV. In fact, it is possible to develop complete CDEV applications using only cdevDevice and cdevData objects. The cdevDevice class defines the basic interface that all applications must use to transmit messages to a CDEV service.

A cdevDevice may be created using the static member functions attachPtr or attachRef. If one of these methods is used, the device will be created within the context of the default cdevSystem. If the application wishes to create a device within a cdevSystem other than the default, it must use the getDevice method of the desired cdevSystem object.

A cdevDevice object is bound by name to a specific device when it is instantiated. However, the underlying service is not selected until a message is specified with a send command. Therefore, simply creating a device does not ensure that the device name is valid, nor that it supports a given message.

Messages may be sent to a device using one of the three send member functions, these are: send, sendNoBlock, and sendCallback. The syntax and functionality of these methods is described in the section below.

Input and output to the specified send methods is managed through the use of cdevData objects. Unlike the cdevDevice object which is bound to a specific system, the cdevData object is completely independent. These objects store the data values (called properties) that are sent to and received from devices. The application may indicate the properties that it wishes to receive as output from the cdevDevice object by specifying them in a special cdevData object called the context.

Examples at the end of this section will illustrate the correct ways to implement these operations.

Public Functions of the cdevDevice Class

attachRef

static cdevDevice& attachRef (char *name);

Obtains a reference to a cdevDevice object by name. By default, the new object will be managed by the default cdevSystem.

attachPtr

static cdevDevice* attachPtr (char *name);

Obtains a pointer to a cdevDevice object specified by name. By default, the new object will be managed by the default cdevSystem.

detach

static void detach (cdevDevice& dev);

Removes a referenced cdevDevice object from its associated cdevSystem object. Ordinary applications should never use this command.

detach

static void detach (cdevDevice* dev);

Detaches the cdevDevice object specified by dev from its associated cdevSystem object. Ordinary applications should never use this command.

getRequestObject

cdevRequestObject* getRequestObject (char *msg);

Obtains a service specific request object. This function uses the name of the device specified within the cdevDevice object, and the message provided by the caller to determine which CDEV service will be used to service this request. The service is then loaded (if necessary), and is contacted to provided a request object for the device/message combination. This cdevRequestObject will then be used to communicate with the service directly.

name

const char *name (void) const;

Returns the name of the device.