Initializing the MTP 3 service under Natural Access

MTP 3 data functions are implemented as a Natural Access service. Natural Access is a development environment for telephony and signaling applications that provides a standard application programming interface for services, such as signaling protocol stacks, independent of the underlying hardware.

Natural Access is described in detail in the Natural Access Developer's Reference Manual. Understanding the basic Natural Access programming concepts, including services, queues, contexts, and asynchronous events, is critical to developing applications that utilize the MTP 3 service.

Before calling any MTP 3 service functions, the application must first:

  1. Initialize the Natural Access run-time environment.

  2. Create the desired queues and contexts.

  3. Open the MTP 3 service to bind itself to the desired MTP 3 SAPs.

Initializing the Natural Access environment

Initialize the Natural Access environment by calling ctaInitialize once per application, regardless of the number of queues and contexts to be created:

CTA_INIT_PARMS      mtp3Initparms       = {0};
CTA_SERVICE_NAME    mtp3ServiceNames[]  = {{"MTP3", "MTP3MGR"}};
...
mtp3Initparms.size              = sizeof(CTA_INIT_PARMS);
mtp3Initparms.traceflags        = CTA_TRACE_ENABLE;
mtp3Initparms.parmflags         = CTA_PARM_MGMT_SHARED;
mtp3Initparms.ctacompatlevel    = CTA_COMPATLEVEL;

Ret = ctaInitialize(mtp3ServiceNames, 1, &mtp3Initparms);
if (Ret != SUCCESS)
{
    printf("ERROR code 0x%08x initializing Natural Access.", Ret);
    exit( 1 );
}

Creating queues and contexts

The application creates the required Natural Access queues and contexts, as described in Contexts and queues. The queue must always be created before any context associated with it.

CTAHD       ctaHd;                  /* CTA context handle */
CTAQUEUEHD  ctaQueue;               /* Queue */
...

Ret = ctaCreateQueue( NULL, 0, &ctaQueue );
if ( Ret != SUCCESS )
{
     ctaGetText( NULL_CTAHD, Ret, sErr, sizeof( sErr ) );
     printf( "*ERROR : ctaCreateQueue failed( %s )\n", sErr );
     ...
}

sprintf( contextName, "Mtp3SAP-%d", spId ); /* context name is optional */

Ret = ctaCreateContext( ctaQueue, spId, contextName, &ctaHd );
if ( Ret != SUCCESS )
{
     ctaGetText( NULL_CTAHD, Ret, sErr, sizeof( sErr ) );
     printf( "ERROR : ctaCreateContext failed( %s )\n", sErr );
     ctaDestroyQueue( pSap->ctaQueue );
     ...
}

Using ctaOpenServices

After the queues and contexts are created, the application must bind itself to each desired MTP 3 user SAP by calling ctaOpenServices once for each binding. The binding operation specifies the following parameters:

Parameter

Description

board

TX board number.

srvInfo

Service information octet.

sapId

MTP 3 NSAP ID (defined in configuration) on which to bind. This parameter must be passed in all functions that make requests to the board.

srcEnt

Calling application entity ID.

srcInst

Calling application instance ID.

suId

Calling application service user ID. This parameter is passed up in future indications from the board.

poolsize

Number of messages allowed to be queued to the TX board. Default value is 256.


Under Natural Access, these parameters are specified in the CTA_SERVICE_ARGS structure, contained in the CTA_SERVICE_DESC structure. An example of the parameter specification is provided:

CTA_SERVICE_DESC mtp3OpenSvcLst[] = {{{"MTP3","MTP3MGR"}, {0}, {0}, {0}}};

mtp3OpenSvcLst[0].svcargs.args[0] = Board;     /* board number          */
mtp3OpenSvcLst[0].svcargs.args[1] = Sio;       /* Service Information
                                                * Octet                 */
mtp3OpenSvcLst[0].svcargs.args[2] = NSapNmb;   /* network SAP number    */
mtp3OpenSvcLst[0].svcargs.args[3] = MyEnt;     /* application entity ID */
mtp3OpenSvcLst[0].svcargs.args[4] = DFLT_INST; /* Inst ID               */
mtp3OpenSvcLst[0].svcargs.args[5] = SuId;      /* Service user ID       */
mtp3OpenSvcLst[0].svcargs.args[6] = poolsize;  /* Pool size             */

ctaOpenServices is an asynchronous function. The return from the function indicates that the bind operation was initiated. Once completed, a CTAEVN_OPEN_SERVICES_DONE event is returned to the application.

If multiple contexts are assigned to the same queue, all of those contexts must use the same entity ID in the service arguments parameter. Conversely, contexts bound to different queues must specify unique entity IDs.

CTA_EVENT   event;    /* Event structure to wait for MTP3 events */
...


Ret = ctaOpenServices( ctaHd, mtp3OpenSvcLst, 1 );
if ( Ret != SUCCESS )
{
    ctaGetText( NULL_CTAHD, Ret, sErr, sizeof( sErr ) );
    printf( "ERROR : ctaOpenServices failed( %s )\n", sErr );
    ctaDestroyQueue( ctaQueue );  /* destroys context too */
    return(...)
}

/* Wait for "open services" to complete; note: this loop 
 * assumes no other contexts are already active on the queue
 * we're waiting on, so no other events will be received that
 * need handling
 */
event.id = CTAEVN_NULL_EVENT;
do
{
    ctaWaitEvent( ctaQueue, &event, 5000 );
}
while( (event.id != CTAEVN_OPEN_SERVICES_DONE) &&
       (event.id != CTAEVN_WAIT_TIMEOUT) );

/* check if binding succeeded */
if( (pSap->event.id != CTAEVN_OPEN_SERVICES_DONE) ||
    (pSap->event.value != CTA_REASON_FINISHED) )
{
    ctaGetText( event.ctahd, event.value, sErr, sizeof( sErr ) );
    printf( "ERROR opening MTP3 service [%s]\n", sErr );
    ctaDestroyQueue( pSap->ctaQueue );    /* destroys context too */
    return( ... );
}

This example is correct only if the application uses a separate queue for each context and service instance. If the application opens multiple service instances against the same queue, with either multiple SAPs on the same board or on multiple boards (in a redundant configuration), it must process events (call MTP3RetrieveMessage) for other contexts while waiting for the CTAEVN_OPEN_SERVICES_DONE event. Failure to do so can result in an infinite loop.