6.1. Writing a Simple Application
This chapter offers advice and suggestions to guide programmers in designing and coding a Digital Network Interface application.
This chapter is not meant to be a comprehensive guide to developing or debugging Digital Network Interface applications. Instead, the following sections provide Digital Network Interface general and task-specific programming guidelines:
6.1.1. General GuidelinesThe following general guidelines for writing applications are explained in this section.
Use Symbolic DefinesDo not use a numerical value in your application when an equivalent symbolic define is available.
Include Header FilesVarious header files must be included in your application to test for error conditions, to use other library functions from this release or to perform event management and standard attribute functions. An example is shown below. See Section 4.3. Include Files, for details.
#include <windows.h> /* For Windows applications only */ #include <srllib.h> #include <dtilib.h> #include <errno.h>
Check Return CodesMost Digital Network Interface library functions return a value of -1 if they fail (extended attribute functions return AT_FAILURE or AT_FAILUREP if they fail). Any call to a Digital Network Interface library function should check for a return value indicating an error. This can be done using a format similar to the following:
/* call to Digital Network Interface library function */
if (dt_xxx(arguments) == -1) {
/* error handling routine */
}
/* successful function call -
continue processing ... */
Using this technique ensures that all errors resulting from a Digital Network Interface device library call will be trapped and handled properly by the application. In many cases, you can check for a return value of other than zero (0), as shown in the example below. However, this should only be used where a non-zero value is returned when the function fails. See Section 4.2. Error Handling, or Chapter 5. Function Reference, for function specific details.
.
.
.
/* error handling routine */
void do_error( devh, funcname )
int devh;
char *funcname;
{
int errorval = ATDV_LASTERR( devh );
printf( "Error while calling function %s on device %s. \n", funcname,
ATDV_NAMEP( devh ) );
if ( errorval == EDT_SYSTEM ) {
printf( "errno = %d\n", errno );
perror("");
} else {
printf( "Error value = %d\n Error message = %s\n",
errorval,ATDV_ERRMSGP( devh ) );
}
return;
}
main( )
{
.
.
.
/* call to DTI/xxx library function */
if (dt_setevtmsk( devh, DTG_SIGEVT, 0, DTA_SETMSK ) ) != 0) {
do_error( devh, "dt_setevtmsk()" );
}
/* successful function call -
continue processing ... */
.
.
.
}
The dtilib.h header file lists symbolic defines for the error.
6.1.2. InitializationBefore a Digital Network Interface application can perform any processing or access devices, it should initialize the Digital Network Interface hardware to reflect the physical configuration of your system and set other parameters needed to support the application. Tasks that are performed as a part of initialization generally include:
These involve the following Digital Network Interface device functions:
Set Hardware ConfigurationUse dt_setparm( ) to set hardware configuration, test mode, clock source, and network telephony parameters. Specific settings include:
For specific parameter or mask values to use for configuring your hardware, see the relevant function description(s) in Chapter 5. Function Reference.
Set Alarm Handling Parameters and MasksUse dt_setalrm( ) to set the alarm handling mode for each Digital Network Interface device. Recommended settings are shown in Table 7. See dt_setalrm( ) in Chapter 5. Function Reference for an example of setting the alarm handling mode.
Table 7. Recommended dt_setalrm( ) Settings
Telephony Standard |
Configuration |
Alarm Handling Mode |
T-1 |
terminate |
DTA_TERM |
drop and insert |
DTA_DROP | |
E-1 |
terminate |
DTA_TERM |
drop and insert |
DTA_TERM <check> |
Use dt_setevtmsk( ) to set the alarm handling masks for each Digital Network Interface device. At a minimum, your application must set masks to detect the T-1 or E-1 alarm conditions listed below.
T-1 alarm masks:
E-1 alarms:
Initialize Time SlotsBefore making or receiving any calls, an application should initialize all time slots to a known state. Initialization consists of:
Setting event masks to a known state helps ensure that the application receives only those events it "expects" and can handle appropriately. Use dt_setevtmsk( ) to set the signaling event masks to the desired state.
Setting all time slots to the idle state at the start of your application helps ensure that off-hook/on-hook transitions will be processed correctly. Use dt_settssig( ) to set the state of a time slot to idle.
To generate system signaling from the Digital Network Interface board, it must be in the signaling insertion mode. In this mode, signaling from a resource board, such as a D/300SC-E1, will be overwritten by the Digital Network Interface board.
Use dt_setidle( ) to idle a time slot.
The programming example below represents a typical initialization routine for a single time slot on a single board in a T-1 environment.
int init( )
{
int dti1;
/* open time slot 1 on D/240SC-T1 board 1 ("dti1") */
.
.
.
/* Set time slot "onhook" */
if ( dt_onhook ( dtiB1T1 ) !=0 ) {
do_error( dti1, "dt_onhook( ) " );
exit( 1 );
}
/* Reset all signaling event masks */
if ( dt_setevtmsk( dti1, DTG_SIGEVT, 0, DTA_SETMSK ) !=0 ) {
do_error( dti1, "dt_setevtmsk()" );
exit ( 1 );
}
}
int dt_onhook ( devh)
int devh;
{
int retval;
/*
* Transmit AOFF and BOFF
*/
if ( ( retval = dt_settssig( devh, DTB_ABIT | DTB_BBIT,
DTA_SUBMSK ) ) != 0 ) {
do_error( devh, "dt_settssig()");
return ( retval );
}
/*
* Set signaling mode to signaling insertion
*/
if ( ( retval = dt_setsigmod( devh, DTM_SIGINS ) ) != 0 ) {
do_error( devh, "dt_setsigmod()");
return ( retval );
}
/*
* Enable idle transmission
*/
if ( ( retval = dt_setidle( devh, DTIS_ENABLE ) ) != 0 ) {
do_error( devh, "dt_setidle()");
}
return ( retval );
}
The dt_setevtmsk( ) function disables generation of signaling events (see Appendix A - Standard Runtime Library or Chapter 5. Function Reference for details).
The dt_onhook( ) routine is a user-defined function that forces the selected time slot to the on-hook, idle state using three separate library functions.
The dt_setsigmod( ) function sets the time slot to signaling insertion mode. (This enables the device to transmit idle on the time slot without overriding signaling.)
The dt_settssig( ) function forces the time slot to the on-hook state.
The dt_setidle( ) function transmits an idle pattern to the network on the selected time slot.
6.1.3. ProcessingThe main processing tasks for a Digital Network Interface application involve:
Opening and Using Board and Time Slot DevicesBoth Linux and Windows open and close devices in the same manner that they open and close files. The operating systems view Digital Network Interface boards and time slot devices as special files. When you open a file, a unique file descriptor is returned for that file. For example:
int file_descriptor;
file_descriptor = open(filename,mode);
Any subsequent action you perform on that file is accomplished by identifying the file using file_descriptor. No action at all can be performed on the file until it is first opened. Devices work in a similar fashion. You must first open a device before you can perform an operation with it. When you open a device, the value returned is a unique handle for that process:
int device_handle;
device_handle = dt_open(device_name,mode);
The Digital Network Interface device driver treats time slot and logical board devices similarly. Each is referred to by using a device handle. Any time you want to use the device, you must identify the device with its handle. A time slot device is an individual T-1 or E-1 time slot; for example, 1 of the 30 time slots on a DTI/300SC. A DTI/300SC is one Digital Network Interface logical board device containing 30 time slot devices.
Follow the guidelines below when defining devices in the configuration file:
Valid device names for DTI devices are found in the /dev directory. For the DTI/xxx boards, the device name format is dtiBx or dtiBxTy, where:
Valid device names for the D/xxxSC boards are built from the board name specified in the configuration file. The name of the D/xxxSC device may be in the form dtiBx, dtiBx, dtiBxTy, or dtiBxTy where:
The following example shows how time slot 1 can be opened on two different D/240SC-T1 boards. For details on opening and closing devices, refer to dt_open( ) in Chapter 5. Function Reference.
int dti1;
int dti2;
/* Open device dtiB1T1 */
if ( ( dti1 = dt_open( "dtiB1T1", 0 ) ) == -1 ) {
printf( "Cannot open DTI device dtiB1T1\n" );
perror( " " );
exit ( 1 );
}
/* Open device dtiB2T1 */
if ( ( dti2 = dt_open( "dtiB2T1", 0 ) ) == -1 ) {
printf( "Cannot open DTI device dtiB2T1\n" );
perror( " " );
exit ( 1 );
}
Establishing ConnectionsThe examples below show how an incoming call can be established.
#include <windows.h> /* For Windows applications only */
#include <srllib.h>
#include <dtilib.h>
#include <errno.h>
int devh; /* Time slot device handle */
int retval; /* Function return value */
int AON_received = 0; /* AON_received flag */
int AON_handler( )
{
int event = sr_getevttype( );
int *datap = (int *)sr_getevtdatap( );
short indx;
if (event != DTEV_SIG) {
printf("Unknown event %d received. Data = %d\n",event,*datap);
return 0;
}
for (indx = 0; indx < 4; indx++) {
/*
* Check if bit in change mask (upper nibble - lower byte) is
* set or if this is a WINK (upper nibble - upper byte) event
*/
if (!(*datap & (0x1010 << indx))) {
continue;
}
switch (*datap & (0x1111 << indx)) {
case DTMM_AON:
AON_received = 1;
break;
.
.
.
default:
printf(Signal Event Error: Data = %d\n,*datap);
}
}
return 0;
}
int wait_ring()
{
/*
* This routine waits for an event from AON_handler to signal
* an incoming call
*/
int devh; /* Time slot device handle */
/*
* Open board 1 time slot 1 device (dti1)
*/
if ( ( devh = dt_open( "dtiB1T1", 0 ) ) == -1 ) {
printf( "Cannot open device dtiB1T1. errno = %d", errno );
return ( -1 );
}
/*
* Enable event handler to catch AON events
*/
if ( ( retval = sr_enbhdlr( devh, DTEV_SIG, AON_handler ) ) == -1 ) {
printf( "Unable to set AON handler for device %s",
ATDV_NAMEP ( devh ) );
return( retval );
}
/*
* Enable AON signaling transition events
*/
if ( ( retval = dt_setevtmsk( devh, DTG_SIGEVT, DTMM_AON,
DTA_SETMSK ) ) == -1 ) {
printf ( "Error message = %s.", ATDV_ERRMSGP( devh ) );
return ( retval );
}
/*
* Now wait for an incoming call
*/
while( AON_received == 0 ) {
sleep( -1 ); /* Sleep until we receive an incoming call */
}
/* We have received an incoming call. See next segment. */
.
.
.
}
The AON_handler( ) routine is an asynchronous event handler that flags transitions of signaling bit "A" to the ON state. When the system detects an A-ON condition, AON_handler( ) sets the AON_received flag to 1. The AON_handler( ) function uses the SRL sr_enbhdlr( ) function and related event management functions to determine when a signaling transition occurs. For details, see Appendix A - Standard Runtime Library.
The wait_ring( ) routine is a user-defined function that performs the following tasks:
The dt_open( ) function opens time slot 1 on Digital Network Interface board 1 and assigns the returned device handle to variable devh.
The SRL sr_enbhdlr( ) function enables processing by the AON_handler function of any signaling events detected on the device represented by devh (for details see Appendix A - Standard Runtime Library).
The dt_setevtmsk( ) function enables detection of signaling bit A-ON transitions on device devh. Using E&M (Ear and Mouth) signaling protocol, a transition of the A-bit from OFF to ON signifies a request for service or ring event. When enabling event notification, the dt_setevtmsk( ) function should be invoked only after the applicable handler has been enabled; otherwise, events could be missed. In the previous example, the AON_handler( ) function was used.
The while statement puts the routine to sleep until the AON_handler routine detects a ring event. When a ring event is detected, processing resumes with the following segment.
/*
* Continued from previous example
*/
.
.
int dt_offhook ( devh)
int devh;
{
int retval;
/*
* Transmit AON and BON
*/
if ( ( retval = dt_settssig( devh, DTB_ABIT | DTB_BBIT,
DTA_ADDMSK ) ) != 0 ) {
do_error( devh, "dt_settssig()" );
return ( retval );
}
/*
* Set signaling mode to signaling insertion
*/
if ( ( retval = dt_setsigmod( devh, DTM_SIGINS ) ) != 0 ) {
do_error( devh, "dt_setsigmod()";
return ( retval );
}
/*
* Disable idle transmission
*/
if ( ( retval = dt_setidle( devh, DTIS_DISABLE ) ) != 0 ) {
do_error( devh, "dt_setidle()" );
}
return ( retval );
}
The dt_offhook( ) routine is a user-defined function that forces the selected time slot to the off-hook state and disables the transmission of idle using three separate library functions.
The dt_setsigmod( ) function sets the time slot to signaling insertion mode.
The dt_settssig( ) function forces the time slot to the off-hook state.
The dt_setidle( ) function disables the transmission of the idle pattern to the network on the selected time slot.
6.1.4. TerminatingWhen your process completes, devices should be shut down in an orderly fashion. Tasks that are performed to terminate an application generally include:
The example that follows is based in part on the processes illustrated in the previous examples. When your application is done processing a call, the following example should be executed.
/* Disable all signaling events for this time slot */
if ( dt_setevtmsk( dti1, DTG_SIGEVT, 0, DTA_SETMSK) != 0 ) {
do_error( dti1, "dt_setevtmsk()" ); /* Error function */
}
/*
* Disable event handler for AON events
*/
if ( ( retval = sr_dishdlr( devh, DTEV_SIG, AON_handler ) ) == -1 ) {
printf( "Unable to disable AON handler for device %s",
ATDV_NAMEP ( devh ) );
return( retval );
}
/*
* close time slot 1 on Digital Network Interface board 1 ("dti1") and Digital Network Interface board2 ("dti2")
*/
if ( dt_close( dti1 ) != 0 ) {
do_error( dti1, "dt_close()" );
}
if ( dt_close( dti2 ) != 0 ) {
do_error( dti2, "dt_close()" );
}
The dt_setevtmsk( ) function disables all currently enabled event notification masks. The routine that follows uses SRL functions (not illustrated) to disable all signal handlers (for SRL details, see Appendix A - Standard Runtime Library).
The dt_onhook( ) routine is a user-defined function that forces the selected time slot back to the on-hook, idle state using three separate library functions.
The dt_setsigmod( ) function resets the time slot device to signaling insertion mode.
The dt_settssig( ) function sets the time slot device to the on-hook state, ready for another call.
The dt_setidle( ) function transmits idle on the selected time slot. When two Digital Network Interface boards are arranged in drop-and-insert configuration, dt_setidle( ) can be used to disable pass-through operation. Transmitting idle overrides voice data being passed between network devices on the selected time slot(s).
The dt_close( ) function closes the time slot device.
6.1.5. Compiling and LinkingTo compile and link your application, follow the syntax instructions for your version of the C Development Package.
-l dti -l dxxx -l srl
or
-l dxxx -l dti -l srl
6.1.6. AbortingIf you abort a Digital Network Interface application by pressing the interrupt key, the system will terminate the current process but may leave devices in an unknown state. The next time you run your application, therefore, you may encounter errors.
To avoid errors of this type, your application should include an event handler that traps the interrupt key and performs the actions discussed under Section 6.1.4. Terminating.
Click here to contact Dialogic Customer Engineering
Copyright 2001, Dialogic Corporation