# Setting up the Natural Access environment

Before calling functions from the NaturalFax library, complete the following steps to set up the Natural Access environment:

Step | Action
1 | Initialize NaturalFax.
2 | Create event queues and contexts.
3 | Open services on each context .

Each of these steps is described in the following sections. For general information on setting up the Natural Access environment, refer to the Natural Access Developer's Reference Manual.

## Initializing NaturalFax

Use the ctaInitialize Natural Access function to initialize NaturalFax and register the services available to the application. If ctdaemon is running, all services defined in cta.cfg are automatically registered when you invoke ctaInitialize.

If ctdaemon is not running, you must explicitly define the services and service managers in the call to ctaInitialize, as shown in the following code sample:

static DWORD initialize_base (void)
{
CTA_SERVICE_NAME init_services [] =
{
{ "NCC", "ADIMGR" },
{ "ADI", "ADIMGR" },
{ "FXM", "ADIMGR" },
/* { "ADI", "QDIMGR" }, for QX 2000 boards */
/* { "FXM", "QDIMGR" }, for QX 2000 boards */
{ "FAX", "FAXMGR" },
{ "NFX", "NFXMGR" },
};
CTA_INIT_PARMS init_parms =
{
sizeof (CTA_INIT_PARMS),
};
DWORD status;
static int initialized = 0;
if (initialized)
return SUCCESS;
status = ctaInitialize (init_services,
sizeof init_services / sizeof init_services [0],
& init_parms);
if (status != SUCCESS)
show_error (NULL_CTAHD, status, "Natural Access initialization
failed");
else
initialized = 1;
return status;
}

Refer to Modifying the Natural Access configuration file for a list of NaturalFax services.

## Creating event queues and contexts

After initializing NaturalFax, complete the following steps to create the event queues and contexts:

Step | Action
1 | Create one or more event queues by calling ctaCreateQueue and specifying the service managers to attach to each queue. Attaching or binding a service manager to a queue makes that service manager available to the queue. A NaturalFax application uses the following service managers:
Service manager | Service
--- | ---
ADIMGR (QDIMGR for QX 2000 boards) | NCC
ADIMGR (QDIMGR for QX 2000 boards) | FXM
NFXMGR | NFX
FAXMGR | FAX
2 | Create a context by calling ctaCreateContext, passing the queue handle (ctaqueuehd) returned from ctaCreateQueue. All events for services on the context are received in the specified event queue. ctaCreateContext returns a context handle (ctahd). The application supplies the context handle when invoking NaturalFax functions. Events communicated back to the application are also associated with the context.

Refer to the Natural Access Developer's Reference Manual for details on the programming models created by the use of Natural Access contexts and queues.

## Opening services

Opening a service on a context creates a service instance that defines a service and its associated resources (for example, MVIP
board, stream
, and timeslot
). The context is a bound collection of service instances. A fax application usually opens the NFX, FAX, FXM, ADI, and NCC services on each individual context. Each context must specify the same board and MVIP address for the ADI and FXM service instances bound to it.

To open services on a context, call ctaOpenServices and pass a context handle and a list of service descriptor structures, one for each service. The service descriptor structure, CTA_SERVICE_DESC, contains the CTA_SERVICE_NAME, CTA_SERVICE_ADDR, CTA_SERVICE_ARGS, and CTA_MVIP_ADDR substructures, which provide the name of the service, its service manager, and service-specific arguments.

An application must open the NCC service to place or receive calls. The application must assign hardware resources to the service by filling in the board, bus, stream, timeslot, and mode fields in the CTA_MVIP_ADDR substructure. To ensure that the context is able to transmit and receive voice and signaling data, use ADI_FULL_DUPLEX mode.

The Fax Manager (FXM) service must use service-specific arguments to identify its hardware resources, because it provides the hardware interface for the NaturalFax service. When an application opens the FXM service, it must fill in the board, bus, stream, timeslot, and mode fields in the CTA_MVIP_ADDR substructure.

The NaturalFax (NFX) and Fax (FAX) services do not require any service-specific arguments. The NFX and FAX services use the same hardware resources specified by the FXM service opened on the same context.

The following code sample demonstrates creating a context and opening the ADI, NCC, FXM, FAX, and NFX services:

static DWORD create_context (CTAQUEUEHD queue,
DWORD board,
DWORD stream,
DWORD timeslot,
DWORD closure,
char * contextname,
CTAHD * contextptr)
{
DWORD status;
CTA_SERVICE_DESC services [4];
DWORD service_count = 0;
CTA_EVENT event;
status = ctaCreateContext (queue, closure, contextname, contextptr);
if (status != SUCCESS)
{
show_error (NULL_CTAHD, status, "Natural Access context creation
failed");
return status;
}
/*
* Now that we have a valid context, we can use
* ctaGetText to get proper error messages.
*/
memset (& services, 0, sizeof services);
services[service_count].name.svcname = "ADI";
services[service_count].name.svcmgrname = "ADIMGR";
/* for QX 2000 boards, use QDIMGR instead of ADIMGR */
services[service_count].mvipaddr.board = board;
services[service_count].mvipaddr.stream = stream;
services[service_count].mvipaddr.timeslot = timeslot;
services[service_count].mvipaddr.mode = ADI_FULL_DUPLEX;
service_count += 1;
services[service_count].name.svcname = "NCC";
services[service_count].name.svcmgrname = "ADIMGR";
/* for QX 2000 boards, use QDIMGR instead of ADIMGR */
services[service_count].mvipaddr.board = board;
services[service_count].mvipaddr.stream = stream;
services[service_count].mvipaddr.timeslot = timeslot;
services[service_count].mvipaddr.mode = ADI_FULL_DUPLEX;
service_count += 1;
services[service_count].name.svcname = "FXM";
services[service_count].name.svcmgrname = "ADIMGR";
/* for QX 2000 boards, use QDIMGR instead of ADIMGR */
services[service_count].mvipaddr.board = board;
services[service_count].mvipaddr.stream = stream;
services[service_count].mvipaddr.timeslot = timeslot;
services[service_count].mvipaddr.mode = ADI_FULL_DUPLEX;
service_count += 1;
/*
* Specific MVIP_ADDR field assignments for the FXM, FAX, and NFX
* services are ignored; these services use the MVIP_ADDR data that was
* passed to the ADI service.
*/
services[service_count].name.svcname = "FAX";
services[service_count].name.svcmgrname = "FAXMGR";
services[service_count].mvipaddr.board = board;
services[service_count].mvipaddr.stream = stream;
services[service_count].mvipaddr.timeslot = timeslot;
services[service_count].mvipaddr.mode = ADI_FULL_DUPLEX;
service_count += 1;
services[service_count].name.svcname = "NFX";
services[service_count].name.svcmgrname = "NFXMGR";
services[service_count].mvipaddr.board = board;
services[service_count].mvipaddr.stream = stream;
services[service_count].mvipaddr.timeslot = timeslot;
services[service_count].mvipaddr.mode = ADI_FULL_DUPLEX;
service_count += 1;
status = ctaOpenServices (* contextptr, services, service_count);
if (status != SUCCESS)
{
show_error (* contextptr, status, "open services failed");
return status;
}
/* Now we need to wait for the CTAEVN_OPEN_SERVICES_DONE event. */
status = wait_event (queue, * contextptr, CTAEVN_OPEN_SERVICES_DONE,
NULL, 0, & event);
if (status != SUCCESS)
{
show_error (* contextptr, status, "open services failed");
return status;
}
else if (event.value != CTA_REASON_FINISHED)
{
show_error (* contextptr, event.value, "open services done event");
return event.value;
}
else
return SUCCESS;
}