Implementation Steps

You can create a custom driver for the SmartServer to provide support for additional protocols not built into the standard SmartServer software.  To develop a custom driver, you implement your driver-specific code in C or C++ using the GNU C++ compiler (g++) and link your driver with the IAP Driver Library (IDL) that is included with the SmartServer.  This page outlines the basic steps required to implement an IDL driver, with specific references to the IDL API.  The other pages in this section walk through an example implementation and the sample code in some detail and include specifics on compiling, running, and debugging an example driver. 

The basic architecture for a custom driver is illustrated in the following flowchart:

Step 1 – Create a New Custom Driver Instance

Create a new IDI instance.  You will reference this instance throughout the custom driver code.  For example, you will reference this instance when initializing the driver or registering callback functions.  For reference refer to the IdlNew() function described in the Init Functions section in the IDL API.  The IdlNew() function returns a pointer to the newly created driver instance, which is then referenced when interacting with IDL.

Step 2 – Register any Supported Callback Routines with the IAP Driver Library (IDL)

Register any supported callback functions with IDL.  The driver library calls these callback functions as necessary when actions that must be executed by the custom driver code occur.  This includes things such as creating a new device that uses this protocol, provisioning / de-provisioning a device, reading & writing data points, and so on.  Registering a callback routine with the library requires calling the appropriate callback set function and providing the previously created driver instance as a parameter, as well as a pointer to the custom driver’s routine that is to be executed when the associated event occurs.

For example, if your custom driver code implements the code to handle the creation of a new device that uses this driver, you might have a function like this:

int dev_create_cb(int request_index, IdlDev *dev, char *args, char *xif_dp_array);

You can register this callback routine with IDL by calling the device create callback set function described in the API section and pass a reference to your routine:

IdlDevCreateCallbackSet(idl, dev_create_cb);

A complete list of the supported callback routines are documented in the IDL API.  In addition, the example in Init Functions, includes reference code showing how to register the callback functions with the IDL, and the provided example driver code illustrates this as well.

Step 3 – Start up any Driver Specific Code, IdiStart()

Start up any driver-specific code that is required for this custom driver instance to operate.  For example, your custom driver might need to open and initialize a serial port or a USB interface as well as initialize any driver-specific constructs.  The example driver described below implements a stub function that illustrates this activity.  As shown in the flowchart, if the custom driver successfully initializes anything it needs to start up, the driver code is then free to create any threads required and to initialize the driver instance itself.

Step 4 – Create any Threads the Custom Driver Might Require

Since initializing the IDL driver instance surrenders the execution thread to IDL, if a custom driver needs any independent Linux POSIX threads to handle any background processes the driver needs to execute, these threads should be created before calling IdiInit() to start up the custom driver instance.  For example, if my driver needed an independent thread to handle incoming, asynchronous protocol packets, you can use the Linux POSIX pthread library to create a thread for this purpose:

pthread_create( &ExampleRxThread, NULL, ExampleRxFunction, NULL);

The example IDL driver includes example code that implements this approach and details can be found in the sections that follow.

Step 5 – Initialize the Driver Instance

Iinitialize the driver instance itself that was created in Step 1.  Initializing the driver instance involves calling the IdlInit() function and passing a reference to the instance, as well as a configuration file that provides IDL important startup information about your custom driver.  Reference code is included in the example IDL driver outlined in the sections that follow.  Details concerning the IdlInit() call and the associated parameters is documented in the Init Functions section.  In addition, the configuration file passed to the IdlInit() function is documented in Conf File section.

Step 6 – Callback Functions

The bulk of the code contained within a custom driver will often be found in the callback functions themselves.  This is where driver specific code that needs to execute based on activities like provisioning a device or reading a data point will be located.  The IDL API documentation section contains complete details on these various callback functions and the example IDL driver includes actual reference code that implements these common callback functions.  For example, if your custom driver needs to implement code to handle creating a device, the device create function, the associated callback function, and the required return call are documented together in the Device Create Functions section.