# Specifying supplementary services

To specify supplementary services, the application performs the following tasks:

1. It finds the beginning of the extended data area of the ACU message buffer.

2. In this area, it fills the structure for a supplementary service.

3. It finds the end of the structure just filled, adds another supplementary service substructure if necessary, and so on.

Most of these tasks are performed using specific macros and pointers. These tasks are listed in the following sections. A sample code fragment showing how to create a supplementary service specification is also included.

## Initializing the extended data area

To begin specifying supplementary services, the application finds the end of the fixed and variable-length argument areas of the ACU message buffer, and sets a specific pointer there. The following table lists the pointers and macros used for these tasks:

Macro | Description
--- | ---
Acu_ext_descr_offset | Must be sent to indicate the beginning of the extended data area of the ACU message buffer. Assumes that a pointer, p_data, points to the first data character of the ACU message buffer.
Acu_xxxx_yy_start_ext_data | Indicates the offset to the first byte of the extended data area for message xxxx_yy. xxxx_yy is the name of an ACU message primitive minus the ACU_ prefix, in lowercase such as conn_rq and facility_rq. For example: Acu_conn_rq_start_ext_data
p_ext_data | Pointer to the beginning of the extended data structure currently being filled.

To initialize the extended data area:

Step | Action
1 | The application completes the construction of the fixed and variable length argument areas of the ACU data buffer. The NMS ISDN Messaging API Developer's Reference Manual describes how to do this. The extended data area can be filled only when the rest of the ACU data buffer has been completed. If you are building a Q.SIG application, the PINX node address is specified in your initial call to isdnStartProtocol. For more information, see Specifying the Q.SIG node address.
2 | The application declares the p_ext_data pointer. This pointer will indicate the beginning of the extended data structure currently being filled. unsigned char *p_ext_data;
3 | The application sets the Acu_facility_code macro to ACU_FAC_EXT_SERVICE to indicate that the extended data area is to be used (if the supplementary service specification is to be sent with an ACU_FACILITY_RQ primitive).This macro does not need to be set if any other ACU primitive is used. Acu_facility_code = ACU_FAC_EXT_SERVICE;
4 | The application sets the Acu_ext_descr_offset macro to indicate the beginning of the extended data area of the buffer. Each fixed data structure contains a macro that specifies the start of the extended data area. Acu_ext_descr_offset = Acu_facility_rq_start_ext_data; Note: These macros assume that a pointer, p_data, points to the first character of the buffer.

When these tasks are complete, the application can begin filling extended data structures and adding them to this area, one after the other.

## Filling extended data structures

To fill in an extended data structure for a supplementary service, the application first fills in the structure's service header, identifying the structure as a supplementary service structure and specifying the type and operation of the service. It then fills the data structure for the service.

If additional data structures are required (for example, the application is specifying more than one supplementary service in the message), the pointer p_ext_data is set to the end of the structure just filled, and a new one is added. The macro Acu_ext_ss_build_end facilitates this procedure.

The following table lists the macros used for these tasks:

Macro | Description
--- | ---
Acu_ext_ss_build_begin(opid, optype) | Initializes a new supplementary service data structure. Sets p_ext_data to the beginning of the extended data structure, and stores the service operation type and id in the service structure header. opid is one of the operation IDs listed in Operation ID, and optype is one of the operation type identifiers listed in Operation type identifier.
Acu_ext_ss_build_end (p_end) | Called to indicate that building of an extended data structure is complete. p_end is a pointer to the byte after the last byte of the current extended data structure. If this structure includes variable-length data, p_end points to the first byte after the last data element. This macro calculates the length of the extended data area and of the new supplementary service structure and stores these values in the header. It also counts the number of supplementary service structures in this specification and stores this value in the header.

To fill an extended data structure for a supplementary service:

Step | Action
1 | The application calls the macro Acu_ext_ss_build_begin(opid, optype) to initialize a new supplementary service data structure. (opid is one of the operation IDs listed in Operation ID and optype is one of the operation type identifiers listed in Operation type identifier.) Acu_ext_ss_build_begin(ACU_OP_ID_DEFLECTION,ACU_OP_TYPE_INVOKE); The macro sets p_ext_data to the beginning of the extended data structure, and stores the service operation type and ID in the service structure header.
2 | The application sets a pointer to the appropriate data structure so it equals p_ext_data. For example, for a call deflection invocation operation, the application uses the acu_ss_deflect_invoke data structure (defined in isdnacu.h): struct acu_ss_deflect_invoke { struct acu_ext_hdr ext_hdr; /*Extension header */ struct acu_ss_hdr ss_hdr; /*Supp. services header*/ struct acu_address deflect_to; /*No. to direct call to*/ struct acu_ss_association charge_association;/*Optional, used when */ }; /*AOC-E service has been invoked*/ The following line shows how the application sets a pointer to this data structure: DeflectInvoke = (struct acu_ss_deflect_invoke *)p_ext_data; Note: If any optional strings are added, p_end must be adjusted for that string length.
3 | The application now fills the extended data structure for the service. The extended data structure for each operation ID/operation type combination is listed in Supplementary service extended data structures.
4 | The application calculates the end of the supplementary services data structure. p_end += sizeof(struct acu_ss_deflect_invoke);
5 | The application calls Acu_ext_ss_build_end to indicate that the data structure is built: Acu_ext_ss_build_end (p_end); p_end is a pointer to the byte after the last byte of the current extended data structure. If this structure includes variable-length data, p_end points to the first byte after the last data element. This macro calculates the length of the extended data area and of the new supplementary service structure and stores these values in the header. It also counts the number of supplementary service structures in this specification, and stores this value in the header.
6 | If there are additional supplementary service data structures to be added, steps 1 through 5 are repeated for each one.

## Supplementary service specification code sample

The following code fragment shows how to create a supplementary service specification:

char *number;
unsigned char *p_end;
unsigned char *p_ext_data;
unsigned char JoinedConnID;
struct acu_facility *p_data;
struct acu_ss_notify_transfer_invoke *NotifyTransfer;
/* Fill in the fixed portion of the facility message */
p_data = (struct acu_facility *)MsgBuffer; /* Initialize p_data */
/* First zero out the entire buffer */
memset(p_data, OFF, ISDN_BUFFER_DATA_LGTH); /* Zero the structure */
/* Tell the stack we are using supplementary services. Needed only if */
/* supp. service is sent in ACU_FACILITY_RQ. */
Acu_facility_code = ACU_FAC_EXT_SERVICE; /* Supp. service */
/* There is no more to do in the fixed structure except fill in header */
Acu_ext_descr_offset = Acu_facility_start_ext_data;
/* Start supplementary service extended data structure, to invoke */
/* Notify Transfer supplementary service */
Acu_ext_ss_build_begin(ACU_OP_ID_NOTIFY_TRANSFER,ACU_OP_TYPE_INVOKE);
/* Set the structure pointer... */
NotifyTransfer = (struct acu_ss_notify_transfer_invoke *)p_ext_data;
/* Calculate the address of where the data will go... */
p_end += sizeof(struct acu_ss_notify_transfer_invoke);
/* FILL IN THE EXTENDED DATA STRUCTURE... */
/* Some data fields follow */
NotifyTransfer->charge_id.invoke = 0;
NotifyTransfer->call_status = ACU_SS_CALL_STATUS_ANSWERED;
NotifyTransfer->end_designation = ACU_SS_END_DESIGNATION_PRIMARY;
/* Redirecting number information */
NotifyTransfer->redir_nb.invoke = 1;
NotifyTransfer->redir_nb.presentation_restricted = 0;
NotifyTransfer->redir_nb.number_plan =
ACU_SS_NUMBER_PLAN_PRIVATE_LEVEL_1_REGIONAL;
NotifyTransfer->redir_nb.screen_ind = ACU_SS_SCREEN_USER_PROV_VERIFIED;
/* Copy in a number to the data area */
number = "1234567"; /* Dummy data */
/*Calculate offset, store length, store the data, advance the pointer */
NotifyTransfer->redir_nb.offset =
(unsigned char)(p_end - (unsigned char*)&NotifyTransfer->redir_nb);
NotifyTransfer->redir_nb.len = strlen(number); /* Length of data */
strcpy((char *)p_end, number); /* Copy extended data */
p_end += strlen(number);
NotifyTransfer->joined_conn_id.board = BoardNumber;
NotifyTransfer->joined_conn_id.nai = NAI;
NotifyTransfer->joined_conn_id.conn_num = JoinedConnID;
/* Field not used in this direction... */
NotifyTransfer->response_rq = 0;
/* No sub-address information. */
NotifyTransfer->redir_sub.invoke = 0;
NotifyTransfer->redir_sub.pad = 0;
NotifyTransfer->redir_sub.type = 0;
NotifyTransfer->redir_sub.odd_even_ind = 0;
NotifyTransfer->redir_sub.offset = 0;
NotifyTransfer->redir_sub.len = 0;
/* Finished with this supp. service */
Acu_ext_ss_build_end(p_end)